6
6
7
7
#include < unistd.h>
8
8
9
+ #include " android_webview/browser/aw_render_process_gone_delegate.h"
9
10
#include " android_webview/common/aw_descriptors.h"
10
11
#include " android_webview/common/crash_reporter/aw_microdump_crash_reporter.h"
11
12
#include " base/bind.h"
17
18
#include " content/public/browser/notification_service.h"
18
19
#include " content/public/browser/notification_types.h"
19
20
#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"
20
25
21
26
using content::BrowserThread;
22
27
23
28
namespace android_webview {
24
29
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
+
25
79
AwBrowserTerminator::AwBrowserTerminator () {}
26
80
27
81
AwBrowserTerminator::~AwBrowserTerminator () {}
@@ -43,19 +97,23 @@ void AwBrowserTerminator::OnChildStart(int child_process_id,
43
97
}
44
98
45
99
void AwBrowserTerminator::ProcessTerminationStatus (
100
+ int child_process_id,
46
101
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.
47
106
if (pipe->Peek () >= sizeof (int )) {
48
107
int exit_code;
49
108
pipe->Receive (&exit_code, sizeof (exit_code));
50
109
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 ;
58
112
}
113
+
114
+ BrowserThread::PostTask (
115
+ BrowserThread::UI, FROM_HERE,
116
+ base::Bind (&OnRenderProcessGoneDetail, child_process_id, crashed));
59
117
}
60
118
61
119
void AwBrowserTerminator::OnChildExit (
@@ -79,10 +137,12 @@ void AwBrowserTerminator::OnChildExit(
79
137
}
80
138
if (termination_status == base::TERMINATION_STATUS_NORMAL_TERMINATION)
81
139
return ;
140
+ OnRenderProcessGone (child_process_id);
82
141
DCHECK (pipe->handle () != base::SyncSocket::kInvalidHandle );
83
142
BrowserThread::PostTask (
84
143
BrowserThread::FILE, FROM_HERE,
85
144
base::Bind (&AwBrowserTerminator::ProcessTerminationStatus,
145
+ child_process_id,
86
146
base::Passed (std::move (pipe))));
87
147
}
88
148
0 commit comments