Index: shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java |
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java b/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java |
index adc747e4756970f5033091c2aa36c4c04d0ec9f4..3769fd9cad848ee9e306b61ee5ffc8abca4bb712 100644 |
--- a/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java |
+++ b/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java |
@@ -5,6 +5,9 @@ |
package org.chromium.mojo.shell; |
import android.content.Context; |
+import android.content.pm.PackageInfo; |
+import android.content.pm.PackageManager; |
+import android.util.Log; |
import java.io.BufferedInputStream; |
import java.io.BufferedOutputStream; |
@@ -12,6 +15,7 @@ import java.io.File; |
import java.io.FileInputStream; |
import java.io.FileNotFoundException; |
import java.io.FileOutputStream; |
+import java.io.FilenameFilter; |
import java.io.IOException; |
import java.io.InputStream; |
import java.io.OutputStream; |
@@ -22,13 +26,70 @@ import java.util.zip.ZipInputStream; |
* Helper methods for file extraction from APK assets and zip archives. |
*/ |
class FileHelper { |
+ public static final String TAG = "MojoFileHelper"; |
+ |
// Size of the buffer used in streaming file operations. |
private static final int BUFFER_SIZE = 1024 * 1024; |
// Prefix used when naming temporary files. |
private static final String TEMP_FILE_PREFIX = "temp-"; |
+ // Prefix used when naming timestamp files. |
+ private static final String TIMESTAMP_PREFIX = "asset_timestamp-"; |
+ |
+ /** |
+ * Looks for a timestamp file on disk that indicates the version of the APK that the resource |
+ * assets were extracted from. Returns null if a timestamp was found and it indicates that the |
+ * resources match the current APK. Otherwise returns a String that represents the filename of a |
+ * timestamp to create. |
+ */ |
+ private static String checkAssetTimestamp(Context context, File outputDir) { |
+ PackageManager pm = context.getPackageManager(); |
+ PackageInfo pi = null; |
+ |
+ try { |
+ pi = pm.getPackageInfo(context.getPackageName(), 0); |
+ } catch (PackageManager.NameNotFoundException e) { |
+ return TIMESTAMP_PREFIX; |
+ } |
+ |
+ if (pi == null) { |
+ return TIMESTAMP_PREFIX; |
+ } |
+ |
+ String expectedTimestamp = TIMESTAMP_PREFIX + pi.versionCode + "-" + pi.lastUpdateTime; |
+ |
+ String[] timestamps = outputDir.list(new FilenameFilter() { |
+ @Override |
+ public boolean accept(File dir, String name) { |
+ return name.startsWith(TIMESTAMP_PREFIX); |
+ } |
+ }); |
- static File extractFromAssets(Context context, String assetName, File outputDirectory, |
+ if (timestamps.length != 1) { |
+ // If there's no timestamp, nuke to be safe as we can't tell the age of the files. |
+ // If there's multiple timestamps, something's gone wrong so nuke. |
+ return expectedTimestamp; |
+ } |
+ |
+ if (!expectedTimestamp.equals(timestamps[0])) { |
+ return expectedTimestamp; |
+ } |
+ |
+ // Timestamp file is already up-to date. |
+ return null; |
+ } |
+ |
+ public static File extractFromAssets(Context context, String assetName, File outputDirectory, |
boolean useTempFile) throws IOException, FileNotFoundException { |
+ String timestampToCreate = null; |
+ if (!useTempFile) { |
+ timestampToCreate = checkAssetTimestamp(context, outputDirectory); |
+ if (timestampToCreate != null) { |
+ for (File child : outputDirectory.listFiles()) { |
+ deleteRecursively(child); |
+ } |
+ } |
+ } |
+ |
File outputFile; |
if (useTempFile) { |
// Make the original filename part of the temp file name. |
@@ -37,12 +98,29 @@ class FileHelper { |
outputFile = File.createTempFile(TEMP_FILE_PREFIX, suffix, outputDirectory); |
} else { |
outputFile = new File(outputDirectory, assetName); |
+ if (outputFile.exists()) { |
+ return outputFile; |
+ } |
} |
BufferedInputStream inputStream = new BufferedInputStream( |
context.getAssets().open(assetName)); |
- writeStreamToFile(inputStream, outputFile); |
- inputStream.close(); |
+ try { |
+ writeStreamToFile(inputStream, outputFile); |
+ } finally { |
+ inputStream.close(); |
+ } |
+ |
+ if (timestampToCreate != null) { |
+ try { |
+ new File(outputDirectory, timestampToCreate).createNewFile(); |
+ } catch (IOException e) { |
+ // In the worst case we don't write a timestamp, so we'll re-extract the asset next |
+ // time. |
+ Log.w(TAG, "Failed to write asset timestamp!"); |
+ } |
+ } |
+ |
return outputFile; |
} |
@@ -87,10 +165,13 @@ class FileHelper { |
throws IOException { |
byte[] buffer = new byte[BUFFER_SIZE]; |
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile)); |
- int read; |
- while ((read = inputStream.read(buffer, 0, BUFFER_SIZE)) > 0) { |
- outputStream.write(buffer, 0, read); |
+ try { |
+ int read; |
+ while ((read = inputStream.read(buffer, 0, BUFFER_SIZE)) > 0) { |
+ outputStream.write(buffer, 0, read); |
+ } |
+ } finally { |
+ outputStream.close(); |
} |
- outputStream.close(); |
} |
} |