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

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/crash/CrashFileManager.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months 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: chrome/android/java_staging/src/org/chromium/chrome/browser/crash/CrashFileManager.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/crash/CrashFileManager.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/crash/CrashFileManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3f2ff75dd1a957e123c940e83f8ef338c88c821
--- /dev/null
+++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/crash/CrashFileManager.java
@@ -0,0 +1,202 @@
+// Copyright 2015 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.chrome.browser.crash;
+
+import android.util.Log;
+
+import org.chromium.base.VisibleForTesting;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Responsible for the Crash Report directory. It routinely scans the directory
+ * for new Minidump files and takes appropriate actions by either uploading new
+ * crash dumps or deleting old ones.
+ */
+public class CrashFileManager {
+ private static final String TAG = "CrashFileManager";
+
+ @VisibleForTesting
+ static final String CRASH_DUMP_DIR = "Crash Reports";
+
+ // This should mirror the C++ CrashUploadList::kReporterLogFilename variable.
+ @VisibleForTesting
+ static final String CRASH_DUMP_LOGFILE = CRASH_DUMP_DIR + "/uploads.log";
+
+ private static final Pattern MINIDUMP_PATTERN =
+ Pattern.compile("\\.dmp([0-9]*)(.try[0-9])?\\z");
+
+ private static final Pattern UPLOADED_MINIDUMP_PATTERN = Pattern.compile("\\.up([0-9]*)\\z");
+
+ private static final String UPLOADED_MINIDUMP_SUFFIX = ".up";
+
+ private static final String UPLOAD_ATTEMPT_DELIMITER = ".try";
+
+ @VisibleForTesting
+ protected static final String TMP_SUFFIX = ".tmp";
+
+ private static final Pattern TMP_PATTERN = Pattern.compile("\\.tmp\\z");
+
+ private static Comparator<File> sFileComparator = new Comparator<File>() {
+ @Override
+ public int compare(File lhs, File rhs) {
+ if (lhs == rhs) {
+ return 0;
+ } else if (lhs.lastModified() < rhs.lastModified()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ };
+
+ @VisibleForTesting
+ static boolean deleteFile(File fileToDelete) {
+ boolean isSuccess = fileToDelete.delete();
+ if (!isSuccess) {
+ Log.w(TAG, "Unable to delete " + fileToDelete.getAbsolutePath());
+ }
+ return isSuccess;
+ }
+
+ public static String tryIncrementAttemptNumber(File mFileToUpload) {
+ String newName = incrementAttemptNumber(mFileToUpload.getPath());
+ return mFileToUpload.renameTo(new File(newName)) ? newName : null;
+ }
+
+ /**
+ * @return The file name to rename to after an addition attempt to upload
+ */
+ @VisibleForTesting
+ public static String incrementAttemptNumber(String filename) {
+ int numTried = readAttemptNumber(filename);
+ if (numTried > 0) {
+ int newCount = numTried + 1;
+ return filename.replaceAll(UPLOAD_ATTEMPT_DELIMITER + numTried,
+ UPLOAD_ATTEMPT_DELIMITER + newCount);
+ } else {
+ return filename + UPLOAD_ATTEMPT_DELIMITER + "1";
+ }
+ }
+
+ @VisibleForTesting
+ public static int readAttemptNumber(String filename) {
+ int tryIndex = filename.lastIndexOf(UPLOAD_ATTEMPT_DELIMITER);
+ if (tryIndex >= 0) {
+ tryIndex += UPLOAD_ATTEMPT_DELIMITER.length();
+ // To avoid out of bound exceptions
+ if (tryIndex < filename.length()) {
+ // We don't try more than 3 times.
+ String numTriesString = filename.substring(
+ tryIndex, tryIndex + 1);
+ try {
+ return Integer.parseInt(numTriesString);
+ } catch (NumberFormatException ignored) {
+ return 0;
+ }
+ }
+ }
+ return 0;
+ }
+
+ public static boolean tryMarkAsUploaded(File mFileToUpload) {
+ return mFileToUpload.renameTo(
+ new File(mFileToUpload.getPath().replaceAll(
+ "\\.dmp", UPLOADED_MINIDUMP_SUFFIX)));
+ }
+
+ private final File mCacheDir;
+
+ public CrashFileManager(File cacheDir) {
+ if (cacheDir == null) {
+ throw new NullPointerException("Specified context cannot be null.");
+ } else if (!cacheDir.isDirectory()) {
+ throw new IllegalArgumentException(cacheDir.getAbsolutePath()
+ + " is not a directory.");
+ }
+ mCacheDir = cacheDir;
+ }
+
+ public File[] getAllMinidumpFiles() {
+ return getMatchingFiles(MINIDUMP_PATTERN);
+ }
+
+ public File[] getAllMinidumpFilesSorted() {
+ File[] minidumps = getAllMinidumpFiles();
+ Arrays.sort(minidumps, sFileComparator);
+ return minidumps;
+ }
+
+ public void cleanOutAllNonFreshMinidumpFiles() {
+ for (File f : getAllUploadedFiles()) {
+ deleteFile(f);
+ }
+ for (File f : getAllTempFiles()) {
+ deleteFile(f);
+ }
+ }
+
+ /**
+ * Deletes all files including unsent crash reports.
+ * Note: This method is called from multiple threads, but it is not thread-safe. It will
+ * generate warning messages in logs if race condition occurs.
+ */
+ @VisibleForTesting
+ public void cleanAllMiniDumps() {
+ cleanOutAllNonFreshMinidumpFiles();
+
+ for (File f : getAllMinidumpFiles()) {
+ deleteFile(f);
+ }
+ }
+
+ @VisibleForTesting
+ File[] getMatchingFiles(final Pattern pattern) {
+ // Get dump dir and get all files with specified suffix.. The path
+ // constructed here must match chrome_paths.cc (see case
+ // chrome::DIR_CRASH_DUMPS).
+ File crashDir = getCrashDirectory();
+ if (!crashDir.exists()) {
+ Log.w(TAG, crashDir.getAbsolutePath() + " does not exist!");
+ return new File[] {};
+ }
+ if (!crashDir.isDirectory()) {
+ Log.w(TAG, crashDir.getAbsolutePath() + " is not a directory!");
+ return new File[] {};
+ }
+ File[] minidumps = crashDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String filename) {
+ Matcher match = pattern.matcher(filename);
+ int tries = readAttemptNumber(filename);
+ return match.find() && tries < MinidumpUploadService.MAX_TRIES_ALLOWED;
+ }
+ });
+ return minidumps;
+ }
+
+ @VisibleForTesting
+ File[] getAllUploadedFiles() {
+ return getMatchingFiles(UPLOADED_MINIDUMP_PATTERN);
+ }
+
+ @VisibleForTesting
+ File getCrashDirectory() {
+ return new File(mCacheDir, CRASH_DUMP_DIR);
+ }
+
+ File getCrashUploadLogFile() {
+ return new File(mCacheDir, CRASH_DUMP_LOGFILE);
+ }
+
+ private File[] getAllTempFiles() {
+ return getMatchingFiles(TMP_PATTERN);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698