Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java |
| index 71d5da9513554c25f32587b26374b7d622060694..df22ec83e3b7e80700d738367014b4589f73b119 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java |
| @@ -19,6 +19,7 @@ import android.view.inputmethod.InputMethodSubtype; |
| import org.chromium.base.CommandLine; |
| import org.chromium.base.ContextUtils; |
| import org.chromium.base.FieldTrialList; |
| +import org.chromium.base.Log; |
| import org.chromium.base.PowerMonitor; |
| import org.chromium.base.SysUtils; |
| import org.chromium.base.ThreadUtils; |
| @@ -26,6 +27,7 @@ import org.chromium.base.TraceEvent; |
| import org.chromium.base.VisibleForTesting; |
| import org.chromium.base.metrics.RecordHistogram; |
| import org.chromium.chrome.browser.bookmarkswidget.BookmarkWidgetProvider; |
| +import org.chromium.chrome.browser.crash.LogcatExtractionRunnable; |
| import org.chromium.chrome.browser.crash.MinidumpUploadService; |
| import org.chromium.chrome.browser.init.ProcessInitializationHandler; |
| import org.chromium.chrome.browser.locale.LocaleManager; |
| @@ -48,7 +50,10 @@ import org.chromium.chrome.browser.webapps.WebappRegistry; |
| import org.chromium.components.minidump_uploader.CrashFileManager; |
| import org.chromium.content.browser.ChildProcessLauncher; |
| +import java.io.File; |
| import java.util.ArrayList; |
| +import java.util.Arrays; |
| +import java.util.Date; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Locale; |
| @@ -59,7 +64,7 @@ import java.util.concurrent.TimeUnit; |
| * Handler for application level tasks to be completed on deferred startup. |
| */ |
| public class DeferredStartupHandler { |
| - private static final String TAG = "DeferredStartupHandler"; |
| + private static final String TAG = "DeferredStartup"; |
| /** Prevents race conditions when deleting snapshot database. */ |
| private static final Object SNAPSHOT_DATABASE_LOCK = new Object(); |
| private static final String SNAPSHOT_DATABASE_REMOVED = "snapshot_database_removed"; |
| @@ -243,24 +248,13 @@ public class DeferredStartupHandler { |
| protected Void doInBackground(Void... params) { |
| try { |
| TraceEvent.begin("ChromeBrowserInitializer.onDeferredStartup.doInBackground"); |
| - mAsyncTaskStartTime = SystemClock.uptimeMillis(); |
| - boolean crashDumpDisabled = CommandLine.getInstance().hasSwitch( |
| - ChromeSwitches.DISABLE_CRASH_DUMP_UPLOAD); |
| - if (!crashDumpDisabled) { |
| - RecordHistogram.recordLongTimesHistogram( |
| - "UMA.Debug.EnableCrashUpload.Uptime3", |
| - mAsyncTaskStartTime - UmaUtils.getForegroundStartTime(), |
| - TimeUnit.MILLISECONDS); |
| - PrivacyPreferencesManager.getInstance().enablePotentialCrashUploading(); |
| - MinidumpUploadService.tryUploadAllCrashDumps(mAppContext); |
| - } |
| - CrashFileManager crashFileManager = |
| - new CrashFileManager(mAppContext.getCacheDir()); |
| - crashFileManager.cleanOutAllNonFreshMinidumpFiles(); |
| + mAsyncTaskStartTime = SystemClock.uptimeMillis(); |
| + RecordHistogram.recordLongTimesHistogram("UMA.Debug.EnableCrashUpload.Uptime3", |
| + mAsyncTaskStartTime - UmaUtils.getForegroundStartTime(), |
| + TimeUnit.MILLISECONDS); |
|
Maria
2017/03/07 06:36:39
looks like you are changing the semantics of when
Ilya Sherman
2017/03/08 02:32:44
Done. Good catch! I misread when this histogram
|
| - MinidumpUploadService.storeBreakpadUploadStatsInUma( |
| - ChromePreferenceManager.getInstance()); |
| + initCrashReporting(); |
| // Initialize the WebappRegistry if it's not already initialized. Must be in |
| // async task due to shared preferences disk access on N. |
| @@ -303,6 +297,75 @@ public class DeferredStartupHandler { |
| }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| } |
| + /** |
| + * Initializes the crash reporting system. More specifically, enables the crash reporting system |
| + * if it is user-permitted, and initiates uploading of any pending crash reports. Also updates |
| + * some UMA metrics and performs cleanup in the local crash minidump storage directory. |
| + */ |
| + private void initCrashReporting() { |
| + // Perform cleanup prior to checking whether crash reporting is enabled, so that users who |
| + // disable crash reporting are still able to eventually recover disk space dedicated to |
| + // storing pending crash reports. |
| + CrashFileManager crashFileManager = new CrashFileManager(mAppContext.getCacheDir()); |
| + crashFileManager.cleanOutAllNonFreshMinidumpFiles(); |
| + |
| + // Likewise, there might be pending metrics from previous runs when crash reporting was |
| + // enabled. |
| + MinidumpUploadService.storeBreakpadUploadStatsInUma(ChromePreferenceManager.getInstance()); |
| + |
| + // Now check whether crash reporting is enable. If it is, broadcast the appropriate |
|
Maria
2017/03/07 06:36:39
nit: enable -> enabled
Ilya Sherman
2017/03/08 02:32:44
Done.
|
| + // permisison. |
|
gsennton
2017/03/07 18:32:04
nit: permisison -> permission
Ilya Sherman
2017/03/08 02:32:44
Done.
|
| + boolean crashReportingDisabled = |
| + CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_CRASH_DUMP_UPLOAD); |
| + if (crashReportingDisabled) { |
|
Maria
2017/03/07 06:36:39
nit: feel free to use
if (crashReportingDisabled
Ilya Sherman
2017/03/08 02:32:44
Done. Yay! This was bugging me, but I wasn't sur
|
| + return; |
| + } |
| + PrivacyPreferencesManager.getInstance().enablePotentialCrashUploading(); |
| + |
| + // Finally, uploading any pending crash reports. |
| + File[] minidumps = |
| + crashFileManager.getAllMinidumpFiles(MinidumpUploadService.MAX_TRIES_ALLOWED); |
| + if (minidumps.length == 0) { |
|
Maria
2017/03/07 06:36:39
ditto
Ilya Sherman
2017/03/08 02:32:44
Done.
|
| + return; |
| + } |
| + |
| + Log.i(TAG, "Attempting to upload accumulated crash dumps."); |
|
Maria
2017/03/07 06:36:39
Might as well log how many there are
Ilya Sherman
2017/03/08 02:32:44
Done.
|
| + if (!doesCrashMinidumpNeedLogcat(minidumps[0])) { |
|
Maria
2017/03/07 06:36:39
Do we have some sort of guarantee on what the firs
gsennton
2017/03/07 18:32:04
Please double-check whether the first minidump her
Ilya Sherman
2017/03/08 02:32:44
I've double-checked that this is indeed the freshe
gsennton
2017/03/08 15:18:41
I would say there are two different scenarios we c
Ilya Sherman
2017/03/09 01:08:45
It would have to be a crash that brings down the b
|
| + MinidumpUploadService.tryUploadAllCrashDumps(mAppContext); |
| + } else { |
|
gsennton
2017/03/07 18:32:04
Would you mind switching the if- and else-statemen
Ilya Sherman
2017/03/08 02:32:44
I can do that, but let me run this by you first: W
gsennton
2017/03/08 15:18:41
What do you mean by "some named variables extracte
Ilya Sherman
2017/03/09 01:08:45
I meant what I included in the latest patch set ;-
|
| + AsyncTask.THREAD_POOL_EXECUTOR.execute( |
| + new LogcatExtractionRunnable(mAppContext, minidumps[0])); |
| + |
| + // TODO(isherman): Once there is support implemented for the JobScheduler API, we should |
| + // only explicitly upload the remaining files here if not using that API. If we *are* |
| + // using the JobScheduler API, then the JobScheduler will schedule uploads for all of |
| + // the available minidumps once the logcat is attached. |
| + List<File> remainingMinidumps = Arrays.asList(minidumps).subList(1, minidumps.length); |
| + for (File minidump : remainingMinidumps) { |
| + MinidumpUploadService.tryUploadCrashDump(mAppContext, minidump); |
| + } |
| + } |
| + } |
| + |
| + /** |
| + * Returns whether or not it's appropriate to try to extract recent logcat output and include |
| + * that logcat output alongside the given {@param minidump} in a crash report. Logcat output |
| + * should only be extracted if (a) it hasn't already been extracted for this minidump file, and |
| + * (b) the minidump is fairly fresh. The freshness check is important for two reasons: (1) First |
| + * of all, it helps avoid including irrelevant logcat output for a crash report. (2) Secondly, |
| + * it provides a cool-off period that can help circumvent a possible infinite crash loop, if the |
|
gsennton
2017/03/07 18:32:04
The cool-off period, is that the infinite period a
Ilya Sherman
2017/03/08 02:32:44
Right. I updated the comment to hopefully clarify
|
| + * code responsible for extracting and appending the logcat content is itself crashing. |
| + * @return Whether to try to include logcat output in the crash report corresponding to the |
| + * given minidump. |
| + */ |
| + private boolean doesCrashMinidumpNeedLogcat(File minidump) { |
| + if (!CrashFileManager.isMinidumpMIMEFirstTry(minidump.getName())) return false; |
| + |
| + long ageInMillis = new Date().getTime() - minidump.lastModified(); |
| + long ageInHours = TimeUnit.HOURS.convert(ageInMillis, TimeUnit.MILLISECONDS); |
| + return ageInHours < 1; |
|
Maria
2017/03/07 06:36:39
How did you choose the duration? I would absolutel
gsennton
2017/03/07 18:32:04
What's the reasoning behind such a short duration?
Maria
2017/03/07 20:04:57
The problem is that we only grab 256 lines from th
Ilya Sherman
2017/03/08 02:32:44
I picked semi-randomly :P I'm happy to start with
Maria
2017/03/08 06:18:47
Hmm, one thing I thought of: logcat data returned
Ilya Sherman
2017/03/08 09:12:30
Okay, sounds good. Any specific suggestions on ho
gsennton
2017/03/08 15:18:41
Ideally we would just read the time-stamp of the f
Ilya Sherman
2017/03/09 01:08:45
I'm not sure whether it's brittle, but it's harder
|
| + } |
| + |
| private void startModerateBindingManagementIfNeeded() { |
| // Moderate binding doesn't apply to low end devices. |
| if (SysUtils.isLowEndDevice()) return; |