Index: chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastCrashUploader.java |
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastCrashUploader.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastCrashUploader.java |
index 4f0b144b60dfd493f2cc7bedc141594b1d1c4480..5f40480f658e9be8430076bcf653f66bb4863d42 100644 |
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastCrashUploader.java |
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastCrashUploader.java |
@@ -4,23 +4,20 @@ |
package org.chromium.chromecast.shell; |
-import android.net.http.AndroidHttpClient; |
-import android.util.Log; |
- |
-import org.apache.http.HttpHost; |
-import org.apache.http.HttpResponse; |
-import org.apache.http.HttpStatus; |
-import org.apache.http.client.methods.HttpPost; |
-import org.apache.http.entity.InputStreamEntity; |
+import org.chromium.base.Log; |
import java.io.BufferedReader; |
import java.io.ByteArrayInputStream; |
import java.io.File; |
import java.io.FileInputStream; |
+import java.io.FileNotFoundException; |
import java.io.IOException; |
import java.io.InputStream; |
import java.io.InputStreamReader; |
+import java.io.OutputStream; |
import java.io.SequenceInputStream; |
+import java.net.HttpURLConnection; |
+import java.net.URL; |
import java.util.LinkedList; |
import java.util.concurrent.ExecutionException; |
import java.util.concurrent.Executors; |
@@ -37,7 +34,7 @@ import java.util.concurrent.TimeUnit; |
* explicitly blocks any post-dump hooks or uploading for Android builds. |
*/ |
public final class CastCrashUploader { |
- private static final String TAG = "CastCrashUploader"; |
+ private static final String TAG = Log.makeTag("CastCrashUploader"); |
private static final String CRASH_REPORT_HOST = "clients2.google.com"; |
private static final String CAST_SHELL_USER_AGENT = android.os.Build.MODEL + "/CastShell"; |
// Multipart dump filename has format "[random string].dmp[pid]", e.g. |
@@ -93,10 +90,9 @@ public final class CastCrashUploader { |
*/ |
private void queueAllCrashDumpUploads(boolean synchronous, String logFile) { |
if (mCrashDumpPath == null) return; |
- Log.d(TAG, "Checking for crash dumps"); |
+ Log.i(TAG, "Checking for crash dumps"); |
LinkedList<Future> tasks = new LinkedList<Future>(); |
- final AndroidHttpClient httpClient = AndroidHttpClient.newInstance(CAST_SHELL_USER_AGENT); |
File crashDumpDirectory = new File(mCrashDumpPath); |
for (File potentialDump : crashDumpDirectory.listFiles()) { |
String dumpName = potentialDump.getName(); |
@@ -111,23 +107,15 @@ public final class CastCrashUploader { |
} |
// Check if the dump we found has pid matching this process, and if so include |
// this process's log. |
- // TODO(kjoswiak): Currently, logs are lost if dump cannot be uploaded right away. |
+ // TODO(gunsch): Currently, logs are lost if dump cannot be uploaded right away. |
if (dumpPid == android.os.Process.myPid()) { |
- tasks.add(queueCrashDumpUpload(httpClient, potentialDump, new File(logFile))); |
+ tasks.add(queueCrashDumpUpload(potentialDump, new File(logFile))); |
} else { |
- tasks.add(queueCrashDumpUpload(httpClient, potentialDump, null)); |
+ tasks.add(queueCrashDumpUpload(potentialDump, null)); |
} |
} |
} |
- // When finished uploading all of the queued dumps, release httpClient |
- tasks.add(mExecutorService.submit(new Runnable() { |
- @Override |
- public void run() { |
- httpClient.close(); |
- } |
- })); |
- |
// Wait on tasks, if necessary. |
if (synchronous) { |
for (Future task : tasks) { |
@@ -142,12 +130,11 @@ public final class CastCrashUploader { |
/** |
* Enqueues a background task to upload a single crash dump file. |
*/ |
- private Future queueCrashDumpUpload(final AndroidHttpClient httpClient, final File dumpFile, |
- final File logFile) { |
+ private Future queueCrashDumpUpload(final File dumpFile, final File logFile) { |
return mExecutorService.submit(new Runnable() { |
@Override |
public void run() { |
- Log.d(TAG, "Uploading dump crash log: " + dumpFile.getName()); |
+ Log.i(TAG, "Uploading dump crash log: %s", dumpFile.getName()); |
try { |
InputStream uploadCrashDumpStream = new FileInputStream(dumpFile); |
@@ -161,7 +148,7 @@ public final class CastCrashUploader { |
String mimeBoundary = dumpFirstLine.substring(2); |
if (logFile != null) { |
- Log.d(TAG, "Including log file: " + logFile.getName()); |
+ Log.i(TAG, "Including log file: %s", logFile.getName()); |
StringBuffer logHeader = new StringBuffer(); |
logHeader.append(dumpFirstLine); |
logHeader.append("\n"); |
@@ -178,49 +165,80 @@ public final class CastCrashUploader { |
uploadCrashDumpStream); |
} |
- InputStreamEntity entity = new InputStreamEntity(uploadCrashDumpStream, -1); |
- entity.setContentType("multipart/form-data; boundary=" + mimeBoundary); |
- |
- HttpPost uploadRequest = new HttpPost(mCrashReportUploadUrl); |
- uploadRequest.setEntity(entity); |
- HttpResponse response = |
- httpClient.execute(new HttpHost(CRASH_REPORT_HOST), uploadRequest); |
+ HttpURLConnection connection = |
+ (HttpURLConnection) new URL(mCrashReportUploadUrl).openConnection(); |
// Expect a report ID as the entire response |
- String responseLine = getFirstLine(response.getEntity().getContent()); |
+ try { |
+ connection.setDoOutput(true); |
+ connection.setRequestProperty("Content-Type", |
+ "multipart/form-data; boundary=" + mimeBoundary); |
+ streamCopy(uploadCrashDumpStream, connection.getOutputStream()); |
+ |
+ String responseLine = getFirstLine(connection.getInputStream()); |
- int statusCode = response.getStatusLine().getStatusCode(); |
- if (statusCode == HttpStatus.SC_OK) { |
- Log.d(TAG, "Successfully uploaded to " + mCrashReportUploadUrl |
- + ", report ID: " + responseLine); |
- } else { |
- Log.e(TAG, "Failed response (" + statusCode + "): " + responseLine); |
+ int responseCode = connection.getResponseCode(); |
+ if (responseCode == HttpURLConnection.HTTP_OK |
+ || responseCode == HttpURLConnection.HTTP_CREATED |
+ || responseCode == HttpURLConnection.HTTP_ACCEPTED) { |
+ Log.i(TAG, "Successfully uploaded to %s, report ID: %s", |
+ mCrashReportUploadUrl, responseLine); |
+ } else { |
+ Log.e(TAG, "Failed response (%d): %s", responseCode, |
+ connection.getResponseMessage()); |
- // 400 Bad Request is returned if the dump file is malformed. If requeset |
- // is not malformed, shortcircuit before clean up to avoid deletion and |
- // retry later, otherwise pass through and delete malformed file |
- if (statusCode != HttpStatus.SC_BAD_REQUEST) { |
- return; |
+ // 400 Bad Request is returned if the dump file is malformed. If request |
+ // is not malformed, short-circuit before cleanup to avoid deletion and |
+ // retry later, otherwise pass through and delete malformed file. |
+ if (responseCode != HttpURLConnection.HTTP_BAD_REQUEST) { |
+ return; |
+ } |
+ } |
+ } catch (FileNotFoundException fnfe) { |
+ // Android's HttpURLConnection implementation fires FNFE on some errors. |
+ Log.e(TAG, "Failed response: " + connection.getResponseCode(), fnfe); |
+ } finally { |
+ connection.disconnect(); |
+ dumpFileStream.close(); |
+ if (logFileStream != null) { |
+ logFileStream.close(); |
} |
} |
// Delete the file so we don't re-upload it next time. |
- uploadCrashDumpStream.close(); |
- dumpFileStream.close(); |
dumpFile.delete(); |
if (logFile != null && logFile.exists()) { |
- logFileStream.close(); |
logFile.delete(); |
} |
} catch (IOException e) { |
- Log.e(TAG, "File I/O error trying to upload crash dump", e); |
+ Log.e(TAG, "Error occurred trying to upload crash dump", e); |
} |
} |
}); |
} |
/** |
+ * Copies all available data from |inStream| to |outStream|. Closes both |
+ * streams when done. |
+ * |
+ * @param inStream the stream to read |
+ * @param outStream the stream to write to |
+ * @throws IOException |
+ */ |
+ private static void streamCopy(InputStream inStream, |
+ OutputStream outStream) throws IOException { |
+ byte[] temp = new byte[4096]; |
+ int bytesRead = inStream.read(temp); |
+ while (bytesRead >= 0) { |
+ outStream.write(temp, 0, bytesRead); |
+ bytesRead = inStream.read(temp); |
+ } |
+ inStream.close(); |
+ outStream.close(); |
+ } |
+ |
+ /** |
* Gets the first line from an input stream, opening and closing readers to do so. |
* We're targeting Java 6, so this is still tedious to do. |
* @return First line of the input stream. |