Skip to content

Commit 5b4745e

Browse files
author
Tao Bai
committed
Implement Crash Handle API
This patch implements basical feature for crash handle API. The feature like 'render processs keep crashing after crash is handled' hasn't implemented. BUG=666106 Review-Url: https://codereview.chromium.org/2630473004 Cr-Commit-Position: refs/heads/master@{#445256} (cherry picked from commit 6e10ee5) Review-Url: https://codereview.chromium.org/2651743006 . Cr-Commit-Position: refs/branch-heads/2987@{#52} Cr-Branched-From: ad51088-refs/heads/master@{#444943}
1 parent 9329198 commit 5b4745e

File tree

7 files changed

+152
-8
lines changed

7 files changed

+152
-8
lines changed

android_webview/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ source_set("common") {
350350
"browser/aw_quota_manager_bridge.h",
351351
"browser/aw_quota_permission_context.cc",
352352
"browser/aw_quota_permission_context.h",
353+
"browser/aw_render_process_gone_delegate.h",
353354
"browser/aw_render_thread_context_provider.cc",
354355
"browser/aw_render_thread_context_provider.h",
355356
"browser/aw_resource_context.cc",

android_webview/browser/aw_browser_terminator.cc

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <unistd.h>
88

9+
#include "android_webview/browser/aw_render_process_gone_delegate.h"
910
#include "android_webview/common/aw_descriptors.h"
1011
#include "android_webview/common/crash_reporter/aw_microdump_crash_reporter.h"
1112
#include "base/bind.h"
@@ -17,11 +18,64 @@
1718
#include "content/public/browser/notification_service.h"
1819
#include "content/public/browser/notification_types.h"
1920
#include "content/public/browser/render_process_host.h"
21+
#include "content/public/browser/render_view_host.h"
22+
#include "content/public/browser/render_widget_host.h"
23+
#include "content/public/browser/render_widget_host_iterator.h"
24+
#include "content/public/browser/web_contents.h"
2025

2126
using content::BrowserThread;
2227

2328
namespace android_webview {
2429

30+
namespace {
31+
32+
void GetAwRenderProcessGoneDelegatesForRenderProcess(
33+
int render_process_id,
34+
std::vector<AwRenderProcessGoneDelegate*>* delegates) {
35+
content::RenderProcessHost* rph =
36+
content::RenderProcessHost::FromID(render_process_id);
37+
if (!rph)
38+
return;
39+
40+
std::unique_ptr<content::RenderWidgetHostIterator> widgets(
41+
content::RenderWidgetHost::GetRenderWidgetHosts());
42+
while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
43+
content::RenderViewHost* view = content::RenderViewHost::From(widget);
44+
if (view && rph == view->GetProcess()) {
45+
content::WebContents* wc = content::WebContents::FromRenderViewHost(view);
46+
if (wc) {
47+
AwRenderProcessGoneDelegate* delegate =
48+
AwRenderProcessGoneDelegate::FromWebContents(wc);
49+
if (delegate)
50+
delegates->push_back(delegate);
51+
}
52+
}
53+
}
54+
}
55+
56+
void OnRenderProcessGone(int child_process_id) {
57+
DCHECK_CURRENTLY_ON(BrowserThread::UI);
58+
std::vector<AwRenderProcessGoneDelegate*> delegates;
59+
GetAwRenderProcessGoneDelegatesForRenderProcess(child_process_id, &delegates);
60+
for (auto delegate : delegates)
61+
delegate->OnRenderProcessGone(child_process_id);
62+
}
63+
64+
void OnRenderProcessGoneDetail(int child_process_id, bool crashed) {
65+
DCHECK_CURRENTLY_ON(BrowserThread::UI);
66+
std::vector<AwRenderProcessGoneDelegate*> delegates;
67+
GetAwRenderProcessGoneDelegatesForRenderProcess(child_process_id, &delegates);
68+
for (auto delegate : delegates) {
69+
if (!delegate->OnRenderProcessGoneDetail(child_process_id, crashed)) {
70+
// Keeps this log unchanged, CTS test uses it to detect crash.
71+
LOG(FATAL) << "Render process's abnormal termination wasn't handled by"
72+
<< " all associated webviews, triggering application crash";
73+
}
74+
}
75+
}
76+
77+
} // namespace
78+
2579
AwBrowserTerminator::AwBrowserTerminator() {}
2680

2781
AwBrowserTerminator::~AwBrowserTerminator() {}
@@ -43,19 +97,23 @@ void AwBrowserTerminator::OnChildStart(int child_process_id,
4397
}
4498

4599
void AwBrowserTerminator::ProcessTerminationStatus(
100+
int child_process_id,
46101
std::unique_ptr<base::SyncSocket> pipe) {
102+
bool crashed = false;
103+
104+
// If the child process hasn't written anything into the pipe. This implies
105+
// that it was terminated via SIGKILL by the low memory killer.
47106
if (pipe->Peek() >= sizeof(int)) {
48107
int exit_code;
49108
pipe->Receive(&exit_code, sizeof(exit_code));
50109
crash_reporter::SuppressDumpGeneration();
51-
LOG(FATAL) << "Renderer process crash detected (code " << exit_code
52-
<< "). Terminating browser.";
53-
} else {
54-
// The child process hasn't written anything into the pipe. This implies
55-
// that it was terminated via SIGKILL by the low memory killer, and thus we
56-
// need to perform a clean exit.
57-
exit(0);
110+
LOG(ERROR) << "Renderer process crash detected (code " << exit_code << ").";
111+
crashed = true;
58112
}
113+
114+
BrowserThread::PostTask(
115+
BrowserThread::UI, FROM_HERE,
116+
base::Bind(&OnRenderProcessGoneDetail, child_process_id, crashed));
59117
}
60118

61119
void AwBrowserTerminator::OnChildExit(
@@ -79,10 +137,12 @@ void AwBrowserTerminator::OnChildExit(
79137
}
80138
if (termination_status == base::TERMINATION_STATUS_NORMAL_TERMINATION)
81139
return;
140+
OnRenderProcessGone(child_process_id);
82141
DCHECK(pipe->handle() != base::SyncSocket::kInvalidHandle);
83142
BrowserThread::PostTask(
84143
BrowserThread::FILE, FROM_HERE,
85144
base::Bind(&AwBrowserTerminator::ProcessTerminationStatus,
145+
child_process_id,
86146
base::Passed(std::move(pipe))));
87147
}
88148

android_webview/browser/aw_browser_terminator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class AwBrowserTerminator : public breakpad::CrashDumpObserver::Client {
3939
base::android::ApplicationState app_state) override;
4040

4141
private:
42-
static void ProcessTerminationStatus(std::unique_ptr<base::SyncSocket> pipe);
42+
static void ProcessTerminationStatus(int child_process_id,
43+
std::unique_ptr<base::SyncSocket> pipe);
4344

4445
// This map should only be accessed with its lock aquired as it is accessed
4546
// from the PROCESS_LAUNCHER, FILE, and UI threads.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2017 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+
5+
#ifndef ANDROID_WEBVIEW_BROWSER_AW_RENDER_PROCESS_GONE_DELEGATE_H_
6+
#define ANDROID_WEBVIEW_BROWSER_AW_RENDER_PROCESS_GONE_DELEGATE_H_
7+
8+
namespace content {
9+
class WebContents;
10+
}
11+
12+
namespace android_webview {
13+
14+
// Delegate interface to handle the events that render process was gone.
15+
class AwRenderProcessGoneDelegate {
16+
public:
17+
// Returns the AwRenderProcessGoneDelegate instance associated with
18+
// the given |web_contents|.
19+
static AwRenderProcessGoneDelegate* FromWebContents(
20+
content::WebContents* web_contents);
21+
22+
// Notify render process's termination is detected.
23+
virtual void OnRenderProcessGone(int child_process_id) = 0;
24+
25+
// Notify if render process crashed or was killed, this callback is
26+
// invoked after OnRenderProcessGone() because the detail information
27+
// can't be obtained immediately when render process's termination is
28+
// detected.
29+
virtual bool OnRenderProcessGoneDetail(int child_process_id,
30+
bool crashed) = 0;
31+
32+
protected:
33+
AwRenderProcessGoneDelegate() {}
34+
};
35+
36+
} // namespace android_webview
37+
38+
#endif // ANDROID_WEBVIEW_BROWSER_AW_RENDER_PROCESS_GONE_DELEGATE_H_

android_webview/java/src/org/chromium/android_webview/AwContents.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,16 @@ private void receivePopupContents(long popupNativeAwContents) {
11571157
}
11581158
}
11591159

1160+
@CalledByNative
1161+
private void onRenderProcessGone(int childProcessID) {
1162+
}
1163+
1164+
@CalledByNative
1165+
private boolean onRenderProcessGoneDetail(int childProcessID, boolean crashed) {
1166+
if (isDestroyed(NO_WARN)) return false;
1167+
return mContentsClient.onRenderProcessGone(new AwRenderProcessGoneDetail(crashed));
1168+
}
1169+
11601170
/**
11611171
* Destroys this object and deletes its native counterpart.
11621172
*/

android_webview/native/aw_contents.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@ AwSafeBrowsingUIManager::UIManagerClient::FromWebContents(
186186
return AwContents::FromWebContents(web_contents);
187187
}
188188

189+
// static
190+
AwRenderProcessGoneDelegate* AwRenderProcessGoneDelegate::FromWebContents(
191+
content::WebContents* web_contents) {
192+
return AwContents::FromWebContents(web_contents);
193+
}
194+
189195
AwContents::AwContents(std::unique_ptr<WebContents> web_contents)
190196
: content::WebContentsObserver(web_contents.get()),
191197
functor_(nullptr),
@@ -1315,4 +1321,26 @@ bool AwContents::CanShowInterstitial() {
13151321
return Java_AwContents_canShowInterstitial(env, obj);
13161322
}
13171323

1324+
void AwContents::OnRenderProcessGone(int child_process_id) {
1325+
DCHECK_CURRENTLY_ON(BrowserThread::UI);
1326+
JNIEnv* env = AttachCurrentThread();
1327+
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1328+
if (obj.is_null())
1329+
return;
1330+
1331+
Java_AwContents_onRenderProcessGone(env, obj, child_process_id);
1332+
}
1333+
1334+
bool AwContents::OnRenderProcessGoneDetail(int child_process_id,
1335+
bool crashed) {
1336+
DCHECK_CURRENTLY_ON(BrowserThread::UI);
1337+
JNIEnv* env = AttachCurrentThread();
1338+
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1339+
if (obj.is_null())
1340+
return false;
1341+
1342+
return Java_AwContents_onRenderProcessGoneDetail(env, obj,
1343+
child_process_id, crashed);
1344+
}
1345+
13181346
} // namespace android_webview

android_webview/native/aw_contents.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <utility>
1414

1515
#include "android_webview/browser/aw_browser_permission_request_delegate.h"
16+
#include "android_webview/browser/aw_render_process_gone_delegate.h"
1617
#include "android_webview/browser/aw_safe_browsing_ui_manager.h"
1718
#include "android_webview/browser/browser_view_renderer.h"
1819
#include "android_webview/browser/browser_view_renderer_client.h"
@@ -64,6 +65,7 @@ class AwContents : public FindHelper::Listener,
6465
public BrowserViewRendererClient,
6566
public PermissionRequestHandlerClient,
6667
public AwBrowserPermissionRequestDelegate,
68+
public AwRenderProcessGoneDelegate,
6769
public content::WebContentsObserver,
6870
public AwSafeBrowsingUIManager::UIManagerClient {
6971
public:
@@ -344,6 +346,10 @@ class AwContents : public FindHelper::Listener,
344346
// AwSafeBrowsingUIManager::UIManagerClient implementation
345347
bool CanShowInterstitial() override;
346348

349+
// AwRenderProcessGoneDelegate overrides
350+
void OnRenderProcessGone(int child_process_id) override;
351+
bool OnRenderProcessGoneDetail(int child_process_id, bool crashed) override;
352+
347353
private:
348354
void InitAutofillIfNecessary(bool enabled);
349355

0 commit comments

Comments
 (0)