OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.crash; | 5 package org.chromium.chrome.browser.crash; |
6 | 6 |
7 import android.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
8 import android.app.IntentService; | 8 import android.app.IntentService; |
9 import android.app.job.JobInfo; | 9 import android.app.job.JobInfo; |
10 import android.content.ComponentName; | 10 import android.content.ComponentName; |
| 11 import android.content.Context; |
11 import android.content.Intent; | 12 import android.content.Intent; |
12 import android.os.Build; | 13 import android.os.Build; |
13 import android.os.PersistableBundle; | 14 import android.os.PersistableBundle; |
14 import android.support.annotation.StringDef; | 15 import android.support.annotation.StringDef; |
15 | 16 |
16 import org.chromium.base.ContextUtils; | |
17 import org.chromium.base.Log; | 17 import org.chromium.base.Log; |
18 import org.chromium.base.StreamUtil; | 18 import org.chromium.base.StreamUtil; |
19 import org.chromium.base.VisibleForTesting; | 19 import org.chromium.base.VisibleForTesting; |
20 import org.chromium.base.annotations.CalledByNative; | 20 import org.chromium.base.annotations.CalledByNative; |
21 import org.chromium.base.metrics.RecordHistogram; | 21 import org.chromium.base.metrics.RecordHistogram; |
22 import org.chromium.chrome.browser.preferences.ChromePreferenceManager; | 22 import org.chromium.chrome.browser.preferences.ChromePreferenceManager; |
23 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager
; | 23 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager
; |
24 import org.chromium.components.background_task_scheduler.TaskIds; | 24 import org.chromium.components.background_task_scheduler.TaskIds; |
25 import org.chromium.components.minidump_uploader.CrashFileManager; | 25 import org.chromium.components.minidump_uploader.CrashFileManager; |
26 import org.chromium.components.minidump_uploader.MinidumpUploadCallable; | 26 import org.chromium.components.minidump_uploader.MinidumpUploadCallable; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 */ | 80 */ |
81 public static boolean shouldUseJobSchedulerForUploads() { | 81 public static boolean shouldUseJobSchedulerForUploads() { |
82 // The JobScheduler API is only usable as of Android M. | 82 // The JobScheduler API is only usable as of Android M. |
83 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; | 83 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; |
84 } | 84 } |
85 | 85 |
86 /** | 86 /** |
87 * Schedules uploading of all pending minidumps, using the JobScheduler API. | 87 * Schedules uploading of all pending minidumps, using the JobScheduler API. |
88 */ | 88 */ |
89 @SuppressLint("NewApi") | 89 @SuppressLint("NewApi") |
90 public static void scheduleUploadJob() { | 90 public static void scheduleUploadJob(Context context) { |
91 assert shouldUseJobSchedulerForUploads(); | 91 assert shouldUseJobSchedulerForUploads(); |
92 | 92 |
93 CrashReportingPermissionManager permissionManager = PrivacyPreferencesMa
nager.getInstance(); | 93 CrashReportingPermissionManager permissionManager = PrivacyPreferencesMa
nager.getInstance(); |
94 PersistableBundle permissions = new PersistableBundle(); | 94 PersistableBundle permissions = new PersistableBundle(); |
95 permissions.putBoolean(ChromeMinidumpUploaderDelegate.IS_CLIENT_IN_METRI
CS_SAMPLE, | 95 permissions.putBoolean(ChromeMinidumpUploaderDelegate.IS_CLIENT_IN_METRI
CS_SAMPLE, |
96 permissionManager.isClientInMetricsSample()); | 96 permissionManager.isClientInMetricsSample()); |
97 permissions.putBoolean(ChromeMinidumpUploaderDelegate.IS_UPLOAD_ENABLED_
FOR_TESTS, | 97 permissions.putBoolean(ChromeMinidumpUploaderDelegate.IS_UPLOAD_ENABLED_
FOR_TESTS, |
98 permissionManager.isUploadEnabledForTests()); | 98 permissionManager.isUploadEnabledForTests()); |
99 | 99 |
100 JobInfo.Builder builder = | 100 JobInfo.Builder builder = |
101 new JobInfo | 101 new JobInfo |
102 .Builder(TaskIds.CHROME_MINIDUMP_UPLOADING_JOB_ID, | 102 .Builder(TaskIds.CHROME_MINIDUMP_UPLOADING_JOB_ID, |
103 new ComponentName(ContextUtils.getApplicationCon
text(), | 103 new ComponentName(context, ChromeMinidumpUploadJ
obService.class)) |
104 ChromeMinidumpUploadJobService.class)) | |
105 .setExtras(permissions); | 104 .setExtras(permissions); |
106 MinidumpUploadJobService.scheduleUpload(builder); | 105 MinidumpUploadJobService.scheduleUpload(context, builder); |
107 } | 106 } |
108 | 107 |
109 /** | 108 /** |
110 * Stores the successes and failures from uploading crash to UMA, | 109 * Stores the successes and failures from uploading crash to UMA, |
111 */ | 110 */ |
112 public static void storeBreakpadUploadStatsInUma(ChromePreferenceManager pre
f) { | 111 public static void storeBreakpadUploadStatsInUma(ChromePreferenceManager pre
f) { |
113 for (String type : TYPES) { | 112 for (String type : TYPES) { |
114 for (int success = pref.getCrashSuccessUploadCount(type); success >
0; success--) { | 113 for (int success = pref.getCrashSuccessUploadCount(type); success >
0; success--) { |
115 RecordHistogram.recordEnumeratedHistogram( | 114 RecordHistogram.recordEnumeratedHistogram( |
116 HISTOGRAM_NAME_PREFIX + type, SUCCESS, HISTOGRAM_MAX); | 115 HISTOGRAM_NAME_PREFIX + type, SUCCESS, HISTOGRAM_MAX); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 return new MinidumpUploadCallable( | 284 return new MinidumpUploadCallable( |
286 minidumpFile, logfile, getCrashReportingPermissionManager()); | 285 minidumpFile, logfile, getCrashReportingPermissionManager()); |
287 } | 286 } |
288 | 287 |
289 /** | 288 /** |
290 * Attempts to upload the specified {@param minidumpFile}. | 289 * Attempts to upload the specified {@param minidumpFile}. |
291 * | 290 * |
292 * Note that this method is asynchronous. All that is guaranteed is that an
upload attempt will | 291 * Note that this method is asynchronous. All that is guaranteed is that an
upload attempt will |
293 * be enqueued. | 292 * be enqueued. |
294 * | 293 * |
295 * @throws SecurityException if the caller doesn't have permission to start
the upload | 294 * @param context The application context, in which to initiate the crash re
port upload. |
| 295 * @throws A security excpetion if the caller doesn't have permission to sta
rt the upload |
296 * service. This can only happen on KitKat and below, due to a frame
work bug. | 296 * service. This can only happen on KitKat and below, due to a frame
work bug. |
297 */ | 297 */ |
298 public static void tryUploadCrashDump(File minidumpFile) throws SecurityExce
ption { | 298 public static void tryUploadCrashDump(Context context, File minidumpFile) |
| 299 throws SecurityException { |
299 assert !shouldUseJobSchedulerForUploads(); | 300 assert !shouldUseJobSchedulerForUploads(); |
300 CrashFileManager fileManager = | 301 CrashFileManager fileManager = new CrashFileManager(context.getCacheDir(
)); |
301 new CrashFileManager(ContextUtils.getApplicationContext().getCac
heDir()); | 302 Intent intent = new Intent(context, MinidumpUploadService.class); |
302 Intent intent = | |
303 new Intent(ContextUtils.getApplicationContext(), MinidumpUploadS
ervice.class); | |
304 intent.setAction(ACTION_UPLOAD); | 303 intent.setAction(ACTION_UPLOAD); |
305 intent.putExtra(FILE_TO_UPLOAD_KEY, minidumpFile.getAbsolutePath()); | 304 intent.putExtra(FILE_TO_UPLOAD_KEY, minidumpFile.getAbsolutePath()); |
306 intent.putExtra(UPLOAD_LOG_KEY, fileManager.getCrashUploadLogFile().getA
bsolutePath()); | 305 intent.putExtra(UPLOAD_LOG_KEY, fileManager.getCrashUploadLogFile().getA
bsolutePath()); |
307 ContextUtils.getApplicationContext().startService(intent); | 306 context.startService(intent); |
308 } | 307 } |
309 | 308 |
310 /** | 309 /** |
311 * Attempts to upload all minidump files using the given {@link android.cont
ent.Context}. | 310 * Attempts to upload all minidump files using the given {@link android.cont
ent.Context}. |
312 * | 311 * |
313 * Note that this method is asynchronous. All that is guaranteed is that | 312 * Note that this method is asynchronous. All that is guaranteed is that |
314 * upload attempts will be enqueued. | 313 * upload attempts will be enqueued. |
315 * | 314 * |
316 * This method is safe to call from the UI thread. | 315 * This method is safe to call from the UI thread. |
317 * | 316 * |
| 317 * @param context Context of the application. |
318 */ | 318 */ |
319 public static void tryUploadAllCrashDumps() { | 319 public static void tryUploadAllCrashDumps(Context context) { |
320 assert !shouldUseJobSchedulerForUploads(); | 320 assert !shouldUseJobSchedulerForUploads(); |
321 CrashFileManager fileManager = | 321 CrashFileManager fileManager = new CrashFileManager(context.getCacheDir(
)); |
322 new CrashFileManager(ContextUtils.getApplicationContext().getCac
heDir()); | |
323 File[] minidumps = fileManager.getAllMinidumpFiles(MAX_TRIES_ALLOWED); | 322 File[] minidumps = fileManager.getAllMinidumpFiles(MAX_TRIES_ALLOWED); |
324 Log.i(TAG, "Attempting to upload accumulated crash dumps."); | 323 Log.i(TAG, "Attempting to upload accumulated crash dumps."); |
325 for (File minidump : minidumps) { | 324 for (File minidump : minidumps) { |
326 tryUploadCrashDump(minidump); | 325 tryUploadCrashDump(context, minidump); |
327 } | 326 } |
328 } | 327 } |
329 | 328 |
330 /** | 329 /** |
331 * Attempts to upload the crash report with the given local ID. | 330 * Attempts to upload the crash report with the given local ID. |
332 * | 331 * |
333 * Note that this method is asynchronous. All that is guaranteed is that | 332 * Note that this method is asynchronous. All that is guaranteed is that |
334 * upload attempts will be enqueued. | 333 * upload attempts will be enqueued. |
335 * | 334 * |
336 * This method is safe to call from the UI thread. | 335 * This method is safe to call from the UI thread. |
337 * | 336 * |
| 337 * @param context the context to use for the intent. |
338 * @param localId The local ID of the crash report. | 338 * @param localId The local ID of the crash report. |
339 */ | 339 */ |
340 @CalledByNative | 340 @CalledByNative |
341 public static void tryUploadCrashDumpWithLocalId(String localId) { | 341 public static void tryUploadCrashDumpWithLocalId(Context context, String loc
alId) { |
342 if (localId == null || localId.isEmpty()) { | 342 if (localId == null || localId.isEmpty()) { |
343 Log.w(TAG, "Cannot force crash upload since local crash id is absent
."); | 343 Log.w(TAG, "Cannot force crash upload since local crash id is absent
."); |
344 return; | 344 return; |
345 } | 345 } |
346 | 346 |
347 CrashFileManager fileManager = | 347 CrashFileManager fileManager = new CrashFileManager(context.getCacheDir(
)); |
348 new CrashFileManager(ContextUtils.getApplicationContext().getCac
heDir()); | |
349 File minidumpFile = fileManager.getCrashFileWithLocalId(localId); | 348 File minidumpFile = fileManager.getCrashFileWithLocalId(localId); |
350 if (minidumpFile == null) { | 349 if (minidumpFile == null) { |
351 Log.w(TAG, "Could not find a crash dump with local ID " + localId); | 350 Log.w(TAG, "Could not find a crash dump with local ID " + localId); |
352 return; | 351 return; |
353 } | 352 } |
354 File renamedMinidumpFile = CrashFileManager.trySetForcedUpload(minidumpF
ile); | 353 File renamedMinidumpFile = CrashFileManager.trySetForcedUpload(minidumpF
ile); |
355 if (renamedMinidumpFile == null) { | 354 if (renamedMinidumpFile == null) { |
356 Log.w(TAG, "Could not rename the file " + minidumpFile.getName() + "
for re-upload"); | 355 Log.w(TAG, "Could not rename the file " + minidumpFile.getName() + "
for re-upload"); |
357 return; | 356 return; |
358 } | 357 } |
359 | 358 |
360 if (shouldUseJobSchedulerForUploads()) { | 359 if (shouldUseJobSchedulerForUploads()) { |
361 scheduleUploadJob(); | 360 scheduleUploadJob(context); |
362 } else { | 361 } else { |
363 tryUploadCrashDump(renamedMinidumpFile); | 362 tryUploadCrashDump(context, renamedMinidumpFile); |
364 } | 363 } |
365 } | 364 } |
366 } | 365 } |
OLD | NEW |