Chromium Code Reviews| 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..8af64d5e610693aafaa4bf763e7f9ffa0787f9b2 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,67 @@ import java.util.zip.ZipInputStream; |
| * Helper methods for file extraction from APK assets and zip archives. |
| */ |
| class FileHelper { |
| + public static final String TAG = "MojoFileHelper"; |
|
ppi
2014/12/22 12:02:25
nit: everything is Mojo in this world, I would pro
qsr
2014/12/22 12:44:19
Everything is mojo, but this is what appear in adb
|
| + |
| // 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-"; |
| - static File extractFromAssets(Context context, String assetName, File outputDirectory, |
| + // Looks for a timestamp file on disk that indicates the version of the APK that |
|
ppi
2014/12/22 12:02:25
Maybe use the javadoc style (matching other per-me
qsr
2014/12/22 12:44:19
Done.
|
| + // the resource paks were extracted from. Returns null if a timestamp was found |
|
ppi
2014/12/22 12:02:25
what is resource pak? should we say "assets", or d
qsr
2014/12/22 12:44:19
Because I copied paste this comment. Fixed.
|
| + // and it indicates that the resources match the current APK. Otherwise returns |
| + // a String that represents the filename of a timestamp to create. |
|
ppi
2014/12/22 12:02:25
This calls for splitting this up - can we extract
qsr
2014/12/22 12:44:19
As discussed, I prefer not to cut this method beca
|
| + private static String checkAssetTimestamp(Context context, File outputDir) { |
| + final String timestampPrefix = "asset_timestamp-"; |
|
ppi
2014/12/22 12:02:25
let's make it private static final field like the
qsr
2014/12/22 12:44:19
Done.
|
| + PackageManager pm = context.getPackageManager(); |
| + PackageInfo pi = null; |
| + |
| + try { |
| + pi = pm.getPackageInfo(context.getPackageName(), 0); |
| + } catch (PackageManager.NameNotFoundException e) { |
| + return timestampPrefix; |
| + } |
| + |
| + if (pi == null) { |
| + return timestampPrefix; |
| + } |
| + |
| + String expectedTimestamp = timestampPrefix + pi.versionCode + "-" + pi.lastUpdateTime; |
| + |
| + String[] timestamps = outputDir.list(new FilenameFilter() { |
| + @Override |
| + public boolean accept(File dir, String name) { |
| + return name.startsWith(timestampPrefix); |
| + } |
| + }); |
| + |
| + 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. |
|
ppi
2014/12/22 12:02:25
nit: capitalize the first word.
qsr
2014/12/22 12:44:20
Done.
|
| + return null; |
| + } |
| + |
| + public static File extractFromAssets(Context context, String assetName, File outputDirectory, |
| boolean useTempFile) throws IOException, FileNotFoundException { |
| + String timestampFile = null; |
| + if (!useTempFile) { |
| + timestampFile = checkAssetTimestamp(context, outputDirectory); |
| + if (timestampFile != null) { |
| + for (File child : outputDirectory.listFiles()) { |
| + deleteRecursively(child); |
| + } |
| + } |
| + } |
| + |
| File outputFile; |
| if (useTempFile) { |
| // Make the original filename part of the temp file name. |
| @@ -37,12 +95,28 @@ 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 (timestampFile != null) { |
| + try { |
| + new File(outputDirectory, timestampFile).createNewFile(); |
| + } catch (IOException e) { |
| + // Worst case we don't write a timestamp, so we'll re-extract the asset next time. |
|
ppi
2014/12/22 12:02:25
nit: s/Worst case/In the worst case/
qsr
2014/12/22 12:44:19
Done.
|
| + Log.w(TAG, "Failed to write asset timestamp!"); |
| + } |
| + } |
| + |
| return outputFile; |
| } |
| @@ -87,10 +161,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(); |
| } |
| } |