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

Side by Side Diff: android_webview/java/src/org/chromium/android_webview/crash/AwMinidumpUploaderDelegate.java

Issue 2709163008: [Android Crash Reporting] Componentize MinidumpUploadImpl.java (Closed)
Patch Set: Finish the componentization Created 3 years, 9 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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.android_webview.crash; 5 package org.chromium.android_webview.crash;
6 6
7 import android.content.Context; 7 import android.content.Context;
8 import android.net.ConnectivityManager; 8 import android.net.ConnectivityManager;
9 import android.net.NetworkInfo; 9 import android.net.NetworkInfo;
10 import android.webkit.ValueCallback; 10 import android.webkit.ValueCallback;
11 11
12 import org.chromium.android_webview.PlatformServiceBridge; 12 import org.chromium.android_webview.PlatformServiceBridge;
13 import org.chromium.android_webview.command_line.CommandLineUtil; 13 import org.chromium.android_webview.command_line.CommandLineUtil;
14 import org.chromium.base.CommandLine; 14 import org.chromium.base.CommandLine;
15 import org.chromium.base.Log;
16 import org.chromium.base.ThreadUtils; 15 import org.chromium.base.ThreadUtils;
17 import org.chromium.base.VisibleForTesting; 16 import org.chromium.base.VisibleForTesting;
18 import org.chromium.components.minidump_uploader.CrashFileManager; 17 import org.chromium.components.minidump_uploader.MinidumpUploaderDelegate;
19 import org.chromium.components.minidump_uploader.MinidumpUploadCallable;
20 import org.chromium.components.minidump_uploader.MinidumpUploader;
21 import org.chromium.components.minidump_uploader.util.CrashReportingPermissionMa nager; 18 import org.chromium.components.minidump_uploader.util.CrashReportingPermissionMa nager;
22 19
23 import java.io.File; 20 import java.io.File;
24 21
25 /** 22 /**
26 * Class in charge of uploading Minidumps from WebView's data directory. 23 * Android Webview-specific implementations for minidump uploading logic.
27 * This class gets invoked from a JobScheduler job and posts the operation of up loading minidumps to
28 * a privately defined worker thread.
29 * Note that this implementation is state-less in the sense that it doesn't keep track of whether it
30 * successfully uploaded any minidumps. At the end of a job it simply checks whe ther there are any
31 * minidumps left to upload, and if so, the job is rescheduled.
32 */ 24 */
33 public class MinidumpUploaderImpl implements MinidumpUploader { 25 public class AwMinidumpUploaderDelegate implements MinidumpUploaderDelegate {
34 private static final String TAG = "MinidumpUploaderImpl"; 26 private final Context mContext;
35 private Context mContext;
36 private Thread mWorkerThread;
37 private final ConnectivityManager mConnectivityManager; 27 private final ConnectivityManager mConnectivityManager;
38 private final CrashFileManager mFileManager;
39 28
40 private boolean mCancelUpload = false;
41
42 private final boolean mCleanOutMinidumps;
43 private boolean mPermittedByUser = false; 29 private boolean mPermittedByUser = false;
44 30
45 @VisibleForTesting 31 @VisibleForTesting
46 public static final int MAX_UPLOAD_TRIES_ALLOWED = 3; 32 public AwMinidumpUploaderDelegate(Context context) {
47 33 mContext = context;
48 /** 34 mConnectivityManager =
49 * Notify the worker thread that the current job has been canceled - so we s houldn't upload any 35 (ConnectivityManager) context.getSystemService(Context.CONNECTIV ITY_SERVICE);
50 * more minidumps.
51 */
52 private void setCancelUpload(boolean cancel) {
53 mCancelUpload = cancel;
54 } 36 }
55 37
56 /** 38 @Override
57 * Check whether the current job has been canceled. 39 public File createCrashDir() {
58 */ 40 return CrashReceiverService.createWebViewCrashDir(mContext);
59 private boolean getCancelUpload() {
60 return mCancelUpload;
61 } 41 }
62 42
63 @VisibleForTesting 43 @Override
64 public MinidumpUploaderImpl(Context context, boolean cleanOutMinidumps) { 44 public CrashReportingPermissionManager createCrashReportingPermissionManager () {
65 mConnectivityManager =
66 (ConnectivityManager) context.getSystemService(Context.CONNECTIV ITY_SERVICE);
67 mContext = context;
68 File webviewCrashDir = CrashReceiverService.createWebViewCrashDir(contex t);
69 mFileManager = new CrashFileManager(webviewCrashDir);
70 if (!mFileManager.ensureCrashDirExists()) {
71 Log.e(TAG, "Crash directory doesn't exist!");
72 }
73 mCleanOutMinidumps = cleanOutMinidumps;
74 }
75
76 /**
77 * Utility method to allow us to test the logic of this class by injecting
78 * test-MinidumpUploadCallables.
79 */
80 @VisibleForTesting
81 public MinidumpUploadCallable createMinidumpUploadCallable(File minidumpFile , File logfile) {
82 return new MinidumpUploadCallable(
83 minidumpFile, logfile, createWebViewCrashReportingManager());
84 }
85
86 /**
87 * Utility method to allow us to test the logic of this class by injecting
88 * a test-PlatformServiceBridge.
89 */
90 @VisibleForTesting
91 public PlatformServiceBridge createPlatformServiceBridge() {
92 return PlatformServiceBridge.getInstance(mContext);
93 }
94
95 @VisibleForTesting
96 protected CrashReportingPermissionManager createWebViewCrashReportingManager () {
97 return new CrashReportingPermissionManager() { 45 return new CrashReportingPermissionManager() {
98 @Override 46 @Override
99 public boolean isClientInMetricsSample() { 47 public boolean isClientInMetricsSample() {
100 // We will check whether the client is in the metrics sample bef ore 48 // We will check whether the client is in the metrics sample bef ore
101 // generating a minidump - so if no minidump is generated this c ode will 49 // generating a minidump - so if no minidump is generated this c ode will
102 // never run and we don't need to check whether we are in the sa mple. 50 // never run and we don't need to check whether we are in the sa mple.
103 // TODO(gsennton): when we switch to using Finch for this value we should use the 51 // TODO(gsennton): when we switch to using Finch for this value we should use the
104 // Finch value here as well. 52 // Finch value here as well.
105 return true; 53 return true;
106 } 54 }
107 @Override 55 @Override
108 public boolean isNetworkAvailableForCrashUploads() { 56 public boolean isNetworkAvailableForCrashUploads() {
109 // JobScheduler will call onStopJob causing our upload to be int errupted when our 57 // JobScheduler will call onStopJob causing our upload to be int errupted when our
110 // network requirements no longer hold. 58 // network requirements no longer hold.
59 // TODO(isherman): This code should really be shared with Chrome . Especially, Chrome
gsennton 2017/02/27 18:54:55 I assume you are implying that Chrome should be ch
Ilya Sherman 2017/02/28 03:54:13 Indeed! Rephrased the comment to hopefully clarif
60 // checks for WiFi networks, rather than checking for whether th e network is
61 // metered.
111 NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkI nfo(); 62 NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkI nfo();
112 if (networkInfo == null || !networkInfo.isConnected()) return fa lse; 63 if (networkInfo == null || !networkInfo.isConnected()) return fa lse;
113 return !mConnectivityManager.isActiveNetworkMetered(); 64 return !mConnectivityManager.isActiveNetworkMetered();
114 } 65 }
115 @Override 66 @Override
116 public boolean isCrashUploadDisabledByCommandLine() { 67 public boolean isCrashUploadDisabledByCommandLine() {
117 return false; 68 return false;
118 } 69 }
119 /** 70 /**
120 * This method is already represented by isClientInMetricsSample() a nd 71 * This method is already represented by isClientInMetricsSample() a nd
121 * isNetworkAvailableForCrashUploads(). 72 * isNetworkAvailableForCrashUploads().
122 */ 73 */
123 @Override 74 @Override
124 public boolean isMetricsUploadPermitted() { 75 public boolean isMetricsUploadPermitted() {
125 return true; 76 return true;
126 } 77 }
127 @Override 78 @Override
128 public boolean isUsageAndCrashReportingPermittedByUser() { 79 public boolean isUsageAndCrashReportingPermittedByUser() {
129 return mPermittedByUser; 80 return mPermittedByUser;
130 } 81 }
131 @Override 82 @Override
132 public boolean isUploadEnabledForTests() { 83 public boolean isUploadEnabledForTests() {
133 // Note that CommandLine/CommandLineUtil are not thread safe. Th ey are initialized 84 // Note that CommandLine/CommandLineUtil are not thread safe. Th ey are initialized
134 // on the main thread, but before the current worker thread star ted - so this thread 85 // on the main thread, but before the current worker thread star ted - so this thread
135 // will have seen the initialization of the CommandLine. 86 // will have seen the initialization of the CommandLine.
87 ThreadUtils.assertOnUiThread();
136 return CommandLine.getInstance().hasSwitch( 88 return CommandLine.getInstance().hasSwitch(
137 CommandLineUtil.CRASH_UPLOADS_ENABLED_FOR_TESTING_SWITCH ); 89 CommandLineUtil.CRASH_UPLOADS_ENABLED_FOR_TESTING_SWITCH );
138 } 90 }
139 }; 91 };
140 } 92 }
141 93
142 /**
143 * Runnable that upload minidumps.
144 * This is where the actual uploading happens - an upload job consists of po sting this Runnable
145 * to the worker thread.
146 */
147 private class UploadRunnable implements Runnable {
148 private final MinidumpUploader.UploadsFinishedCallback mUploadsFinishedC allback;
149
150 public UploadRunnable(MinidumpUploader.UploadsFinishedCallback uploadsFi nishedCallback) {
151 mUploadsFinishedCallback = uploadsFinishedCallback;
152 }
153
154 @Override
155 public void run() {
156 File[] minidumps = mFileManager.getAllMinidumpFiles(MAX_UPLOAD_TRIES _ALLOWED);
157 for (File minidump : minidumps) {
158 // Store the name of the current minidump so that we can mark it as a failure from
159 // the main thread if JobScheduler tells us to stop.
160 MinidumpUploadCallable uploadCallable = createMinidumpUploadCall able(
161 minidump, mFileManager.getCrashUploadLogFile());
162 int uploadResult = uploadCallable.call();
163
164 // Job was canceled -> early out: any clean-up will be performed in cancelUploads().
165 // Note that we check whether we are canceled AFTER trying to up load a minidump -
166 // this is to allow the uploading of at least one minidump per j ob (to deal with
167 // cases where we reschedule jobs over and over again and would never upload any
168 // minidumps because old jobs are canceled when scheduling new j obs).
169 if (getCancelUpload()) return;
170
171 if (uploadResult == MinidumpUploadCallable.UPLOAD_FAILURE) {
172 String newName = CrashFileManager.tryIncrementAttemptNumber( minidump);
173 if (newName == null) {
174 Log.w(TAG, "Failed to increment attempt number of " + mi nidump);
175 }
176 }
177 }
178
179 // Clean out old/uploaded minidumps. Note that this clean-up method is more strict than
180 // our copying mechanism in the sense that it keeps less minidumps.
181 if (mCleanOutMinidumps) {
182 mFileManager.cleanOutAllNonFreshMinidumpFiles();
183 }
184
185 // Reschedule if there are still minidumps to upload.
186 boolean reschedule =
187 mFileManager.getAllMinidumpFiles(MAX_UPLOAD_TRIES_ALLOWED).l ength > 0;
188 mUploadsFinishedCallback.uploadsFinished(reschedule);
189 }
190 }
191
192 @Override 94 @Override
193 public void uploadAllMinidumps( 95 public void prepareToUploadMinidumps(final Runnable startUploads) {
194 final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallba ck) {
195 // This call should happen on the main thread
196 ThreadUtils.assertOnUiThread();
197 if (mWorkerThread != null) {
198 throw new RuntimeException("Only one upload-job should be active at a time");
199 }
200 mWorkerThread = new Thread(new UploadRunnable(uploadsFinishedCallback), "mWorkerThread");
201 setCancelUpload(false);
202
203 createPlatformServiceBridge().queryMetricsSetting(new ValueCallback<Bool ean>() { 96 createPlatformServiceBridge().queryMetricsSetting(new ValueCallback<Bool ean>() {
204 public void onReceiveValue(Boolean enabled) { 97 public void onReceiveValue(Boolean enabled) {
205 // This callback should be received on the main thread (e.g. mWo rkerThread 98 // This callback should be received on the main thread (e.g. mWo rkerThread
206 // is not thread-safe). 99 // is not thread-safe).
207 ThreadUtils.assertOnUiThread(); 100 ThreadUtils.assertOnUiThread();
208 101
209 mPermittedByUser = enabled; 102 mPermittedByUser = enabled;
210 // Note that our job might have been cancelled by this time - ho wever, we do start 103
211 // our worker thread anyway to try to make some progress towards uploading 104 startUploads.run();
212 // minidumps.
213 // This is to ensure that in the case where an app is crashing o ver and over again
214 // - and we are rescheduling jobs over and over again - we are s till uploading at
215 // least one minidump per job, as long as that job starts before it is canceled by
216 // the next job.
217 // For cases where the job is cancelled because the network conn ection is lost, or
218 // because we switch over to a metered connection, we won't try to upload any
219 // minidumps anyway since we check the network connection just b efore the upload of
220 // each minidump.
221 mWorkerThread.start();
222 } 105 }
223 }); 106 });
224 } 107 }
225 108
109 /**
110 * Utility method to allow us to test the logic of this class by injecting
111 * a test-PlatformServiceBridge.
112 */
226 @VisibleForTesting 113 @VisibleForTesting
227 public void joinWorkerThreadForTesting() throws InterruptedException { 114 public PlatformServiceBridge createPlatformServiceBridge() {
228 mWorkerThread.join(); 115 return PlatformServiceBridge.getInstance(mContext);
229 }
230
231 /**
232 * @return whether to reschedule the uploads.
233 */
234 @Override
235 public boolean cancelUploads() {
236 setCancelUpload(true);
237
238 // Reschedule if there are still minidumps to upload.
239 return mFileManager.getAllMinidumpFiles(MAX_UPLOAD_TRIES_ALLOWED).length > 0;
240 } 116 }
241 } 117 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698