Bug 738421 - Close up ZipReader. r=cpeterson
authorWes Johnston <wjohnston@mozilla.com>
Fri, 23 Mar 2012 17:07:10 -0700
changeset 93540 71f36268b7de38a098ae249a568453e7e9f68c65
parent 93539 dc11394d4693e3e10dcc4dcb67e1b29d7f0cb1c5
child 93541 f9f96c36c7419f737feaa5e510a0d2931c00ec2b
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpeterson
bugs738421
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 738421 - Close up ZipReader. r=cpeterson
mobile/android/base/Favicons.java
mobile/android/base/GeckoJarReader.java
--- a/mobile/android/base/Favicons.java
+++ b/mobile/android/base/Favicons.java
@@ -269,16 +269,20 @@ public class Favicons {
             }
         }
 
         // Runs in background thread
         private BitmapDrawable downloadFavicon(URL faviconUrl) {
             Log.d(LOGTAG, "Downloading favicon for URL = " + mPageUrl +
                           " with favicon URL = " + mFaviconUrl);
 
+            if (mFaviconUrl.startsWith("jar:jar:")) {
+                return GeckoJarReader.getBitmapDrawable(mFaviconUrl);
+            }
+
             // due to android bug 6066, we must download the entire image before using it
             // http://code.google.com/p/android/issues/detail?id=6066
             URLConnection urlConnection = null;
             BufferedInputStream contentStream = null;
             ByteArrayInputStream byteStream = null;
             BitmapDrawable image = null;
 
             try {
@@ -289,39 +293,36 @@ public class Favicons {
                 int pos = 0;
                 int offset = 0;
                 while ((pos = contentStream.read(bytes, offset, length - offset)) > 0)
                     offset += pos;
                 if (length == offset) {
                     byteStream = new ByteArrayInputStream(bytes);
                     image = (BitmapDrawable) Drawable.createFromStream(byteStream, "src");
                 }
+            } catch (IOException e) {
+                // just close up and return null
             } catch (Exception e) {
-                Log.e(LOGTAG, "Error downloading favicon", e);
+                Log.e(LOGTAG, "Error reading favicon", e);
             } finally {
                 if (urlConnection != null && urlConnection instanceof HttpURLConnection) {
                     HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
                     httpConnection.disconnect();
                 }
 
                 try {
                     if (contentStream != null)
                         contentStream.close();
                     if (byteStream != null)
                         byteStream.close();
                 } catch (IOException e) {
                     Log.d(LOGTAG, "error closing favicon stream");
                 }
             }
 
-            if (image != null) {
-                Log.d(LOGTAG, "Downloaded favicon successfully for URL = " + mPageUrl);
-                saveFaviconToDb(image);
-            }
-
             return image;
         }
 
         @Override
         protected BitmapDrawable doInBackground(Void... unused) {
             BitmapDrawable image = null;
 
             if (isCancelled())
@@ -368,16 +369,21 @@ public class Favicons {
                 // stored in the database for some reason, we force download.
                 if (image == null) {
                     image = downloadFavicon(faviconUrl);
                 }
             } else {
                 image = downloadFavicon(faviconUrl);
             }
 
+            if (image != null) {
+                Log.d(LOGTAG, "Downloaded favicon successfully for URL = " + mPageUrl);
+                saveFaviconToDb(image);
+            }
+
             return image;
         }
 
         @Override
         protected void onPostExecute(final BitmapDrawable image) {
             Log.d(LOGTAG, "LoadFaviconTask finished for URL = " + mPageUrl +
                           " (" + mId + ")");
 
--- a/mobile/android/base/GeckoJarReader.java
+++ b/mobile/android/base/GeckoJarReader.java
@@ -9,36 +9,70 @@ 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.graphics.drawable.BitmapDrawable;
 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";
+    private static String LOGTAG = "GeckoJarReader";
 
-    static public InputStream getStream(String url) {
+    public static BitmapDrawable getBitmapDrawable(String url) {
         Stack<String> jarUrls = parseUrl(url);
-        ZipInputStream inputStream = null;
+        InputStream inputStream = null;
+        BitmapDrawable bitmap = null;
 
         ZipFile zip = null;
         try {
             // Load the initial jar file as a zip
-            URL fileUrl = new URL(jarUrls.pop());
-            File file = new File(fileUrl.getPath());
-            zip = new ZipFile(file);
-            ZipEntry entry = null;
+            zip = getZipFile(jarUrls.pop());
+            inputStream = getStream(zip, jarUrls);
+            if (inputStream != null) {
+                bitmap = new BitmapDrawable(inputStream);
+            }
+        } catch (IOException ex) {
+            Log.e(LOGTAG, "Exception ", ex);
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch(IOException ex) {
+                    Log.e(LOGTAG, "Error closing stream", ex);
+                }
+            }
+            if (zip != null) {
+                try {
+                    zip.close();
+                } catch(IOException ex) {
+                    Log.e(LOGTAG, "Error closing zip", ex);
+                }
+            }
+        }
 
+        return bitmap;
+    }
+
+    private static ZipFile getZipFile(String url) throws IOException {
+        URL fileUrl = new URL(url);
+        File file = new File(fileUrl.getPath());
+        return new ZipFile(file);
+    }
+
+    private static InputStream getStream(ZipFile zip, Stack<String> jarUrls) throws IOException {
+        ZipInputStream inputStream = null;
+        ZipEntry entry = null;
+        try {
             // 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);
@@ -54,36 +88,23 @@ public class GeckoJarReader {
                 }
   
                 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);
-        } finally {
-            if (zip != null) {
-                try {
-                    zip.close();
-                } catch(IOException ex) {
-                    Log.e(LOGTAG, "Error closing zip", ex);
-                }
-            }
+            Log.d(LOGTAG, "Jar reader reached end of stack");
         }
-
         return inputStream;
     }
 
     /* Searches through a ZipInputStream for an entry with a given name */
-    static private ZipEntry getEntryFromStream(ZipInputStream zipStream, String entryName) {
+    private static 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) {
@@ -97,21 +118,21 @@ public class GeckoJarReader {
      * 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) {
+    private static Stack<String> parseUrl(String url) {
         return parseUrl(url, null);
     }
 
-    static private Stack<String> parseUrl(String url, Stack<String> results) {
+    private static 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