mobile/android/base/util/GeckoJarReader.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko.util;
     7 import org.mozilla.gecko.mozglue.NativeZip;
     9 import android.content.res.Resources;
    10 import android.graphics.Bitmap;
    11 import android.graphics.drawable.BitmapDrawable;
    12 import android.util.Log;
    13 import org.mozilla.gecko.mozglue.RobocopTarget;
    15 import java.io.BufferedReader;
    16 import java.io.IOException;
    17 import java.io.InputStream;
    18 import java.io.InputStreamReader;
    19 import java.net.URI;
    20 import java.net.URISyntaxException;
    21 import java.util.Stack;
    23 /* Reads out of a multiple level deep jar file such as
    24  *  jar:jar:file:///data/app/org.mozilla.fennec.apk!/omni.ja!/chrome/chrome/content/branding/favicon32.png
    25  */
    26 public final class GeckoJarReader {
    27     private static final String LOGTAG = "GeckoJarReader";
    29     private GeckoJarReader() {}
    31     public static Bitmap getBitmap(Resources resources, String url) {
    32         BitmapDrawable drawable = getBitmapDrawable(resources, url);
    33         return (drawable != null) ? drawable.getBitmap() : null;
    34     }
    36     public static BitmapDrawable getBitmapDrawable(Resources resources, String url) {
    37         Stack<String> jarUrls = parseUrl(url);
    38         InputStream inputStream = null;
    39         BitmapDrawable bitmap = null;
    41         NativeZip zip = null;
    42         try {
    43             // Load the initial jar file as a zip
    44             zip = getZipFile(jarUrls.pop());
    45             inputStream = getStream(zip, jarUrls, url);
    46             if (inputStream != null) {
    47                 bitmap = new BitmapDrawable(resources, inputStream);
    48             }
    49         } catch (IOException ex) {
    50             Log.e(LOGTAG, "Exception ", ex);
    51         } catch (URISyntaxException ex) {
    52             Log.e(LOGTAG, "Exception ", ex);
    53         } finally {
    54             if (inputStream != null) {
    55                 try {
    56                     inputStream.close();
    57                 } catch(IOException ex) {
    58                     Log.e(LOGTAG, "Error closing stream", ex);
    59                 }
    60             }
    61             if (zip != null) {
    62                 zip.close();
    63             }
    64         }
    66         return bitmap;
    67     }
    69     public static String getText(String url) {
    70         Stack<String> jarUrls = parseUrl(url);
    72         NativeZip zip = null;
    73         BufferedReader reader = null;
    74         String text = null;
    75         try {
    76             zip = getZipFile(jarUrls.pop());
    77             InputStream input = getStream(zip, jarUrls, url);
    78             if (input != null) {
    79                 reader = new BufferedReader(new InputStreamReader(input));
    80                 text = reader.readLine();
    81             }
    82         } catch (IOException ex) {
    83             Log.e(LOGTAG, "Exception ", ex);
    84         } catch (URISyntaxException ex) {
    85             Log.e(LOGTAG, "Exception ", ex);
    86         } finally {
    87             if (reader != null) {
    88                 try {
    89                     reader.close();
    90                 } catch(IOException ex) {
    91                     Log.e(LOGTAG, "Error closing reader", ex);
    92                 }
    93             }
    94             if (zip != null) {
    95                 zip.close();
    96             }
    97         }
    99         return text;
   100     }
   102     private static NativeZip getZipFile(String url) throws IOException, URISyntaxException {
   103         URI fileUrl = new URI(url);
   104         return new NativeZip(fileUrl.getPath());
   105     }
   107     @RobocopTarget
   108     public static InputStream getStream(String url) {
   109         Stack<String> jarUrls = parseUrl(url);
   110         try {
   111             NativeZip zip = getZipFile(jarUrls.pop());
   112             return getStream(zip, jarUrls, url);
   113         } catch (Exception ex) {
   114             // Some JNI code throws IllegalArgumentException on a bad file name;
   115             // swallow the error and return null.  We could also see legitimate
   116             // IOExceptions here.
   117             return null;
   118         }
   119     }
   121     private static InputStream getStream(NativeZip zip, Stack<String> jarUrls, String origUrl) {
   122         InputStream inputStream = null;
   124         // loop through children jar files until we reach the innermost one
   125         while (!jarUrls.empty()) {
   126             String fileName = jarUrls.pop();
   128             if (inputStream != null) {
   129                 // intermediate NativeZips and InputStreams will be garbage collected.
   130                 try {
   131                     zip = new NativeZip(inputStream);
   132                 } catch (IllegalArgumentException e) {
   133                     String description = "!!! BUG 849589 !!! origUrl=" + origUrl;
   134                     Log.e(LOGTAG, description, e);
   135                     throw new IllegalArgumentException(description);
   136                 }
   137             }
   139             inputStream = zip.getInputStream(fileName);
   140             if (inputStream == null) {
   141                 Log.d(LOGTAG, "No Entry for " + fileName);
   142                 return null;
   143             }
   144         }
   146         return inputStream;
   147     }
   149     /* Returns a stack of strings breaking the url up into pieces. Each piece
   150      * is assumed to point to a jar file except for the final one. Callers should
   151      * pass in the url to parse, and null for the parent parameter (used for recursion)
   152      * For example, jar:jar:file:///data/app/org.mozilla.fennec.apk!/omni.ja!/chrome/chrome/content/branding/favicon32.png
   153      * will return:
   154      *    file:///data/app/org.mozilla.fennec.apk
   155      *    omni.ja
   156      *    chrome/chrome/content/branding/favicon32.png
   157      */
   158     private static Stack<String> parseUrl(String url) {
   159         return parseUrl(url, null);
   160     }
   162     private static Stack<String> parseUrl(String url, Stack<String> results) {
   163         if (results == null) {
   164             results = new Stack<String>();
   165         }
   167         if (url.startsWith("jar:")) {
   168             int jarEnd = url.lastIndexOf("!");
   169             String subStr = url.substring(4, jarEnd);
   170             results.push(url.substring(jarEnd+2)); // remove the !/ characters
   171             return parseUrl(subStr, results);
   172         } else {
   173             results.push(url);
   174             return results;
   175         }
   176     }
   177 }

mercurial