Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2292)

Unified Diff: android_webview/java/src/org/chromium/android_webview/crash/MinidumpUploaderImpl.java

Issue 2515353005: [Android WebView] Implement copying and uploading of Minidumps. (Closed)
Patch Set: Fix findbugs errors for realz! Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: android_webview/java/src/org/chromium/android_webview/crash/MinidumpUploaderImpl.java
diff --git a/android_webview/java/src/org/chromium/android_webview/crash/MinidumpUploaderImpl.java b/android_webview/java/src/org/chromium/android_webview/crash/MinidumpUploaderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d9ed3265dec59ad2410771dddd33bc2d5b091fc
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/crash/MinidumpUploaderImpl.java
@@ -0,0 +1,187 @@
+// Copyright 2016 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.crash;
+
+import android.content.Context;
+
+import org.chromium.base.Log;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.components.minidump_uploader.CrashFileManager;
+import org.chromium.components.minidump_uploader.MinidumpUploadCallable;
+import org.chromium.components.minidump_uploader.util.CrashReportingPermissionManager;
+
+import java.io.File;
+
+/**
+ * Class in charge of uploading Minidumps from WebView's data directory.
+ * This class gets invoked from a JobScheduler job and posts the operation of uploading minidumps to
+ * a privately defined worker thread.
+ * Note that this implementation is state-less in the sense that it doesn't keep track of whether it
+ * successfully uploaded any minidumps. At the end of a job it simply checks whether there are any
+ * minidumps left to upload, and if so, the job is rescheduled.
+ */
+public class MinidumpUploaderImpl implements MinidumpUploader {
+ private static final String TAG = "MinidumpUploaderImpl";
+ private Thread mWorkerThread;
+ private final CrashFileManager mFileManager;
+
+ private Object mCancelLock = new Object();
+ private boolean mCancelUpload = false;
+
+ private final boolean mCleanOutMinidumps;
+
+ @VisibleForTesting
+ public static final int MAX_UPLOAD_TRIES_ALLOWED = 3;
+
+ /**
+ * Notify the worker thread that the current job has been canceled - so we shouldn't upload any
+ * more minidumps.
+ */
+ private void setCancelUpload(boolean cancel) {
+ synchronized (mCancelLock) {
+ mCancelUpload = cancel;
+ }
+ }
+
+ /**
+ * Check whether the current job has been canceled.
+ */
+ private boolean getCancelUpload() {
+ synchronized (mCancelLock) {
+ return mCancelUpload;
+ }
+ }
+
+ @VisibleForTesting
+ public MinidumpUploaderImpl(Context context, boolean cleanOutMinidumps) {
+ File webviewCrashDir = CrashReceiverService.createWebViewCrashDir(context);
+ mFileManager = new CrashFileManager(webviewCrashDir);
+ if (!mFileManager.ensureCrashDirExists()) {
+ Log.e(TAG, "Crash directory doesn't exist!");
+ }
+ mCleanOutMinidumps = cleanOutMinidumps;
+ }
+
+ /**
+ * Utility method to allow us to test the logic of this class by injecting
+ * test-MinidumpUploadCallables.
+ */
+ @VisibleForTesting
+ public MinidumpUploadCallable createMinidumpUploadCallable(File minidumpFile, File logfile) {
+ return new MinidumpUploadCallable(
+ minidumpFile, logfile, createWebViewCrashReportingManager());
+ }
+
+ private final CrashReportingPermissionManager createWebViewCrashReportingManager() {
+ return new CrashReportingPermissionManager() {
+ @Override
+ public boolean isClientInMetricsSample() {
+ // We will check whether the client is in the metrics sample before
+ // generating a minidump - so if no minidump is generated this code will
+ // never run and we don't need to check whether we are in the sample.
+ // TODO(gsennton): when we switch to using Finch for this value we should use the
+ // Finch value here as well.
+ return true;
+ }
+ @Override
+ public boolean isNetworkAvailableForCrashUploads() {
+ // JobScheduler will call onStopJob causing our upload to be interrupted when our
+ // network requirements no longer hold.
+ return true;
+ }
+ @Override
+ public boolean isCrashUploadDisabledByCommandLine() {
+ return false;
+ }
+ /**
+ * This method is already represented by isClientInMetricsSample() and
+ * isNetworkAvailableForCrashUploads().
+ */
+ @Override
+ public boolean isMetricsUploadPermitted() {
+ return true;
+ }
+ @Override
+ public boolean isUsageAndCrashReportingPermittedByUser() {
+ // TODO(gsennton): make this depend on Android Checkbox when we can read that
+ // through GmsCore.
+ return false;
+ }
+ @Override
+ public boolean isUploadEnabledForTests() {
+ return SynchronizedWebViewCommandLine.hasSwitch(
+ CrashReceiverService.CRASH_UPLOADS_ENABLED_FOR_TESTING_SWITCH);
+ }
+ };
+ }
+
+ /**
+ * Runnable that upload minidumps.
+ * This is where the actual uploading happens - an upload job consists of posting this Runnable
+ * to the worker thread.
+ */
+ private class UploadRunnable implements Runnable {
+ private final MinidumpUploader.UploadsFinishedCallback mUploadsFinishedCallback;
+
+ public UploadRunnable(MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback) {
+ mUploadsFinishedCallback = uploadsFinishedCallback;
+ }
+
+ @Override
+ public void run() {
+ File[] minidumps = mFileManager.getAllMinidumpFiles(MAX_UPLOAD_TRIES_ALLOWED);
+ for (File minidump : minidumps) {
+ // Store the name of the current minidump so that we can mark it as a failure from
+ // the main thread if JobScheduler tells us to stop.
+ MinidumpUploadCallable uploadCallable = createMinidumpUploadCallable(
+ minidump, mFileManager.getCrashUploadLogFile());
+ int uploadResult = uploadCallable.call();
+
+ // Job was canceled -> early out: any clean-up will be performed in cancelUploads().
+ if (getCancelUpload()) return;
+
+ if (uploadResult == MinidumpUploadCallable.UPLOAD_FAILURE) {
+ String newName = CrashFileManager.tryIncrementAttemptNumber(minidump);
+ if (newName == null) {
+ Log.w(TAG, "Failed to increment attempt number of " + minidump);
+ }
+ }
+ }
+
+ // Clean out old/uploaded minidumps. Note that this clean-up method is more strict than
+ // our copying mechanism in the sense that it keeps less minidumps.
+ if (mCleanOutMinidumps) {
+ mFileManager.cleanOutAllNonFreshMinidumpFiles();
+ }
+
+ // Reschedule if there are still minidumps to upload.
+ boolean reschedule =
+ mFileManager.getAllMinidumpFiles(MAX_UPLOAD_TRIES_ALLOWED).length > 0;
+ mUploadsFinishedCallback.uploadsFinished(reschedule);
+ }
+ }
+
+ @Override
+ public void uploadAllMinidumps(
+ MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback) {
+ if (mWorkerThread != null) {
+ throw new RuntimeException("Only one upload-job should be active at a time");
+ }
+ mWorkerThread = new Thread(new UploadRunnable(uploadsFinishedCallback), "mWorkerThread");
+ setCancelUpload(false);
+ mWorkerThread.start();
+ }
+
+ /**
+ * @return whether to reschedule the uploads.
+ */
+ @Override
+ public boolean cancelUploads() {
+ setCancelUpload(true);
+
+ // Reschedule if there are still minidumps to upload.
+ return mFileManager.getAllMinidumpFiles(MAX_UPLOAD_TRIES_ALLOWED).length > 0;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698