Commit 3e8f2679 authored by Hazem Ashmawy's avatar Hazem Ashmawy Committed by Commit Bot

[AW] Add an activity to show WebView crashes

Add an activity to show a list of recent WebView crashes ordered by the
time they are captured.

It's a simple ListView where each item is a TextView that shows:
- Crash Upload ID (if the crash is uploaded).
- Crash Upload time (if the crash is uploaded).
- Crash Upload Status.
- Crash Local ID (unique id for the crash report on the device).
- Crash Capture time (the time when the crash is captured).
- App Package Name (the package name where the crash took place).
- Variations (experiments keys that were running when the crash
  happened).

A report button is only enabled for uploaded crashes to provide more
info about the crash. It opens a webpage to open an issue on crbug.com
using "WebView Bugs" template quoting crash-upload-id.

Bug: 948923
Bug: 990189
Binary-Size: This change adds a new ui activity to webview, it also adds many strings which probably caused that large increase in binary size. However, all these strings are marked as not translatable so this should significantly cut down the size increase estimated by the bot.
Change-Id: Ie09b4a95da4a2cc60898b69f69f7fde04420240e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1700202Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Reviewed-by: default avatarNate Fischer <ntfschr@chromium.org>
Commit-Queue: Hazem Ashmawy <hazems@chromium.org>
Auto-Submit: Hazem Ashmawy <hazems@chromium.org>
Cr-Commit-Position: refs/heads/master@{#689168}
parent dc613c9c
......@@ -887,6 +887,7 @@ android_library("android_webview_java") {
"java/src/org/chromium/android_webview/permission/AwGeolocationCallback.java",
"java/src/org/chromium/android_webview/permission/AwPermissionRequest.java",
"java/src/org/chromium/android_webview/policy/AwPolicyProvider.java",
"java/src/org/chromium/android_webview/ui/CrashesListActivity.java",
"java/src/org/chromium/android_webview/ui/util/CrashInfoLoader.java",
"java/src/org/chromium/android_webview/ui/util/UnuploadedFilesStateLoader.java",
"java/src/org/chromium/android_webview/ui/util/UploadedCrashesInfoLoader.java",
......
......@@ -38,6 +38,10 @@
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<activity android:name="org.chromium.android_webview.ui.CrashesListActivity"
android:label="@string/crashes_list_activity_title"
android:process=":webview_apk"> {# Explicit process required for monochrome compatibility. #}
</activity>
<provider android:name="com.android.webview.chromium.LicenseContentProvider"
android:exported="true"
android:authorities="{{ manifest_package }}.LicenseContentProvider"
......
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 The Chromium Authors. All rights reserved. Use of this
source code is governed by a BSD-style license that can be found in the
LICENSE file.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_crashes_list"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/crashes_summary_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#A9A9A9"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:paddingBottom="5sp"
android:paddingTop="5sp"/>
<ListView
android:id="@+id/crashes_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="25dp"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 The Chromium Authors. All rights reserved. Use of this
source code is governed by a BSD-style license that can be found in the
LICENSE file.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/crash_list_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="vertical">
<TextView
android:id="@+id/crash_info_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
android:textStyle="bold"
android:textSize="16sp"
android:paddingBottom="2dp"
android:paddingTop="2dp"
android:background="#d3d3d3"/>
<TextView
android:id="@+id/crash_info_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textIsSelectable="true"/>
<Button
android:id="@+id/crash_report_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/crash_report_button_text"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 The Chromium Authors. All rights reserved. Use of this
source code is governed by a BSD-style license that can be found in the
LICENSE file.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/options_menu_refresh"
android:title="@string/menu_refresh"
android:showAsAction="never" />
</menu>
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview.ui;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.style.StyleSpan;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import org.chromium.android_webview.R;
import org.chromium.android_webview.common.crash.CrashInfo;
import org.chromium.android_webview.common.crash.CrashInfo.UploadState;
import org.chromium.android_webview.ui.util.WebViewCrashInfoCollector;
import java.util.Date;
import java.util.List;
/**
* An activity to show a list of recent WebView crashes.
*/
public class CrashesListActivity extends Activity {
// Max number of crashes to show in the crashes list.
private static final int MAX_CRASHES_NUMBER = 20;
private ListView mCrashListView;
private TextView mCrashesSummaryView;
private WebViewCrashInfoCollector mCrashCollector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.crashes_list_activity_title);
setContentView(R.layout.activity_crashes_list);
mCrashListView = findViewById(R.id.crashes_list);
mCrashesSummaryView = findViewById(R.id.crashes_summary_textview);
mCrashCollector = new WebViewCrashInfoCollector();
updateCrashesList();
}
/**
* Adapter to create crashes list rows from a list of CrashInfo.
*/
private class CrashListAdapter extends ArrayAdapter<CrashInfo> {
private final List<CrashInfo> mCrashInfoList;
public CrashListAdapter(List<CrashInfo> crashInfoList) {
super(CrashesListActivity.this, R.layout.crashes_list_row, crashInfoList);
mCrashInfoList = crashInfoList;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
// If the the old view is already created then reuse it, else create a new one by layout
// inflation.
if (view == null) {
view = getLayoutInflater().inflate(R.layout.crashes_list_row, null, true);
}
TextView label = view.findViewById(R.id.crash_info_label);
TextView infoTextView = view.findViewById(R.id.crash_info_textview);
Button button = view.findViewById(R.id.crash_report_button);
CrashInfo crashInfo = mCrashInfoList.get(position);
label.setText(getCrashInfoLabelText(crashInfo));
infoTextView.setText(crashInfoToString(crashInfo));
// Report button is only clickable if the crash report is uploaded.
if (crashInfo.uploadState == UploadState.UPLOADED) {
button.setEnabled(true);
button.setOnClickListener(v -> {
startActivity(new Intent(Intent.ACTION_VIEW, getReportUri(crashInfo)));
});
} else {
button.setEnabled(false);
}
return view;
}
private String getCrashInfoLabelText(CrashInfo crashInfo) {
String status =
crashInfo.uploadState == null ? "UNKOWN" : crashInfo.uploadState.toString();
return getString(R.string.crash_label, crashInfo.localId, status);
}
/**
* Convert CrashInfo object to a string to show it in a TexView.
* Field name is in BOLD while the value is not.
*/
private SpannableStringBuilder crashInfoToString(CrashInfo crashInfo) {
SpannableStringBuilder builder = new SpannableStringBuilder();
if (crashInfo.uploadId != null) {
builder.append("upload ID: ", new StyleSpan(android.graphics.Typeface.BOLD), 0)
.append(crashInfo.uploadId)
.append("\n");
}
if (crashInfo.uploadTime >= 0) {
builder.append("upload time: ", new StyleSpan(android.graphics.Typeface.BOLD), 0)
.append(new Date(crashInfo.uploadTime * 1000).toString())
.append("\n");
}
if (crashInfo.captureTime >= 0) {
builder.append("capture time: ", new StyleSpan(android.graphics.Typeface.BOLD), 0)
.append(new Date(crashInfo.captureTime).toString())
.append("\n");
}
if (crashInfo.packageName != null) {
builder.append("app package name: ", new StyleSpan(android.graphics.Typeface.BOLD),
0)
.append(crashInfo.packageName)
.append("\n");
}
if (crashInfo.variations != null) {
builder.append("variations: ", new StyleSpan(android.graphics.Typeface.BOLD), 0)
.append(crashInfo.variations.toString())
.append("\n");
}
return builder;
}
// Build a report uri to open an issue on https://bugs.chromium.org/p/chromium/issues/entry.
// It uses WebView Bugs Template and adds "User-Submitted" Label.
// It adds the upload id at the end of the template and populates the Application package
// name field.
// TODO(https://crbug.com/991594) populate more fields in the template.
private Uri getReportUri(CrashInfo crashInfo) {
return new Uri.Builder()
.scheme("https")
.authority("bugs.chromium.org")
.path("/p/chromium/issues/entry")
.appendQueryParameter("template", "Webview+Bugs")
.appendQueryParameter("comment",
getString(R.string.crash_report_template, crashInfo.uploadId))
.appendQueryParameter("labels", "User-Submitted")
.build();
}
}
private void updateCrashesList() {
List<CrashInfo> crashesList = mCrashCollector.loadCrashesInfo(MAX_CRASHES_NUMBER);
mCrashListView.setAdapter(new CrashListAdapter(crashesList));
mCrashesSummaryView.setText(getString(R.string.crashes_num, crashesList.size()));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.crashes_options_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.options_menu_refresh) {
updateCrashesList();
return true;
}
return super.onOptionsItemSelected(item);
}
}
......@@ -117,6 +117,45 @@
<message name="IDS_LICENSE_ACTIVITY_TITLE" desc="The title of the activity that displays licenses of WebView. [CHAR-LIMIT=50]">
System WebView licenses
</message>
<!-- All WebView Developer UI strings below this line are intentionally marked as not translateable -->
<message name="IDS_CRASHES_LIST_ACTIVITY_TITLE" translateable="false">
WebView Crashes
</message>
<message name="IDS_MENU_REFRESH" translateable="false">
Refresh
</message>
<message name="IDS_CRASHES_NUM" translateable="false">
Crashes (<ph name="CRASHES_NUMBER"><ex>10</ex>%1$d</ph>)
</message>
<message name="IDS_CRASH_LABEL" translateable="false">
Crash (<ph name="CRASH_LOCAL_ID"><ex>abde213122d3ff0</ex>%1$s</ph>) - [<ph name="CRASH_STATUS"><ex>UPLOADED</ex>%2$s</ph>]
</message>
<message name="IDS_CRASH_REPORT_BUTTON_TEXT" translateable="false">
Provide more info
</message>
<message name="IDS_CRASH_REPORT_TEMPLATE" translateable="false">
IMPORTANT: Your crash has already been automatically reported to our crash system. You only need to fill this out if you can share more information like steps to reproduce the crash.
Device name:
Android OS version:
WebView version (On Android L-M, this is the version of the "Android System WebView" app. On Android N-P, it's most likely Chrome's version. You can find the version of any app under Settings > Apps > the 3 dots in the upper right > Show system.):
Application: (Please link to its Play Store page if possible. You can get the link from inside the Play Store app by tapping the 3 dots in the upper right > Share > Copy to clipboard. Or you can find the app on the Play Store website: https://play.google.com/store/apps .)
Application version:
Steps to reproduce:
(1)
(2)
(3)
Expected result:
(What should have happened?)
****DO NOT CHANGE BELOW THIS LINE****
Crash ID: http://crash/<ph name="CRASH_UPLOAD_ID"><ex>277008e5bac834706c</ex>%1$s</ph>
</message>
</messages>
</release>
</grit>
......@@ -953,6 +953,10 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:label="@string/crashes_list_activity_title"
android:name="org.chromium.android_webview.ui.CrashesListActivity"
android:process=":webview_apk"/>
<activity
android:label="@string/license_activity_title"
android:name="com.android.webview.chromium.LicenseActivity"
......
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