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