Commit 2930eb12 authored by Tobias Sargeant's avatar Tobias Sargeant Committed by Commit Bot

[wv] Propagate onRenderProcessGone exceptions back to the application.

If an exception is thrown in onRenderProcessGone, then it should be
propagated back to the UI thread message loop so that it is observable
by the application/debuggerd as something other than a native crash.

Bug: 592556
Change-Id: I28b6792c4503347092ce4e79370b20de87c51114
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1585881
Commit-Queue: Tobias Sargeant <tobiasjs@chromium.org>
Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#663026}
parent b997fe2a
......@@ -9,11 +9,14 @@
#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/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "components/crash/content/app/crashpad.h"
#include "components/crash/content/browser/crash_metrics_reporter_android.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"
......@@ -26,15 +29,16 @@
#include "content/public/browser/web_contents.h"
#include "jni/AwBrowserProcess_jni.h"
using base::android::ScopedJavaGlobalRef;
using content::BrowserThread;
namespace android_webview {
namespace {
void GetAwRenderProcessGoneDelegatesForRenderProcess(
void GetJavaWebContentsForRenderProcess(
content::RenderProcessHost* rph,
std::vector<AwRenderProcessGoneDelegate*>* delegates) {
std::vector<ScopedJavaGlobalRef<jobject>>* java_web_contents) {
std::unique_ptr<content::RenderWidgetHostIterator> widgets(
content::RenderWidgetHost::GetRenderWidgetHosts());
while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
......@@ -42,23 +46,36 @@ void GetAwRenderProcessGoneDelegatesForRenderProcess(
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);
java_web_contents->push_back(static_cast<ScopedJavaGlobalRef<jobject>>(
wc->GetJavaWebContents()));
}
}
}
}
void OnRenderProcessGone(content::RenderProcessHost* host,
void OnRenderProcessGone(
const std::vector<ScopedJavaGlobalRef<jobject>>& java_web_contents,
base::ProcessId child_process_pid,
bool crashed) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<AwRenderProcessGoneDelegate*> delegates;
GetAwRenderProcessGoneDelegatesForRenderProcess(host, &delegates);
for (auto* delegate : delegates) {
if (!delegate->OnRenderProcessGone(child_process_pid, crashed)) {
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:
// Let the exception propagate back to the message loop.
base::MessageLoopCurrentForUI::Get()->Abort();
return;
case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kUnhandled:
if (crashed) {
// Keeps this log unchanged, CTS test uses it to detect crash.
std::string message = base::StringPrintf(
......@@ -75,6 +92,10 @@ void OnRenderProcessGone(content::RenderProcessHost* host,
<< " killing application.";
kill(getpid(), SIGKILL);
}
NOTREACHED();
break;
case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kHandled:
break;
}
}
......@@ -104,7 +125,13 @@ void AwBrowserTerminator::OnChildExit(
LOG(ERROR) << "Renderer process (" << info.pid << ") crash detected (code "
<< info.crash_signo << ").";
OnRenderProcessGone(rph, info.pid, info.is_crashed());
std::vector<ScopedJavaGlobalRef<jobject>> java_web_contents;
GetJavaWebContentsForRenderProcess(rph, &java_web_contents);
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI, base::TaskPriority::HIGHEST},
base::BindOnce(OnRenderProcessGone, java_web_contents, info.pid,
info.is_crashed()));
}
} // namespace android_webview
......@@ -1493,15 +1493,23 @@ void AwContents::RendererResponsive(
aw_render_process->GetJavaObject());
}
bool AwContents::OnRenderProcessGone(int child_process_id, bool crashed) {
AwContents::RenderProcessGoneResult AwContents::OnRenderProcessGone(
int child_process_id,
bool crashed) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return false;
return RenderProcessGoneResult::kHandled;
bool result =
Java_AwContents_onRenderProcessGone(env, obj, child_process_id, crashed);
if (HasException(env))
return RenderProcessGoneResult::kException;
return Java_AwContents_onRenderProcessGone(env, obj, child_process_id,
crashed);
return result ? RenderProcessGoneResult::kHandled
: RenderProcessGoneResult::kUnhandled;
}
} // namespace android_webview
......@@ -365,7 +365,8 @@ class AwContents : public FindHelper::Listener,
const base::android::JavaParamRef<jobject>& callback);
// AwRenderProcessGoneDelegate overrides
bool OnRenderProcessGone(int child_process_id, bool crashed) override;
RenderProcessGoneResult OnRenderProcessGone(int child_process_id,
bool crashed) override;
private:
void InitAutofillIfNecessary(bool autocomplete_enabled);
......
......@@ -14,13 +14,15 @@ namespace android_webview {
// Delegate interface to handle the events that render process was gone.
class AwRenderProcessGoneDelegate {
public:
enum class RenderProcessGoneResult { kHandled, kUnhandled, kException };
// Returns the AwRenderProcessGoneDelegate instance associated with
// the given |web_contents|.
static AwRenderProcessGoneDelegate* FromWebContents(
content::WebContents* web_contents);
// Notify if render process crashed or was killed.
virtual bool OnRenderProcessGone(int child_process_id, bool crashed) = 0;
virtual RenderProcessGoneResult OnRenderProcessGone(int child_process_id,
bool crashed) = 0;
protected:
AwRenderProcessGoneDelegate() {}
......
......@@ -61,6 +61,7 @@ import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.CalledByNativeUnchecked;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.AsyncTask;
......@@ -1371,7 +1372,7 @@ public class AwContents implements SmartClipProvider {
}
@VisibleForTesting
@CalledByNative
@CalledByNativeUnchecked
protected boolean onRenderProcessGone(int childProcessID, boolean crashed) {
if (isDestroyed(NO_WARN)) return true;
return mContentsClient.onRenderProcessGone(new AwRenderProcessGoneDetail(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment