Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd5c823e authored by Grace Kloba's avatar Grace Kloba
Browse files

Add "res" support for WebView.

parent 8c7ab034
Loading
Loading
Loading
Loading
+81 −8
Original line number Diff line number Diff line
@@ -23,9 +23,12 @@ import android.content.res.AssetManager;
import android.net.http.EventHandler;
import android.net.http.Headers;
import android.os.Environment;
import android.util.Log;
import android.util.TypedValue;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;

/**
 * This class is a concrete implementation of StreamLoader that uses a
@@ -35,10 +38,19 @@ import java.io.FileInputStream;
class FileLoader extends StreamLoader {

    private String mPath;  // Full path to the file to load
    private Context mContext;  // Application context, used for asset loads
    private boolean mIsAsset;  // Indicates if the load is an asset or not
    private Context mContext;  // Application context, used for asset/res loads
    private int mType;  // Indicates the type of the load
    private boolean mAllowFileAccess; // Allow/block file system access

    // used for files under asset directory
    static final int TYPE_ASSET = 1;
    // used for files under res directory
    static final int TYPE_RES = 2;
    // generic file
    static final int TYPE_FILE = 3;

    private static final String LOGTAG = "webkit";

    /**
     * Construct a FileLoader with the file URL specified as the content
     * source.
@@ -51,19 +63,24 @@ class FileLoader extends StreamLoader {
     *                        on the file system.
     */
    FileLoader(String url, LoadListener loadListener, Context context,
            boolean asset, boolean allowFileAccess) {
            int type, boolean allowFileAccess) {
        super(loadListener);
        mIsAsset = asset;
        mType = type;
        mContext = context;
        mAllowFileAccess = allowFileAccess;

        // clean the Url
        int index = url.indexOf('?');
        if (mIsAsset) {
        if (mType == TYPE_ASSET) {
            mPath = index > 0 ? URLUtil.stripAnchor(
                    url.substring(URLUtil.ASSET_BASE.length(), index)) :
                    URLUtil.stripAnchor(url.substring(
                            URLUtil.ASSET_BASE.length()));
        } else if (mType == TYPE_RES) {
            mPath = index > 0 ? URLUtil.stripAnchor(
                    url.substring(URLUtil.RESOURCE_BASE.length(), index)) :
                    URLUtil.stripAnchor(url.substring(
                            URLUtil.RESOURCE_BASE.length()));
        } else {
            mPath = index > 0 ? URLUtil.stripAnchor(
                    url.substring(URLUtil.FILE_BASE.length(), index)) :
@@ -84,13 +101,69 @@ class FileLoader extends StreamLoader {
    @Override
    protected boolean setupStreamAndSendStatus() {
        try {
            if (mIsAsset) {
            if (mType == TYPE_ASSET) {
                try {
                    mDataStream = mContext.getAssets().open(mPath);
                } catch (java.io.FileNotFoundException ex) {
                    // try the rest files included in the package
                    mDataStream = mContext.getAssets().openNonAsset(mPath);
                }
            } else if (mType == TYPE_RES) {
                // get the resource id from the path. e.g. for the path like
                // drawable/foo.png, the id is located at field "foo" of class
                // "<package>.R$drawable"
                if (mPath == null || mPath.length() == 0) {
                    Log.e(LOGTAG, "Need a path to resolve the res file");
                    mHandler.error(EventHandler.FILE_ERROR, mContext
                            .getString(R.string.httpErrorFileNotFound));
                    return false;

                }
                int slash = mPath.indexOf('/');
                int dot = mPath.indexOf('.', slash);
                if (slash == -1 || dot == -1) {
                    Log.e(LOGTAG, "Incorrect res path: " + mPath);
                    mHandler.error(EventHandler.FILE_ERROR, mContext
                            .getString(R.string.httpErrorFileNotFound));
                    return false;
                }
                String subClassName = mPath.substring(0, slash);
                String fieldName = mPath.substring(slash + 1, dot);
                String errorMsg = null;
                try {
                    final Class<?> d = mContext.getApplicationContext()
                            .getClassLoader().loadClass(
                                    mContext.getPackageName() + ".R$"
                                            + subClassName);
                    final Field field = d.getField(fieldName);
                    final int id = field.getInt(null);
                    TypedValue value = new TypedValue();
                    mContext.getResources().getValue(id, value, true);
                    if (value.type == TypedValue.TYPE_STRING) {
                        mDataStream = mContext.getAssets().openNonAsset(
                                value.assetCookie, value.string.toString(),
                                AssetManager.ACCESS_STREAMING);
                    } else {
                        errorMsg = "Only support TYPE_STRING for the res files";
                    }
                } catch (ClassNotFoundException e) {
                    errorMsg = "Can't find class:  "
                            + mContext.getPackageName() + ".R$" + subClassName;
                } catch (SecurityException e) {
                    errorMsg = "Caught SecurityException: " + e;
                } catch (NoSuchFieldException e) {
                    errorMsg = "Can't find field:  " + fieldName + " in "
                            + mContext.getPackageName() + ".R$" + subClassName;
                } catch (IllegalArgumentException e) {
                    errorMsg = "Caught IllegalArgumentException: " + e;
                } catch (IllegalAccessException e) {
                    errorMsg = "Caught IllegalAccessException: " + e;
                }
                if (errorMsg != null) {
                    mHandler.error(EventHandler.FILE_ERROR, mContext
                            .getString(R.string.httpErrorFileNotFound));
                    return false;
                }
            } else {
                if (!mAllowFileAccess) {
                    mHandler.error(EventHandler.FILE_ERROR,
@@ -131,8 +204,8 @@ class FileLoader extends StreamLoader {
     *                        file system.
     */
    public static void requestUrl(String url, LoadListener loadListener,
            Context context, boolean asset, boolean allowFileAccess) {
        FileLoader loader = new FileLoader(url, loadListener, context, asset,
            Context context, int type, boolean allowFileAccess) {
        FileLoader loader = new FileLoader(url, loadListener, context, type,
                allowFileAccess);
        loader.load();
    }
+6 −2
Original line number Diff line number Diff line
@@ -142,11 +142,15 @@ class FrameLoader {
        }
        if (URLUtil.isAssetUrl(url)) {
            FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
                    true, settings.getAllowFileAccess());
                    FileLoader.TYPE_ASSET, true);
            return true;
        } else if (URLUtil.isResourceUrl(url)) {
            FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
                    FileLoader.TYPE_RES, true);
            return true;
        } else if (URLUtil.isFileUrl(url)) {
            FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
                    false, settings.getAllowFileAccess());
                    FileLoader.TYPE_FILE, settings.getAllowFileAccess());
            return true;
        } else if (URLUtil.isContentUrl(url)) {
            // Send the raw url to the ContentLoader because it will do a
+4 −4
Original line number Diff line number Diff line
@@ -163,10 +163,10 @@ class Network {
            return false;
        }

        // asset, file system or data stream are handled in the other code path.
        // This only handles network request.
        if (URLUtil.isAssetUrl(url) || URLUtil.isFileUrl(url) ||
                URLUtil.isDataUrl(url)) {
        // asset, res, file system or data stream are handled in the other code
        // path. This only handles network request.
        if (URLUtil.isAssetUrl(url) || URLUtil.isResourceUrl(url)
                || URLUtil.isFileUrl(url) || URLUtil.isDataUrl(url)) {
            return false;
        }

+17 −2
Original line number Diff line number Diff line
@@ -29,7 +29,13 @@ public final class URLUtil {

    private static final String LOGTAG = "webkit";

    // to refer to bar.png under your package's asset/foo/ directory, use
    // "file:///android_asset/foo/bar.png".
    static final String ASSET_BASE = "file:///android_asset/";
    // to refer to bar.png under your package's res/drawable/ directory, use
    // "file:///android_res/drawable/bar.png". Use "drawable" to refer to
    // "drawable-hdpi" directory as well.
    static final String RESOURCE_BASE = "file:///android_res/";
    static final String FILE_BASE = "file://";
    static final String PROXY_BASE = "file:///cookieless_proxy/";

@@ -167,6 +173,14 @@ public final class URLUtil {
        return (null != url) && url.startsWith(ASSET_BASE);
    }

    /**
     * @return True iff the url is a resource file.
     * @hide
     */
    public static boolean isResourceUrl(String url) {
        return (null != url) && url.startsWith(RESOURCE_BASE);
    }

    /**
     * @return True iff the url is an proxy url to allow cookieless network 
     * requests from a file url.
@@ -251,6 +265,7 @@ public final class URLUtil {
        }

        return (isAssetUrl(url) ||
                isResourceUrl(url) ||
                isFileUrl(url) ||
                isAboutUrl(url) ||
                isHttpUrl(url) ||