Bug 709250 - Add the ability to read nested jar files. r=mfinkle,lucasr

This commit is contained in:
Wes Johnston 2012-03-22 11:11:49 -07:00
Родитель c0fb2597a3
Коммит 92f07743eb
3 изменённых файлов: 128 добавлений и 1 удалений

Просмотреть файл

@ -51,6 +51,7 @@ import android.util.Log;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.URLConnection;
import java.net.HttpURLConnection;
@ -294,7 +295,17 @@ public class Favicons {
image = (BitmapDrawable) Drawable.createFromStream(byteStream, "src");
}
} catch (Exception e) {
Log.d(LOGTAG, "Error downloading favicon: " + e);
// Trying to read icons from nested jar files will fail
if (mFaviconUrl.startsWith("jar:jar:")) {
InputStream stream = GeckoJarReader.getStream(mFaviconUrl);
if (stream != null) {
image = new BitmapDrawable(stream);
} else {
Log.d(LOGTAG, "Error getting favicon from jar: " + e);
}
} else {
Log.d(LOGTAG, "Error downloading favicon: " + e);
}
} finally {
if (urlConnection != null && urlConnection instanceof HttpURLConnection) {
HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;

Просмотреть файл

@ -0,0 +1,115 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import java.io.File;
import java.net.URL;
import java.util.EmptyStackException;
import java.util.Stack;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipEntry;
import java.io.InputStream;
import java.io.IOException;
import android.util.Log;
/* Reads out of a multiple level deep jar file such as
* jar:jar:file:///data/app/org.mozilla.fennec.apk!/omni.ja!/chrome/chrome/content/branding/favicon32.png
*/
public class GeckoJarReader {
static private String LOGTAG = "GeckoJarReader";
static public InputStream getStream(String url) {
Stack<String> jarUrls = parseUrl(url);
ZipInputStream inputStream = null;
try {
// Load the initial jar file as a zip
URL fileUrl = new URL(jarUrls.pop());
File file = new File(fileUrl.getPath());
ZipFile zip = new ZipFile(file);
ZipEntry entry = null;
// loop through children jar files until we reach the innermost one
while (jarUrls.peek() != null) {
String fileName = jarUrls.pop();
if (inputStream != null) {
entry = getEntryFromStream(inputStream, fileName);
} else {
entry = zip.getEntry(fileName);
}
// if there is nothing else on the stack, this will throw and break us out of the loop
jarUrls.peek();
if (inputStream != null) {
inputStream = new ZipInputStream(inputStream);
} else {
inputStream = new ZipInputStream(zip.getInputStream(entry));
}
if (entry == null) {
Log.d(LOGTAG, "No Entry for " + fileName);
return null;
}
}
} catch (EmptyStackException ex) {
Log.d(LOGTAG, "Reached Jar reader reached end of stack");
} catch (IOException ex) {
Log.e(LOGTAG, "Exception ", ex);
} catch (Exception ex) {
Log.e(LOGTAG, "Exception ", ex);
}
return inputStream;
}
/* Searches through a ZipInputStream for an entry with a given name */
static private ZipEntry getEntryFromStream(ZipInputStream zipStream, String entryName) {
ZipEntry entry = null;
try {
entry = zipStream.getNextEntry();
while(entry != null && !entry.getName().equals(entryName)) {
entry = zipStream.getNextEntry();
}
} catch (IOException ex) {
Log.e(LOGTAG, "Exception getting stream entry", ex);
}
return entry;
}
/* Returns a stack of strings breaking the url up into pieces. Each piece
* is assumed to point to a jar file except for the final one. Callers should
* pass in the url to parse, and null for the parent parameter (used for recursion)
* For example, jar:jar:file:///data/app/org.mozilla.fennec.apk!/omni.ja!/chrome/chrome/content/branding/favicon32.png
* will return:
* file:///data/app/org.mozilla.fennec.apk
* omni.ja
* chrome/chrome/content/branding/favicon32.png
*/
static private Stack<String> parseUrl(String url) {
return parseUrl(url, null);
}
static private Stack<String> parseUrl(String url, Stack<String> results) {
if (results == null) {
results = new Stack<String>();
}
if (url.startsWith("jar:")) {
int jarEnd = url.lastIndexOf("!");
String subStr = url.substring(4, jarEnd);
results.push(url.substring(jarEnd+2)); // remove the !/ characters
return parseUrl(subStr, results);
} else {
results.push(url);
return results;
}
}
}

Просмотреть файл

@ -90,6 +90,7 @@ FENNEC_JAVA_FILES = \
GeckoEventResponder.java \
GeckoHalDefines.java \
GeckoInputConnection.java \
GeckoJarReader.java \
GeckoMessageReceiver.java \
GeckoPreferences.java \
GeckoProfile.java \