Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Unified Diff: mojo/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java

Issue 1049993002: Get mojo_shell building inside chromium checkout. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix presubmit Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java b/mojo/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..c455251559f35f3d5cece6872935792b9878cedb
--- /dev/null
+++ b/mojo/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java
@@ -0,0 +1,179 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+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;
+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;
+import java.util.zip.ZipEntry;
+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);
+ }
+ });
+
+ 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.
+ // TODO(ppi): do we need to sanitize the suffix?
+ String suffix = "-" + assetName;
+ 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));
+ 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;
+ }
+
+ /**
+ * Extracts the file of the given extension from the archive. Throws FileNotFoundException if no
+ * matching file is found.
+ */
+ static File extractFromArchive(File archive, String suffixToMatch,
+ File outputDirectory) throws IOException, FileNotFoundException {
+ ZipInputStream zip = new ZipInputStream(new BufferedInputStream(new FileInputStream(
+ archive)));
+ ZipEntry entry;
+ while ((entry = zip.getNextEntry()) != null) {
+ if (entry.getName().endsWith(suffixToMatch)) {
+ // Make the original filename part of the temp file name.
+ // TODO(ppi): do we need to sanitize the suffix?
+ String suffix = "-" + new File(entry.getName()).getName();
+ File extractedFile = File.createTempFile(TEMP_FILE_PREFIX, suffix,
+ outputDirectory);
+ writeStreamToFile(zip, extractedFile);
+ zip.close();
+ return extractedFile;
+ }
+ }
+ zip.close();
+ throw new FileNotFoundException();
+ }
+
+ /**
+ * Deletes a file or directory. Directory will be deleted even if not empty.
+ */
+ static void deleteRecursively(File file) {
+ if (file.isDirectory()) {
+ for (File child : file.listFiles()) {
+ deleteRecursively(child);
+ }
+ }
+ if (!file.delete()) {
+ Log.w(TAG, "Unable to delete file: " + file.getAbsolutePath());
+ }
+ }
+
+ private static void writeStreamToFile(InputStream inputStream, File outputFile)
+ throws IOException {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
+ try {
+ int read;
+ while ((read = inputStream.read(buffer, 0, BUFFER_SIZE)) > 0) {
+ outputStream.write(buffer, 0, read);
+ }
+ } finally {
+ outputStream.close();
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698