LeOSium_webview/LeOS/patches/Logcat-crash-reports-UI.patch

958 lines
38 KiB
Diff
Raw Permalink Normal View History

2023-11-18 11:46:19 +01:00
From: uazo <uazo@users.noreply.github.com>
Date: Tue, 15 Jun 2021 11:49:43 +0000
Subject: Logcat crash reports UI
Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
---
.../crash/MinidumpUploadServiceImpl.java | 22 +++
.../crash_upload_list_android.cc | 25 ++-
.../crash_upload_list_android.h | 1 +
chrome/browser/net/chrome_network_delegate.cc | 7 +
chrome/browser/ui/BUILD.gn | 1 +
chrome/browser/ui/webui/crashes_ui.cc | 176 ++++++++++++++++--
.../crash/core/browser/crashes_ui_util.cc | 4 +
.../crash/core/browser/crashes_ui_util.h | 2 +
.../crash/core/browser/resources/crashes.css | 67 ++++++-
.../crash/core/browser/resources/crashes.html | 17 ++
.../crash/core/browser/resources/crashes.ts | 94 +++-------
components/crash_strings.grdp | 22 ++-
.../minidump_uploader/CrashFileManager.java | 7 +-
.../MinidumpUploadCallable.java | 21 +--
.../minidump_uploader/MinidumpUploader.java | 29 +--
.../upload_list/text_log_upload_list.cc | 1 +
components/upload_list/upload_list.cc | 14 ++
components/upload_list/upload_list.h | 9 +
18 files changed, 385 insertions(+), 134 deletions(-)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java
@@ -44,6 +44,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.chromium.base.task.AsyncTask;
+import org.chromium.base.task.PostTask;
+import org.chromium.base.task.TaskTraits;
+import org.chromium.chrome.browser.crash.LogcatExtractionRunnable;
+
/**
* Service that is responsible for uploading crash minidumps to the Google crash server.
*/
@@ -92,6 +97,23 @@ public class MinidumpUploadServiceImpl extends MinidumpUploadService.Impl {
getService().setIntentRedelivery(true);
}
+ @CalledByNative
+ public static void requestNewExtraction() {
+ CrashFileManager crashFileManager =
+ new CrashFileManager(ContextUtils.getApplicationContext().getCacheDir());
+
+ // Append logcat output to minidumps where are missing
+ // getMinidumpsSansLogcat() also extract new files from crashpad
+ File[] minidumpsSansLogcat = crashFileManager.getMinidumpsSansLogcat();
+ if (minidumpsSansLogcat.length >= 1) {
+ for (int i = 0; i < minidumpsSansLogcat.length; ++i) {
+ File minidump = minidumpsSansLogcat[i];
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(
+ new LogcatExtractionRunnable(minidump));
+ }
+ }
+ }
+
/**
* Schedules uploading of all pending minidumps, using the JobScheduler API.
*/
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_android.cc b/chrome/browser/crash_upload_list/crash_upload_list_android.cc
--- a/chrome/browser/crash_upload_list/crash_upload_list_android.cc
+++ b/chrome/browser/crash_upload_list/crash_upload_list_android.cc
@@ -14,6 +14,7 @@
#include "base/metrics/histogram_macros_local.h"
#include "chrome/android/chrome_jni_headers/MinidumpUploadServiceImpl_jni.h"
#include "ui/base/text/bytes_formatting.h"
+#include "base/strings/string_util.h"
namespace {
@@ -76,16 +77,26 @@ void CrashUploadListAndroid::RequestSingleUpload(const std::string& local_id) {
Java_MinidumpUploadServiceImpl_tryUploadCrashDumpWithLocalId(env, j_local_id);
}
+void CrashUploadListAndroid::RequestNewExtraction() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MinidumpUploadServiceImpl_requestNewExtraction(env);
+}
+
void CrashUploadListAndroid::LoadUnsuccessfulUploadList(
std::vector<std::unique_ptr<UploadInfo>>* uploads) {
const char pending_uploads[] = ".dmp";
const char skipped_uploads[] = ".skipped";
const char manually_forced_uploads[] = ".forced";
+ const char zipped_uploads[] = ".zip";
base::FileEnumerator files(upload_log_path().DirName(), false,
base::FileEnumerator::FILES);
for (base::FilePath file = files.Next(); !file.empty(); file = files.Next()) {
UploadList::UploadInfo::State upload_state;
+ if (base::EndsWith(file.value(), zipped_uploads, base::CompareCase::INSENSITIVE_ASCII)) {
+ // skip zip files
+ continue;
+ }
if (file.value().find(manually_forced_uploads) != std::string::npos) {
RecordUnsuccessfulUploadListState(UnsuccessfulUploadListState::FORCED);
upload_state = UploadList::UploadInfo::State::Pending_UserRequested;
@@ -117,6 +128,8 @@ void CrashUploadListAndroid::LoadUnsuccessfulUploadList(
continue;
}
+ std::string file_path = file.value();
+
// Crash reports can have multiple extensions (e.g. foo.dmp, foo.dmp.try1,
// foo.skipped.try0).
file = file.BaseName();
@@ -136,7 +149,15 @@ void CrashUploadListAndroid::LoadUnsuccessfulUploadList(
RecordUnsuccessfulUploadListState(
UnsuccessfulUploadListState::ADDING_AN_UPLOAD_ENTRY);
id = id.substr(pos + 1);
- uploads->push_back(std::make_unique<UploadList::UploadInfo>(
- id, info.creation_time, upload_state, ui::FormatBytes(file_size)));
+ // Since current thread is an IO thread
+ // to avoid failed DCHECK ThreadRestrictions::AssertSingletonAllowed()
+ // remove ui::FormatBytes(): dcheck fail because it use base::FormatDouble()
+ // and LazyInstance<NumberFormatWrapper>::DestructorAtExit().
+ // also "upload.file_size" is unused.
+ std::u16string file_size_string;
+ auto upload = std::make_unique<UploadList::UploadInfo>(
+ id, info.creation_time, upload_state, file_size_string);
+ upload->file_path = file_path;
+ uploads->push_back(std::move(upload));
}
}
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_android.h b/chrome/browser/crash_upload_list/crash_upload_list_android.h
--- a/chrome/browser/crash_upload_list/crash_upload_list_android.h
+++ b/chrome/browser/crash_upload_list/crash_upload_list_android.h
@@ -35,6 +35,7 @@ class CrashUploadListAndroid : public TextLogUploadList {
std::vector<std::unique_ptr<UploadList::UploadInfo>> LoadUploadList()
override;
void RequestSingleUpload(const std::string& local_id) override;
+ void RequestNewExtraction() override;
private:
void LoadUnsuccessfulUploadList(
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -150,6 +150,13 @@ bool IsAccessAllowedAndroid(const base::FilePath& path) {
if (external_storage_path.IsParent(path))
return true;
+ // access to the crash folder is allowed for the download by the user
+ base::FilePath cache_dir;
+ base::android::GetCacheDirectory(&cache_dir);
+ base::FilePath upload_log_path = cache_dir.Append("Crash Reports");
+ if (upload_log_path.IsParent(path))
+ return true;
+
std::vector<base::FilePath> allowlist;
std::vector<base::FilePath> all_download_dirs =
base::android::GetAllPrivateDownloadsDirectories();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -665,6 +665,7 @@ static_library("ui") {
"//third_party/re2",
"//third_party/webrtc_overrides:webrtc_component",
"//third_party/zlib",
+ "//third_party/zlib/google:zip",
"//ui/accessibility",
"//ui/base",
"//ui/base:data_exchange",
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc
--- a/chrome/browser/ui/webui/crashes_ui.cc
+++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -37,6 +37,19 @@
#include "google_apis/gaia/gaia_auth_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "base/logging.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/files/file_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#if BUILDFLAG(IS_ANDROID)
+#include "base/android/path_utils.h"
+#endif
+#include "net/base/filename_util.h"
+#include "third_party/zlib/google/zip.h"
+
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h"
#endif
@@ -72,6 +85,10 @@ void CreateAndAddCrashesUIHTMLSource(Profile* profile) {
source->SetDefaultResource(IDR_CRASH_CRASHES_HTML);
}
+constexpr base::TaskTraits kLoadingTaskTraits = {
+ base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
+
////////////////////////////////////////////////////////////////////////////////
//
// CrashesDOMHandler
@@ -81,7 +98,7 @@ void CreateAndAddCrashesUIHTMLSource(Profile* profile) {
// The handler for Javascript messages for the chrome://crashes/ page.
class CrashesDOMHandler : public WebUIMessageHandler {
public:
- CrashesDOMHandler();
+ CrashesDOMHandler(content::WebContents* web_contents);
CrashesDOMHandler(const CrashesDOMHandler&) = delete;
CrashesDOMHandler& operator=(const CrashesDOMHandler&) = delete;
@@ -97,6 +114,8 @@ class CrashesDOMHandler : public WebUIMessageHandler {
// Asynchronously fetches the list of crashes. Called from JS.
void HandleRequestCrashes(const base::Value::List& args);
+ void RequestCrashesList();
+
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Asynchronously triggers crash uploading. Called from JS.
void HandleRequestUploads(const base::Value::List& args);
@@ -108,14 +127,30 @@ class CrashesDOMHandler : public WebUIMessageHandler {
// Asynchronously requests a user triggered upload. Called from JS.
void HandleRequestSingleCrashUpload(const base::Value::List& args);
+ std::string RequestSingleUpload(const std::string& local_id) const;
+ void RequestSingleUploadCallback(const std::string& local_id, const std::string& filename);
+
+ // Asynchronously requests a user log extraction. Called from JS.
+ void HandleRequestNewExtraction(const base::Value::List& args);
+ void RequestNewExtraction();
+
+ // Requests remove all crash files. Called from JS.
+ void HandleRequestClearAll(const base::Value::List& args);
+ void ClearAll();
+
scoped_refptr<UploadList> upload_list_;
bool list_available_;
bool first_load_;
+ raw_ptr<content::WebContents> web_contents_;
};
-CrashesDOMHandler::CrashesDOMHandler()
- : list_available_(false), first_load_(true) {
+CrashesDOMHandler::CrashesDOMHandler(content::WebContents* web_contents)
+ : list_available_(false), first_load_(true),
+ web_contents_(web_contents) {
upload_list_ = CreateCrashUploadList();
+#if !BUILDFLAG(IS_ANDROID)
+ web_contents_ = nullptr;
+#endif
}
CrashesDOMHandler::~CrashesDOMHandler() {
@@ -141,10 +176,24 @@ void CrashesDOMHandler::RegisterMessages() {
crash_reporter::kCrashesUIRequestSingleCrashUpload,
base::BindRepeating(&CrashesDOMHandler::HandleRequestSingleCrashUpload,
base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ crash_reporter::kCrashesUIHandleClearAll,
+ base::BindRepeating(&CrashesDOMHandler::HandleRequestClearAll,
+ base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ crash_reporter::kCrashesUIHandleRequestNewExtraction,
+ base::BindRepeating(&CrashesDOMHandler::HandleRequestNewExtraction,
+ base::Unretained(this)));
}
void CrashesDOMHandler::HandleRequestCrashes(const base::Value::List& args) {
AllowJavascript();
+ RequestCrashesList();
+}
+
+void CrashesDOMHandler::RequestCrashesList() {
if (first_load_) {
first_load_ = false;
if (list_available_)
@@ -176,8 +225,7 @@ void CrashesDOMHandler::OnUploadListAvailable() {
}
void CrashesDOMHandler::UpdateUI() {
- bool crash_reporting_enabled =
- ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
+ bool crash_reporting_enabled = true;
bool system_crash_reporter = false;
#if BUILDFLAG(IS_CHROMEOS)
@@ -225,14 +273,117 @@ void CrashesDOMHandler::UpdateUI() {
void CrashesDOMHandler::HandleRequestSingleCrashUpload(
const base::Value::List& args) {
- // Only allow manual uploads if crash uploads arent disabled by policy.
- if (!ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled() &&
- IsMetricsReportingPolicyManaged()) {
- return;
+ std::string local_id = args[0].GetString();
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, kLoadingTaskTraits,
+ base::BindOnce(&CrashesDOMHandler::RequestSingleUpload, base::Unretained(this), local_id),
+ base::BindOnce(&CrashesDOMHandler::RequestSingleUploadCallback, base::Unretained(this), local_id));
+}
+
+std::string CrashesDOMHandler::RequestSingleUpload(const std::string& local_id) const {
+#if BUILDFLAG(IS_ANDROID)
+ // get crash file path
+ std::string info_file_path = upload_list_->GetFilePathByLocalId(local_id);
+ if (info_file_path.empty()) {
+ LOG(ERROR) << "Crash report: file path is not set for " << local_id;
+ return std::string();
+ }
+ base::FilePath crash_file_path(info_file_path);
+
+ // get android crash report dir
+ base::FilePath cache_dir;
+ base::android::GetCacheDirectory(&cache_dir);
+ base::FilePath upload_log_path = cache_dir.Append("Crash Reports");
+
+ // crash reports can have multiple extensions (e.g. foo.dmp, foo.dmp.try1,
+ // foo.skipped.try0), remove it
+ base::FilePath zip_file_name = crash_file_path;
+ while (zip_file_name != zip_file_name.RemoveExtension())
+ zip_file_name = zip_file_name.RemoveExtension();
+
+ // make zip file name, like "ec708a7b-cb17-44e7-8dae-e32f6c45cb8c.zip"
+ zip_file_name = upload_log_path.Append(zip_file_name.BaseName())
+ .AddExtensionASCII(".zip");
+ // since the download is always allowed, the generation takes place only
+ // at the first request, so if exists return it
+ if (base::PathExists(zip_file_name))
+ return zip_file_name.value();
+
+ // original code remove the file immediately after upload.
+ // we changed this behavior but it is still possible that the file no longer exists
+ // because in uploads.log it could be indicated but the file was deleted by self-cleaning
+ if (!base::PathExists(crash_file_path)) {
+ LOG(ERROR) << "Crash report: file " << crash_file_path
+ << " no more available";
+ return std::string();
}
- std::string local_id = args[0].GetString();
- upload_list_->RequestSingleUploadAsync(local_id);
+ std::vector<base::FilePath> files_list;
+ files_list.push_back(crash_file_path.BaseName());
+
+ // open zip file
+ base::File zip_f(zip_file_name,
+ base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+ auto result = zip::ZipFiles(crash_file_path.DirName(), files_list, zip_f.GetPlatformFile());
+ zip_f.Close();
+ if (result) {
+ return zip_file_name.value();
+ }
+#endif
+ LOG(ERROR) << "Crash report: cannot create zip content";
+ return std::string();
+}
+
+void CrashesDOMHandler::RequestSingleUploadCallback(const std::string& local_id,
+ const std::string& file_name) {
+#if BUILDFLAG(IS_ANDROID)
+ if (!file_name.empty()) {
+ upload_list_->RequestSingleUploadAsync(local_id);
+
+ base::FilePath file_path(file_name);
+ web_contents_->GetController().LoadURL(
+ net::FilePathToFileURL(file_path), {}, {}, {});
+ }
+#endif
+}
+
+void CrashesDOMHandler::HandleRequestNewExtraction(
+ const base::Value::List& args) {
+ base::ThreadPool::PostTask(
+ FROM_HERE, kLoadingTaskTraits,
+ base::BindOnce(&CrashesDOMHandler::RequestNewExtraction, base::Unretained(this)));
+}
+
+void CrashesDOMHandler::RequestNewExtraction() {
+ base::debug::DumpWithoutCrashing();
+ // ask java to get file from crashpad and to add logcat
+ upload_list_->RequestNewExtraction();
+}
+
+void CrashesDOMHandler::HandleRequestClearAll(
+ const base::Value::List& args) {
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, kLoadingTaskTraits,
+ base::BindOnce(&CrashesDOMHandler::ClearAll, base::Unretained(this)),
+ base::BindOnce(&CrashesDOMHandler::RequestCrashesList, base::Unretained(this)));
+}
+
+void CrashesDOMHandler::ClearAll() {
+#if BUILDFLAG(IS_ANDROID)
+ // get android crash report dir
+ base::FilePath cache_dir;
+ base::android::GetCacheDirectory(&cache_dir);
+ base::FilePath upload_log_path = cache_dir.Append("Crash Reports");
+
+ base::FileEnumerator dir_enum(
+ upload_log_path,
+ /*recursive=*/false, base::FileEnumerator::FILES);
+ base::FilePath full_name;
+ while (full_name = dir_enum.Next(), !full_name.empty()) {
+ // remove all files, don't care for result
+ base::DeleteFile(full_name);
+ }
+#endif
}
} // namespace
@@ -244,7 +395,8 @@ void CrashesDOMHandler::HandleRequestSingleCrashUpload(
///////////////////////////////////////////////////////////////////////////////
CrashesUI::CrashesUI(content::WebUI* web_ui) : WebUIController(web_ui) {
- web_ui->AddMessageHandler(std::make_unique<CrashesDOMHandler>());
+ web_ui->AddMessageHandler(std::make_unique<CrashesDOMHandler>(
+ web_ui->GetWebContents()));
// Set up the chrome://crashes/ source.
CreateAndAddCrashesUIHTMLSource(Profile::FromWebUI(web_ui));
diff --git a/components/crash/core/browser/crashes_ui_util.cc b/components/crash/core/browser/crashes_ui_util.cc
--- a/components/crash/core/browser/crashes_ui_util.cc
+++ b/components/crash/core/browser/crashes_ui_util.cc
@@ -39,6 +39,8 @@ const CrashesUILocalizedString kCrashesUILocalizedStrings[] = {
{"uploadId", IDS_CRASH_REPORT_UPLOADED_ID},
{"uploadNowLinkText", IDS_CRASH_UPLOAD_NOW_LINK_TEXT},
{"uploadTime", IDS_CRASH_REPORT_UPLOADED_TIME},
+ {"clearAll", IDS_CRASH_CLEAR_ALL_TEXT},
+ {"extractNow", IDS_CRASH_EXTRACT_NOW_TEXT},
};
const size_t kCrashesUILocalizedStringsCount =
@@ -52,6 +54,8 @@ const char kCrashesUIRequestCrashUpload[] = "requestCrashUpload";
const char kCrashesUIShortProductName[] = "shortProductName";
const char kCrashesUIUpdateCrashList[] = "update-crash-list";
const char kCrashesUIRequestSingleCrashUpload[] = "requestSingleCrashUpload";
+const char kCrashesUIHandleClearAll[] = "requestClearAll";
+const char kCrashesUIHandleRequestNewExtraction[] = "requestNewExtraction";
std::string UploadInfoStateAsString(UploadList::UploadInfo::State state) {
switch (state) {
diff --git a/components/crash/core/browser/crashes_ui_util.h b/components/crash/core/browser/crashes_ui_util.h
--- a/components/crash/core/browser/crashes_ui_util.h
+++ b/components/crash/core/browser/crashes_ui_util.h
@@ -34,6 +34,8 @@ extern const char kCrashesUIRequestCrashUpload[];
extern const char kCrashesUIShortProductName[];
extern const char kCrashesUIUpdateCrashList[];
extern const char kCrashesUIRequestSingleCrashUpload[];
+extern const char kCrashesUIHandleClearAll[];
+extern const char kCrashesUIHandleRequestNewExtraction[];
// Converts and appends the most recent uploads to |out_value|.
void UploadListToValue(UploadList* upload_list, base::Value::List* out_value);
diff --git a/components/crash/core/browser/resources/crashes.css b/components/crash/core/browser/resources/crashes.css
--- a/components/crash/core/browser/resources/crashes.css
+++ b/components/crash/core/browser/resources/crashes.css
@@ -3,7 +3,9 @@
* found in the LICENSE file. */
body {
- margin: 20px;
+ margin: 0;
+ padding: 1em;
+ font-size: 100%;
}
h1 {
@@ -27,7 +29,6 @@ html[dir=rtl] h1 {
background-color: rgb(235, 239, 250);
border: 1px solid #bbb;
border-radius: 2px;
- display: flex;
font-size: 100%;
padding: 4px;
}
@@ -80,3 +81,65 @@ html[dir=rtl] h1 {
.not-uploaded {
color: #a0a0a0;
}
+
+label {
+ float: right;
+}
+
+#countBanner > div {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 10px;
+}
+
+.spinner {
+ width: 50px;
+ height: 40px;
+ text-align: center;
+ font-size: 10px;
+}
+
+.spinner > div {
+ background-color: #333;
+ height: 100%;
+ width: 6px;
+ display: inline-block;
+
+ -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
+ animation: sk-stretchdelay 1.2s infinite ease-in-out;
+}
+
+.spinner .rect2 {
+ -webkit-animation-delay: -1.1s;
+ animation-delay: -1.1s;
+}
+
+.spinner .rect3 {
+ -webkit-animation-delay: -1.0s;
+ animation-delay: -1.0s;
+}
+
+.spinner .rect4 {
+ -webkit-animation-delay: -0.9s;
+ animation-delay: -0.9s;
+}
+
+.spinner .rect5 {
+ -webkit-animation-delay: -0.8s;
+ animation-delay: -0.8s;
+}
+
+@-webkit-keyframes sk-stretchdelay {
+ 0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
+ 20% { -webkit-transform: scaleY(1.0) }
+}
+
+@keyframes sk-stretchdelay {
+ 0%, 40%, 100% {
+ transform: scaleY(0.4);
+ -webkit-transform: scaleY(0.4);
+ } 20% {
+ transform: scaleY(1.0);
+ -webkit-transform: scaleY(1.0);
+ }
+}
diff --git a/components/crash/core/browser/resources/crashes.html b/components/crash/core/browser/resources/crashes.html
--- a/components/crash/core/browser/resources/crashes.html
+++ b/components/crash/core/browser/resources/crashes.html
@@ -1,6 +1,7 @@
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8">
<if expr="is_ios">
@@ -39,6 +40,22 @@
<input type="checkbox" id="showDevDetails">
$i18n{showDeveloperDetails}
</label>
+ <div style="clear: both"></div>
+ <div>
+ <button class="button" id="clearAll">
+ $i18n{clearAll}
+ </button>
+ <button class="button" id="newExtraction">
+ $i18n{extractNow}
+ </button>
+ <div class="spinner" id="spinner" hidden>
+ <div class="rect1"></div>
+ <div class="rect2"></div>
+ <div class="rect3"></div>
+ <div class="rect4"></div>
+ <div class="rect5"></div>
+ </div>
+ </div>
</h2>
<div id="crashList">
diff --git a/components/crash/core/browser/resources/crashes.ts b/components/crash/core/browser/resources/crashes.ts
--- a/components/crash/core/browser/resources/crashes.ts
+++ b/components/crash/core/browser/resources/crashes.ts
@@ -12,7 +12,7 @@ import './strings.m.js';
import {assert} from 'chrome://resources/js/assert_ts.js';
import {addWebUiListener} from 'chrome://resources/js/cr.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
-import {appendParam, getRequiredElement} from 'chrome://resources/js/util_ts.js';
+import {getRequiredElement} from 'chrome://resources/js/util_ts.js';
/* Id for tracking automatic refresh of crash list. */
let refreshCrashListId: number|undefined = undefined;
@@ -44,10 +44,7 @@ interface CrashData {
interface UpdateCrashListParams {
enabled: boolean;
dynamicBackend: boolean;
- manualUploads: boolean;
crashes: CrashData[];
- version: string;
- os: string;
isGoogleAccount: boolean;
}
@@ -57,10 +54,7 @@ interface UpdateCrashListParams {
function updateCrashList({
enabled,
dynamicBackend,
- manualUploads,
crashes,
- version,
- os,
isGoogleAccount,
}: UpdateCrashListParams) {
getRequiredElement('crashesCount').textContent = loadTimeData.getStringF(
@@ -70,6 +64,7 @@ function updateCrashList({
getRequiredElement('disabledMode').hidden = enabled;
getRequiredElement('crashUploadStatus').hidden = !enabled || !dynamicBackend;
+ getRequiredElement('spinner').hidden = true;
const template = crashList.querySelector('template');
assert(template);
@@ -150,22 +145,16 @@ function updateCrashList({
assert(uploadTimeCell);
uploadTimeCell.textContent = crash.upload_time || '';
- sendNowButton.remove();
- fileBugButton.onclick = () => fileBug(crash.id, os, version);
+ fileBugButton.remove();
} else {
uploadId.remove();
uploadTime.remove();
fileBugButton.remove();
- // Do not allow crash submission if the Chromium build does not support
- // it, or if the user already requested it.
- if (!manualUploads || crash.state === State.PENDING_USER_REQUESTED) {
- sendNowButton.remove();
- }
- sendNowButton.onclick = (_e: Event) => {
- sendNowButton.disabled = true;
- chrome.send('requestSingleCrashUpload', [crash.local_id]);
- };
}
+ sendNowButton.onclick = (_e: Event) => {
+ sendNowButton.disabled = true;
+ chrome.send('requestSingleCrashUpload', [crash.local_id]);
+ };
const fileSize = clone.querySelector('.file-size');
assert(fileSize);
@@ -183,52 +172,6 @@ function updateCrashList({
getRequiredElement('noCrashes').hidden = crashes.length !== 0;
}
-/**
- * Opens a new tab/window to report the crash to crbug.
- * @param The crash report ID.
- * @param The OS name.
- * @param The product version.
- */
-function fileBug(crashId: string, os: string, version: string) {
- const commentLines = [
- 'IMPORTANT: Your crash has already been automatically reported ' +
- 'to our crash system. Please file this bug only if you can provide ' +
- 'more information about it.',
- '',
- '',
- 'Chrome Version: ' + version,
- 'Operating System: ' + os,
- '',
- 'URL (if applicable) where crash occurred:',
- '',
- 'Can you reproduce this crash?',
- '',
- 'What steps will reproduce this crash? (If it\'s not ' +
- 'reproducible, what were you doing just before the crash?)',
- '1.',
- '2.',
- '3.',
- '',
- '****DO NOT CHANGE BELOW THIS LINE****',
- 'Crash ID: crash/' + crashId,
- ];
- const params: {[key: string]: string} = {
- template: 'Crash Report',
- comment: commentLines.join('\n'),
- // TODO(scottmg): Use add_labels to add 'User-Submitted' rather than
- // duplicating the template's labels (the first two) once
- // https://bugs.chromium.org/p/monorail/issues/detail?id=1488 is done.
- labels:
- 'Restrict-View-EditIssue,Stability-Crash,User-Submitted,Pri-3,Type-Bug',
- };
- let href = 'https://bugs.chromium.org/p/chromium/issues/entry';
- for (const param in params) {
- href = appendParam(href, param, params[param]!);
- }
-
- window.open(href);
-}
-
/**
* Request crashes get uploaded in the background.
*/
@@ -242,6 +185,27 @@ function requestCrashUpload() {
refreshCrashListId = setTimeout(requestCrashes, 5000);
}
+/**
+ * Request new log extraction.
+ */
+function requestNewExtraction() {
+ chrome.send('requestNewExtraction');
+
+ // show spinner
+ getRequiredElement('spinner').hidden = false;
+
+ // Trigger a refresh in 3 seconds. Clear any previous requests.
+ clearTimeout(refreshCrashListId);
+ refreshCrashListId = setTimeout(requestCrashes, 3000);
+}
+
+/**
+ * Request remove all crash files.
+ */
+ function requestClearAll() {
+ chrome.send('requestClearAll');
+}
+
/**
* Toggles hiding/showing the developer details of a crash report, depending
* on the value of the check box.
@@ -256,5 +220,7 @@ document.addEventListener('DOMContentLoaded', function() {
addWebUiListener('update-crash-list', updateCrashList);
getRequiredElement('uploadCrashes').onclick = requestCrashUpload;
getRequiredElement('showDevDetails').onclick = toggleDevDetails;
+ getRequiredElement('clearAll').onclick = requestClearAll;
+ getRequiredElement('newExtraction').onclick = requestNewExtraction;
requestCrashes();
});
diff --git a/components/crash_strings.grdp b/components/crash_strings.grdp
--- a/components/crash_strings.grdp
+++ b/components/crash_strings.grdp
@@ -19,22 +19,22 @@
Status:
</message>
<message name="IDS_CRASH_REPORT_STATUS_NOT_UPLOADED" desc="Value on chrome://crashes for the 'not uploaded' status of a crash report.">
- Not uploaded
+ Not saved
</message>
<message name="IDS_CRASH_REPORT_STATUS_PENDING" desc="Value on chrome://crashes for the 'pending' status of a crash report.">
- Not yet uploaded, or ignored
+ Not yet saved, or ignored
</message>
<message name="IDS_CRASH_REPORT_STATUS_PENDING_USER_REQUESTED" desc="Value on chrome://crashes for the 'pending user requested' status of a crash report.">
- Upload requested by user
+ Save requested by user
</message>
<message name="IDS_CRASH_REPORT_STATUS_UPLOADED" desc="Value on chrome://crashes for the 'uploaded' status of a crash report.">
- Uploaded
+ Saved
</message>
<message name="IDS_CRASH_REPORT_UPLOADED_ID" desc="Label on chrome://crashes for the identifier for an uploaded crash report on chrome://crashes">
- Uploaded Crash Report ID:
+ Saved Crash Report File:
</message>
<message name="IDS_CRASH_REPORT_UPLOADED_TIME" desc="Label on chrome://crashes for the time at which the crash report was uploaded.">
- Upload Time:
+ Saved Time:
</message>
<message name="IDS_CRASH_REPORT_LOCAL_ID" desc="Label on chrome://crashes for the identifier of a crash report on the user's machine">
Local Crash Context:
@@ -53,9 +53,15 @@
Crash reporting is disabled.
</message>
<message name="IDS_CRASH_UPLOAD_MESSAGE" desc="Link text for triggering crash uploading on chrome://crashes">
- Start uploading crashes
+ Start saving crashes
</message>
<message name="IDS_CRASH_UPLOAD_NOW_LINK_TEXT" desc="Link text for manual uploads of a crash report">
- Send now
+ Save now
+ </message>
+ <message name="IDS_CRASH_CLEAR_ALL_TEXT" desc="Link text for clear all crash files">
+ Clear all
+ </message>
+ <message name="IDS_CRASH_EXTRACT_NOW_TEXT" desc="Link text for manual generation of a crash report">
+ Generate report
</message>
</grit-part>
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
--- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
+++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
@@ -109,6 +109,8 @@ public class CrashFileManager {
private static final Pattern TMP_PATTERN = Pattern.compile("\\.tmp\\z");
+ private static final String SAVED_MINIDUMP_ZIP_SUFFIX = ".zip";
+
// The maximum number of non-uploaded crashes that may be kept in the crash reports directory.
// Chosen to attempt to balance between keeping a generous number of crashes, and not using up
// too much filesystem storage space for obsolete crash reports.
@@ -118,7 +120,7 @@ public class CrashFileManager {
// The maximum age, in days, considered acceptable for a crash report. Reports older than this
// age will be removed. The constant is chosen to be quite conservative, while still allowing
// users to eventually reclaim filesystem storage space from obsolete crash reports.
- private static final int MAX_CRASH_REPORT_AGE_IN_DAYS = 30;
+ private static final int MAX_CRASH_REPORT_AGE_IN_DAYS = 5;
// The maximum number of non-uploaded crashes to copy to the crash reports directory. The
// difference between this value and MAX_CRASH_REPORTS_TO_KEEP is that TO_KEEP is only checked
@@ -613,6 +615,9 @@ public class CrashFileManager {
&& !f.getName().contains(UPLOAD_FORCED_MINIDUMP_SUFFIX)) {
continue;
}
+ // as above, zip files must also be excluded
+ if (f.getName().endsWith(SAVED_MINIDUMP_ZIP_SUFFIX))
+ continue;
String filenameSansExtension = f.getName().split("\\.")[0];
if (filenameSansExtension.endsWith(localId)) {
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java
--- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java
+++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java
@@ -63,27 +63,8 @@ public class MinidumpUploadCallable implements Callable<Integer> {
if (mPermManager.isUploadEnabledForTests()) {
Log.i(TAG, "Minidump upload enabled for tests, skipping other checks.");
} else if (!CrashFileManager.isForcedUpload(mFileToUpload)) {
- if (!mPermManager.isUsageAndCrashReportingPermitted()) {
- Log.i(TAG,
- "Minidump upload is not permitted. Marking file as skipped "
- + "for cleanup to prevent future uploads.");
- CrashFileManager.markUploadSkipped(mFileToUpload);
- return MinidumpUploadStatus.USER_DISABLED;
- }
-
- if (!mPermManager.isClientInMetricsSample()) {
- Log.i(TAG, "Minidump upload skipped due to sampling. Marking file as skipped for "
- + "cleanup to prevent future uploads.");
- CrashFileManager.markUploadSkipped(mFileToUpload);
- return MinidumpUploadStatus.DISABLED_BY_SAMPLING;
- }
-
- if (!mPermManager.isNetworkAvailableForCrashUploads()) {
- Log.i(TAG, "Minidump cannot currently be uploaded due to network constraints.");
- return MinidumpUploadStatus.FAILURE;
- }
+ return MinidumpUploadStatus.USER_DISABLED;
}
-
MinidumpUploader.Result result = mMinidumpUploader.upload(mFileToUpload);
if (result.isSuccess()) {
String uploadId = result.message();
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java
--- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java
+++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java
@@ -120,31 +120,10 @@ public class MinidumpUploader {
if (fileToUpload == null || !fileToUpload.exists()) {
return Result.failure("Crash report does not exist");
}
- HttpURLConnection connection =
- mHttpURLConnectionFactory.createHttpURLConnection(CRASH_URL_STRING);
- if (connection == null) {
- return Result.failure("Failed to create connection");
- }
- configureConnectionForHttpPost(connection, readBoundary(fileToUpload));
-
- try (InputStream minidumpInputStream = new FileInputStream(fileToUpload);
- OutputStream requestBodyStream =
- new GZIPOutputStream(connection.getOutputStream())) {
- streamCopy(minidumpInputStream, requestBodyStream);
- int responseCode = connection.getResponseCode();
- if (isSuccessful(responseCode)) {
- // The crash server returns the crash ID in the response body.
- String responseContent = getResponseContentAsString(connection);
- String uploadId = responseContent != null ? responseContent : "unknown";
- return Result.success(uploadId);
- } else {
- // Return the remote error code and message.
- return Result.uploadError(responseCode, connection.getResponseMessage());
- }
- } finally {
- connection.disconnect();
- }
- } catch (IOException | RuntimeException e) {
+ // for us, it's always good
+ // returns the file name without path, which will be registered as local_id
+ return Result.success(fileToUpload.getName());
+ } catch (RuntimeException e) {
return Result.failure(e.toString());
}
}
diff --git a/components/upload_list/text_log_upload_list.cc b/components/upload_list/text_log_upload_list.cc
--- a/components/upload_list/text_log_upload_list.cc
+++ b/components/upload_list/text_log_upload_list.cc
@@ -165,6 +165,7 @@ std::unique_ptr<UploadList::UploadInfo> TextLogUploadList::TryParseCsvLogEntry(
}
auto info = std::make_unique<TextLogUploadList::UploadInfo>(components[1],
upload_time);
+ info->file_path = components[1];
// Add local ID if present.
if (components.size() > 2)
diff --git a/components/upload_list/upload_list.cc b/components/upload_list/upload_list.cc
--- a/components/upload_list/upload_list.cc
+++ b/components/upload_list/upload_list.cc
@@ -99,6 +99,11 @@ std::vector<const UploadList::UploadInfo*> UploadList::GetUploads(
return uploads;
}
+void UploadList::RequestNewExtraction() {
+ // only available for Android. overrided in crash_upload_list_android.cc
+ NOTREACHED();
+}
+
void UploadList::OnLoadComplete(
std::vector<std::unique_ptr<UploadInfo>> uploads) {
uploads_ = std::move(uploads);
@@ -111,3 +116,12 @@ void UploadList::OnClearComplete() {
if (!clear_callback_.is_null())
std::move(clear_callback_).Run();
}
+
+std::string UploadList::GetFilePathByLocalId(const std::string& local_id) {
+ for (const std::unique_ptr<UploadList::UploadInfo>& info : uploads_) {
+ if (info->local_id == local_id) {
+ return info->file_path;
+ }
+ }
+ return std::string();
+}
diff --git a/components/upload_list/upload_list.h b/components/upload_list/upload_list.h
--- a/components/upload_list/upload_list.h
+++ b/components/upload_list/upload_list.h
@@ -69,6 +69,9 @@ class UploadList : public base::RefCountedThreadSafe<UploadList> {
// Formatted file size for locally stored data.
std::u16string file_size;
+
+ // path of crash file
+ std::string file_path;
};
UploadList();
@@ -99,6 +102,12 @@ class UploadList : public base::RefCountedThreadSafe<UploadList> {
// The |UploadInfo| pointers are still owned by this |UploadList| instance.
std::vector<const UploadInfo*> GetUploads(size_t max_count) const;
+ // Get full path of crash file for local_id
+ std::string GetFilePathByLocalId(const std::string& local_id);
+
+ // Request new log extraction
+ virtual void RequestNewExtraction();
+
protected:
virtual ~UploadList();
--
2.25.1