diff options
-rw-r--r-- | core/java/android/webkit/FileLoader.java | 89 | ||||
-rw-r--r-- | core/java/android/webkit/FrameLoader.java | 8 | ||||
-rw-r--r-- | core/java/android/webkit/Network.java | 8 | ||||
-rw-r--r-- | core/java/android/webkit/URLUtil.java | 19 |
4 files changed, 108 insertions, 16 deletions
diff --git a/core/java/android/webkit/FileLoader.java b/core/java/android/webkit/FileLoader.java index 085f1f4..974ccbf 100644 --- a/core/java/android/webkit/FileLoader.java +++ b/core/java/android/webkit/FileLoader.java @@ -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(); } diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java index c3dac6e..51f60c3 100644 --- a/core/java/android/webkit/FrameLoader.java +++ b/core/java/android/webkit/FrameLoader.java @@ -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 diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java index b53e404..598f20d 100644 --- a/core/java/android/webkit/Network.java +++ b/core/java/android/webkit/Network.java @@ -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; } diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java index 211e5e4..7c5f2b0 100644 --- a/core/java/android/webkit/URLUtil.java +++ b/core/java/android/webkit/URLUtil.java @@ -28,8 +28,14 @@ import android.util.Log; 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/"; @@ -166,7 +172,15 @@ public final class URLUtil { public static boolean isAssetUrl(String url) { 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) || |