OLD | NEW |
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.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
8 import android.app.Service; | 8 import android.app.Service; |
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.Binder; | 13 import android.os.Binder; |
13 import android.os.Build; | 14 import android.os.Build; |
14 import android.os.IBinder; | 15 import android.os.IBinder; |
15 import android.os.ParcelFileDescriptor; | 16 import android.os.ParcelFileDescriptor; |
16 | 17 |
17 import org.chromium.base.ContextUtils; | |
18 import org.chromium.base.Log; | 18 import org.chromium.base.Log; |
19 import org.chromium.base.VisibleForTesting; | 19 import org.chromium.base.VisibleForTesting; |
20 import org.chromium.components.background_task_scheduler.TaskIds; | 20 import org.chromium.components.background_task_scheduler.TaskIds; |
21 import org.chromium.components.minidump_uploader.CrashFileManager; | 21 import org.chromium.components.minidump_uploader.CrashFileManager; |
22 import org.chromium.components.minidump_uploader.MinidumpUploadJobService; | 22 import org.chromium.components.minidump_uploader.MinidumpUploadJobService; |
23 | 23 |
24 import java.io.File; | 24 import java.io.File; |
25 import java.io.IOException; | 25 import java.io.IOException; |
26 | 26 |
27 /** | 27 /** |
(...skipping 11 matching lines...) Expand all Loading... |
39 | 39 |
40 @Override | 40 @Override |
41 public void onCreate() { | 41 public void onCreate() { |
42 super.onCreate(); | 42 super.onCreate(); |
43 } | 43 } |
44 | 44 |
45 private final ICrashReceiverService.Stub mBinder = new ICrashReceiverService
.Stub() { | 45 private final ICrashReceiverService.Stub mBinder = new ICrashReceiverService
.Stub() { |
46 @Override | 46 @Override |
47 public void transmitCrashes(ParcelFileDescriptor[] fileDescriptors) { | 47 public void transmitCrashes(ParcelFileDescriptor[] fileDescriptors) { |
48 int uid = Binder.getCallingUid(); | 48 int uid = Binder.getCallingUid(); |
49 performMinidumpCopyingSerially(uid, fileDescriptors, true /* schedul
eUploads */); | 49 performMinidumpCopyingSerially( |
| 50 CrashReceiverService.this, uid, fileDescriptors, true /* sch
eduleUploads */); |
50 } | 51 } |
51 }; | 52 }; |
52 | 53 |
53 /** | 54 /** |
54 * Copies minidumps in a synchronized way, waiting for any already started c
opying operations to | 55 * Copies minidumps in a synchronized way, waiting for any already started c
opying operations to |
55 * finish before copying the current dumps. | 56 * finish before copying the current dumps. |
56 * @param scheduleUploads whether to ask JobScheduler to schedule an upload-
job (avoid this | 57 * @param scheduleUploads whether to ask JobScheduler to schedule an upload-
job (avoid this |
57 * during testing). | 58 * during testing). |
58 */ | 59 */ |
59 @VisibleForTesting | 60 @VisibleForTesting |
60 public void performMinidumpCopyingSerially( | 61 public void performMinidumpCopyingSerially(Context context, int uid, |
61 int uid, ParcelFileDescriptor[] fileDescriptors, boolean scheduleUpl
oads) { | 62 ParcelFileDescriptor[] fileDescriptors, boolean scheduleUploads) { |
62 if (!waitUntilWeCanCopy()) { | 63 if (!waitUntilWeCanCopy()) { |
63 Log.e(TAG, "something went wrong when waiting to copy minidumps, bai
ling!"); | 64 Log.e(TAG, "something went wrong when waiting to copy minidumps, bai
ling!"); |
64 return; | 65 return; |
65 } | 66 } |
66 | 67 |
67 try { | 68 try { |
68 boolean copySucceeded = copyMinidumps(uid, fileDescriptors); | 69 boolean copySucceeded = copyMinidumps(context, uid, fileDescriptors)
; |
69 if (copySucceeded && scheduleUploads) { | 70 if (copySucceeded && scheduleUploads) { |
70 // Only schedule a new job if there actually are any files to up
load. | 71 // Only schedule a new job if there actually are any files to up
load. |
71 scheduleNewJob(); | 72 scheduleNewJob(); |
72 } | 73 } |
73 } finally { | 74 } finally { |
74 synchronized (mCopyingLock) { | 75 synchronized (mCopyingLock) { |
75 mIsCopying = false; | 76 mIsCopying = false; |
76 mCopyingLock.notifyAll(); | 77 mCopyingLock.notifyAll(); |
77 } | 78 } |
78 } | 79 } |
(...skipping 14 matching lines...) Expand all Loading... |
93 } | 94 } |
94 } | 95 } |
95 mIsCopying = true; | 96 mIsCopying = true; |
96 return true; | 97 return true; |
97 } | 98 } |
98 } | 99 } |
99 | 100 |
100 private void scheduleNewJob() { | 101 private void scheduleNewJob() { |
101 JobInfo.Builder builder = new JobInfo.Builder(TaskIds.WEBVIEW_MINIDUMP_U
PLOADING_JOB_ID, | 102 JobInfo.Builder builder = new JobInfo.Builder(TaskIds.WEBVIEW_MINIDUMP_U
PLOADING_JOB_ID, |
102 new ComponentName(this, AwMinidumpUploadJobService.class)); | 103 new ComponentName(this, AwMinidumpUploadJobService.class)); |
103 MinidumpUploadJobService.scheduleUpload(builder); | 104 MinidumpUploadJobService.scheduleUpload(this, builder); |
104 } | 105 } |
105 | 106 |
106 /** | 107 /** |
107 * Copy minidumps from the {@param fileDescriptors} to the directory where W
ebView stores its | 108 * Copy minidumps from the {@param fileDescriptors} to the directory where W
ebView stores its |
108 * minidump files. {@param context} is used to look up the directory in whic
h the files will be | 109 * minidump files. {@param context} is used to look up the directory in whic
h the files will be |
109 * saved. | 110 * saved. |
110 * @return whether any minidump was copied. | 111 * @return whether any minidump was copied. |
111 */ | 112 */ |
112 @VisibleForTesting | 113 @VisibleForTesting |
113 public static boolean copyMinidumps(int uid, ParcelFileDescriptor[] fileDesc
riptors) { | 114 public static boolean copyMinidumps( |
114 CrashFileManager crashFileManager = new CrashFileManager(getOrCreateWebV
iewCrashDir()); | 115 Context context, int uid, ParcelFileDescriptor[] fileDescriptors) { |
| 116 CrashFileManager crashFileManager = new CrashFileManager(createWebViewCr
ashDir(context)); |
115 boolean copiedAnything = false; | 117 boolean copiedAnything = false; |
116 if (fileDescriptors != null) { | 118 if (fileDescriptors != null) { |
117 for (ParcelFileDescriptor fd : fileDescriptors) { | 119 for (ParcelFileDescriptor fd : fileDescriptors) { |
118 if (fd == null) continue; | 120 if (fd == null) continue; |
119 try { | 121 try { |
120 File copiedFile = crashFileManager.copyMinidumpFromFD( | 122 File copiedFile = crashFileManager.copyMinidumpFromFD(fd.get
FileDescriptor(), |
121 fd.getFileDescriptor(), getWebViewTmpCrashDir(), uid
); | 123 getWebViewTmpCrashDir(context), uid); |
122 if (copiedFile == null) { | 124 if (copiedFile == null) { |
123 Log.w(TAG, "failed to copy minidump from " + fd.toString
()); | 125 Log.w(TAG, "failed to copy minidump from " + fd.toString
()); |
124 // TODO(gsennton): add UMA metric to ensure we aren't lo
sing too many | 126 // TODO(gsennton): add UMA metric to ensure we aren't lo
sing too many |
125 // minidumps here. | 127 // minidumps here. |
126 } else { | 128 } else { |
127 copiedAnything = true; | 129 copiedAnything = true; |
128 } | 130 } |
129 } catch (IOException e) { | 131 } catch (IOException e) { |
130 Log.w(TAG, "failed to copy minidump from " + fd.toString() +
": " | 132 Log.w(TAG, "failed to copy minidump from " + fd.toString() +
": " |
131 + e.getMessage()); | 133 + e.getMessage()); |
132 } finally { | 134 } finally { |
133 deleteFilesInWebViewTmpDirIfExists(); | 135 deleteFilesInWebViewTmpDirIfExists(context); |
134 } | 136 } |
135 } | 137 } |
136 } | 138 } |
137 return copiedAnything; | 139 return copiedAnything; |
138 } | 140 } |
139 | 141 |
140 /** | 142 /** |
141 * Delete all files in the directory where temporary files from this Service
are stored. | 143 * Delete all files in the directory where temporary files from this Service
are stored. |
142 */ | 144 */ |
143 @VisibleForTesting | 145 @VisibleForTesting |
144 public static void deleteFilesInWebViewTmpDirIfExists() { | 146 public static void deleteFilesInWebViewTmpDirIfExists(Context context) { |
145 deleteFilesInDirIfExists(getWebViewTmpCrashDir()); | 147 deleteFilesInDirIfExists(getWebViewTmpCrashDir(context)); |
146 } | 148 } |
147 | 149 |
148 private static void deleteFilesInDirIfExists(File directory) { | 150 private static void deleteFilesInDirIfExists(File directory) { |
149 if (directory.isDirectory()) { | 151 if (directory.isDirectory()) { |
150 File[] files = directory.listFiles(); | 152 File[] files = directory.listFiles(); |
151 if (files != null) { | 153 if (files != null) { |
152 for (File file : files) { | 154 for (File file : files) { |
153 if (!file.delete()) { | 155 if (!file.delete()) { |
154 Log.w(TAG, "Couldn't delete file " + file.getAbsolutePat
h()); | 156 Log.w(TAG, "Couldn't delete file " + file.getAbsolutePat
h()); |
155 } | 157 } |
156 } | 158 } |
157 } | 159 } |
158 } | 160 } |
159 } | 161 } |
160 | 162 |
161 /** | 163 /** |
162 * Create the directory in which WebView will store its minidumps. | 164 * Create the directory in which WebView will store its minidumps. |
163 * WebView needs a crash directory different from Chrome's to ensure Chrome'
s and WebView's | 165 * WebView needs a crash directory different from Chrome's to ensure Chrome'
s and WebView's |
164 * minidump handling won't clash in cases where both Chrome and WebView are
provided by the | 166 * minidump handling won't clash in cases where both Chrome and WebView are
provided by the |
165 * same app (Monochrome). | 167 * same app (Monochrome). |
| 168 * @param context Android Context used to find a cache-directory where minid
umps can be stored. |
166 * @return a reference to the created directory, or null if the creation fai
led. | 169 * @return a reference to the created directory, or null if the creation fai
led. |
167 */ | 170 */ |
168 @VisibleForTesting | 171 @VisibleForTesting |
169 public static File getOrCreateWebViewCrashDir() { | 172 public static File createWebViewCrashDir(Context context) { |
170 File dir = getWebViewCrashDir(); | 173 File dir = getWebViewCrashDir(context); |
171 // Call mkdir before isDirectory to ensure that if another thread create
d the directory | 174 // Call mkdir before isDirectory to ensure that if another thread create
d the directory |
172 // just before the call to mkdir, the current thread fails mkdir, but pa
sses isDirectory. | 175 // just before the call to mkdir, the current thread fails mkdir, but pa
sses isDirectory. |
173 if (dir.mkdir() || dir.isDirectory()) { | 176 if (dir.mkdir() || dir.isDirectory()) { |
174 return dir; | 177 return dir; |
175 } | 178 } |
176 return null; | 179 return null; |
177 } | 180 } |
178 | 181 |
179 /** | 182 /** |
180 * Fetch the crash directory where WebView stores its minidumps. | 183 * Fetch the crash directory where WebView stores its minidumps. |
| 184 * @param context Android Context used to find a cache-directory where minid
umps can be stored. |
181 * @return a File pointing to the crash directory. | 185 * @return a File pointing to the crash directory. |
182 */ | 186 */ |
183 @VisibleForTesting | 187 @VisibleForTesting |
184 public static File getWebViewCrashDir() { | 188 public static File getWebViewCrashDir(Context context) { |
185 return new File(ContextUtils.getApplicationContext().getCacheDir(), WEBV
IEW_CRASH_DIR); | 189 return new File(context.getCacheDir(), WEBVIEW_CRASH_DIR); |
186 } | 190 } |
187 | 191 |
188 /** | 192 /** |
189 * Directory where we store files temporarily when copying from an app proce
ss. | 193 * Directory where we store files temporarily when copying from an app proce
ss. |
| 194 * @param context Android Context used to find a cache-directory where minid
umps can be stored. |
190 */ | 195 */ |
191 @VisibleForTesting | 196 @VisibleForTesting |
192 public static File getWebViewTmpCrashDir() { | 197 public static File getWebViewTmpCrashDir(Context context) { |
193 return new File(ContextUtils.getApplicationContext().getCacheDir(), WEBV
IEW_TMP_CRASH_DIR); | 198 return new File(context.getCacheDir(), WEBVIEW_TMP_CRASH_DIR); |
194 } | 199 } |
195 | 200 |
196 @Override | 201 @Override |
197 public IBinder onBind(Intent intent) { | 202 public IBinder onBind(Intent intent) { |
198 return mBinder; | 203 return mBinder; |
199 } | 204 } |
200 } | 205 } |
OLD | NEW |