| Index: components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
|
| 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
|
| index 8214b7b5b449d705f067d3313235b955c31ac420..6451173389494f3e5b7cc1c2b86d4c175fd2b620 100644
|
| --- 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
|
| @@ -29,24 +29,24 @@ import java.util.regex.Pattern;
|
| /**
|
| * The CrashFileManager is responsible for managing the "Crash Reports" directory containing
|
| * minidump files and shepherding them through a state machine represented by the file names. Note
|
| - * that some of the steps are optional:
|
| + * that the second step is optional.
|
| * 1. foo.dmp is a minidump file, written to the directory by Breakpad.
|
| * (2) foo.dmpNNNNN is a minidump file, where NNNNN is the PID (process id) of the crashing
|
| * process. This step is optional -- that is, a minidump could fail to have its PID included in
|
| * the filename.
|
| - * (3) foo.dmpNNNNN.try0 is a minidump file with recent logcat output attached to it. This step is
|
| - * optional -- that is, logcat output might fail to be extracted for the minidump. Notably,
|
| + * 3. foo.dmp.try0 or foo.dmpNNNNN.try0 is a minidump file with recent logcat output attached to
|
| + * it; or a file for which logcat output has been intentionally omitted. Notably,
|
| * Webview-generated minidumps do not include logcat output.
|
| * 4. foo.dmpNNNNN.tryM for M > 0 is a minidump file that's been attempted to be uploaded to the
|
| * crash server, but for which M upload attempts have failed.
|
| - * 5. foo.up, foo.upNNNNN, or foo.upNNNNN.tryM are all valid possible names for a successfully
|
| - * uploaded file.
|
| - * 6. foo.skipped, foo.skippedNNNNN, or foo.skippedNNNNN.tryM are all valid possible names for a
|
| - * file whose upload was skipped. An upload may be skipped, for example, if the user has not
|
| - * consented to uploading crash reports. These files are marked as skipped rather than deleted
|
| - * immediately to allow the user to manually initiate an upload.
|
| - * 7. foo.forced, foo.forcedNNNNN, or foo.forcedNNNNN.tryM are all valid possible names for a file
|
| - * that the user has manually requested to upload.
|
| + * 5. foo.up.tryM and foo.upNNNNN.tryM are both valid possible names for a successfully uploaded
|
| + * file.
|
| + * 6. foo.skipped.tryM and foo.skippedNNNNN.tryM are both valid possible names for a file whose
|
| + * upload was skipped. An upload may be skipped, for example, if the user has not consented to
|
| + * uploading crash reports. These files are marked as skipped rather than deleted immediately to
|
| + * allow the user to manually initiate an upload.
|
| + * 7. foo.forced.tryM and foo.forcedNNNNN.tryM are both valid possible names for a file that the
|
| + * user has manually requested to upload.
|
| * 8. foo.tmp is a temporary file.
|
| */
|
| public class CrashFileManager {
|
| @@ -61,12 +61,17 @@ public class CrashFileManager {
|
| @VisibleForTesting
|
| public static final String CRASH_DUMP_LOGFILE = "uploads.log";
|
|
|
| - private static final Pattern MINIDUMP_MIME_FIRST_TRY_PATTERN =
|
| - Pattern.compile("\\.dmp([0-9]+)$\\z");
|
| + // Unlike the MINIDUMP_READY_FOR_UPLOAD_PATTERN below, this pattern omits a ".tryN" suffix.
|
| + private static final Pattern MINIDUMP_SANS_LOGCAT_PATTERN =
|
| + Pattern.compile("\\.dmp([0-9]*)\\z");
|
|
|
| - private static final Pattern MINIDUMP_PATTERN =
|
| - Pattern.compile("\\.(dmp|forced)([0-9]*)(\\.try([0-9]+))?\\z");
|
| + private static final Pattern MINIDUMP_READY_FOR_UPLOAD_PATTERN =
|
| + Pattern.compile("\\.(dmp|forced)([0-9]*)(\\.try([0-9]+))\\z");
|
|
|
| + // TODO(isherman): The ".tryN" suffix is currently optional, so that old uploaded minidump files
|
| + // will continue to be detected as such. However, new uploads are guaranteed to include this
|
| + // suffix. Tighten this regex (by removing the final '?') in roughly the M61 timeframe:
|
| + // http://crbug.com/719120
|
| private static final Pattern UPLOADED_MINIDUMP_PATTERN =
|
| Pattern.compile("\\.up([0-9]*)(\\.try([0-9]+))?\\z");
|
|
|
| @@ -80,6 +85,9 @@ public class CrashFileManager {
|
|
|
| private static final String UPLOAD_ATTEMPT_DELIMITER = ".try";
|
|
|
| + // The suffix used when a minidump is first ready for upload: ".try0".
|
| + public static final String READY_FOR_UPLOAD_SUFFIX = UPLOAD_ATTEMPT_DELIMITER + "0";
|
| +
|
| // A delimiter between uid and the rest of a minidump filename. Only used for WebView minidumps.
|
| private static final String UID_DELIMITER = "_";
|
|
|
| @@ -140,8 +148,17 @@ public class CrashFileManager {
|
| return isSuccess;
|
| }
|
|
|
| - public static boolean isMinidumpMIMEFirstTry(String path) {
|
| - return MINIDUMP_MIME_FIRST_TRY_PATTERN.matcher(path).find();
|
| + /**
|
| + * Returns whether a minidump file definitely lacks logcat output. Note: This method does not
|
| + * provide an "if and only if" test: it may return false for a path that lacks logcat output, if
|
| + * logcat output has been intentionally skipped for that minidump. However, a return value of
|
| + * true means that the file definitely lacks logcat output.
|
| + * @param path The minidump pathname to test.
|
| + * @return Whether the given path corresponds to a minidump file that definitely lacks logcat
|
| + * output.
|
| + */
|
| + public static boolean isMinidumpSansLogcat(String path) {
|
| + return MINIDUMP_SANS_LOGCAT_PATTERN.matcher(path).find();
|
| }
|
|
|
| public static String tryIncrementAttemptNumber(File mFileToUpload) {
|
| @@ -168,6 +185,20 @@ public class CrashFileManager {
|
| }
|
|
|
| /**
|
| + * Attempts to rename the given file to mark it as ready for upload. This should be done when
|
| + * logcat extraction fails or is otherwise intentionally skipped. An equivalent operation is
|
| + * done when extraction succeeds; but since the logcat output needs to be included in the
|
| + * uploaded data, more than a simple rename is needed.
|
| + *
|
| + * @return The renamed file, or null if renaming failed.
|
| + */
|
| + public static File trySetReadyForUpload(File fileToUpload) {
|
| + assert CrashFileManager.isMinidumpSansLogcat(fileToUpload.getName());
|
| + File renamedFile = new File(fileToUpload.getPath() + READY_FOR_UPLOAD_SUFFIX);
|
| + return fileToUpload.renameTo(renamedFile) ? renamedFile : null;
|
| + }
|
| +
|
| + /**
|
| * Attempts to rename the given file to mark it as a forced upload. This is useful for allowing
|
| * users to manually initiate previously skipped uploads.
|
| *
|
| @@ -309,18 +340,21 @@ public class CrashFileManager {
|
| }
|
|
|
| /**
|
| - * Returns all minidump files that could still be uploaded, sorted by modification time stamp.
|
| - * Only returns files that we have tried to upload less than {@param maxTries} number of times.
|
| + * Returns all minidump files that definitely do not have logcat output, sorted by modification
|
| + * time stamp. Note: This method does not provide an "if and only if" test: it may return omit
|
| + * some files that lack logcat output, if logcat output has been intentionally skipped for those
|
| + * minidumps. However, any files returned definitely lack logcat output.
|
| */
|
| - public File[] getAllMinidumpFiles(int maxTries) {
|
| - return getFilesBelowMaxTries(getAllMinidumpFilesIncludingFailed(), maxTries);
|
| + public File[] getMinidumpsSansLogcat() {
|
| + return listCrashFiles(MINIDUMP_SANS_LOGCAT_PATTERN);
|
| }
|
|
|
| /**
|
| - * Returns all minidump files sorted by modification time stamp.
|
| + * Returns all minidump files that could still be uploaded, sorted by modification time stamp.
|
| + * Only returns files that we have tried to upload less than {@param maxTries} number of times.
|
| */
|
| - private File[] getAllMinidumpFilesIncludingFailed() {
|
| - return listCrashFiles(MINIDUMP_PATTERN);
|
| + public File[] getMinidumpsReadyForUpload(int maxTries) {
|
| + return getFilesBelowMaxTries(listCrashFiles(MINIDUMP_READY_FOR_UPLOAD_PATTERN), maxTries);
|
| }
|
|
|
| /**
|
| @@ -486,7 +520,7 @@ public class CrashFileManager {
|
| * @param uid The uid of the app to check the minidump limit for.
|
| */
|
| private void enforceMinidumpStorageRestrictions(int uid) {
|
| - File[] allMinidumpFiles = getAllMinidumpFilesIncludingFailed();
|
| + File[] allMinidumpFiles = listCrashFiles(MINIDUMP_READY_FOR_UPLOAD_PATTERN);
|
| List<File> minidumpFilesWithCurrentUid = filterMinidumpFilesOnUid(allMinidumpFiles, uid);
|
|
|
| // If we have exceeded our cap per uid, delete the oldest minidump of the same uid
|
| @@ -598,7 +632,8 @@ public class CrashFileManager {
|
| * some entity. A uid, on the other hand, is a unique identifier for Android packages.
|
| */
|
| private static String createUniqueMinidumpNameForUid(int uid) {
|
| - return uid + UID_DELIMITER + UUID.randomUUID() + NOT_YET_UPLOADED_MINIDUMP_SUFFIX;
|
| + return uid + UID_DELIMITER + UUID.randomUUID() + NOT_YET_UPLOADED_MINIDUMP_SUFFIX
|
| + + READY_FOR_UPLOAD_SUFFIX;
|
| }
|
|
|
| /**
|
|
|