Merge change I234162b0 into eclair-mr2
* changes: Add "res" support for WebView.
This commit is contained in:
@@ -23,9 +23,12 @@ import android.content.res.AssetManager;
|
|||||||
import android.net.http.EventHandler;
|
import android.net.http.EventHandler;
|
||||||
import android.net.http.Headers;
|
import android.net.http.Headers;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is a concrete implementation of StreamLoader that uses a
|
* This class is a concrete implementation of StreamLoader that uses a
|
||||||
@@ -35,10 +38,19 @@ import java.io.FileInputStream;
|
|||||||
class FileLoader extends StreamLoader {
|
class FileLoader extends StreamLoader {
|
||||||
|
|
||||||
private String mPath; // Full path to the file to load
|
private String mPath; // Full path to the file to load
|
||||||
private Context mContext; // Application context, used for asset loads
|
private Context mContext; // Application context, used for asset/res loads
|
||||||
private boolean mIsAsset; // Indicates if the load is an asset or not
|
private int mType; // Indicates the type of the load
|
||||||
private boolean mAllowFileAccess; // Allow/block file system access
|
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
|
* Construct a FileLoader with the file URL specified as the content
|
||||||
* source.
|
* source.
|
||||||
@@ -51,19 +63,24 @@ class FileLoader extends StreamLoader {
|
|||||||
* on the file system.
|
* on the file system.
|
||||||
*/
|
*/
|
||||||
FileLoader(String url, LoadListener loadListener, Context context,
|
FileLoader(String url, LoadListener loadListener, Context context,
|
||||||
boolean asset, boolean allowFileAccess) {
|
int type, boolean allowFileAccess) {
|
||||||
super(loadListener);
|
super(loadListener);
|
||||||
mIsAsset = asset;
|
mType = type;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mAllowFileAccess = allowFileAccess;
|
mAllowFileAccess = allowFileAccess;
|
||||||
|
|
||||||
// clean the Url
|
// clean the Url
|
||||||
int index = url.indexOf('?');
|
int index = url.indexOf('?');
|
||||||
if (mIsAsset) {
|
if (mType == TYPE_ASSET) {
|
||||||
mPath = index > 0 ? URLUtil.stripAnchor(
|
mPath = index > 0 ? URLUtil.stripAnchor(
|
||||||
url.substring(URLUtil.ASSET_BASE.length(), index)) :
|
url.substring(URLUtil.ASSET_BASE.length(), index)) :
|
||||||
URLUtil.stripAnchor(url.substring(
|
URLUtil.stripAnchor(url.substring(
|
||||||
URLUtil.ASSET_BASE.length()));
|
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 {
|
} else {
|
||||||
mPath = index > 0 ? URLUtil.stripAnchor(
|
mPath = index > 0 ? URLUtil.stripAnchor(
|
||||||
url.substring(URLUtil.FILE_BASE.length(), index)) :
|
url.substring(URLUtil.FILE_BASE.length(), index)) :
|
||||||
@@ -84,13 +101,69 @@ class FileLoader extends StreamLoader {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean setupStreamAndSendStatus() {
|
protected boolean setupStreamAndSendStatus() {
|
||||||
try {
|
try {
|
||||||
if (mIsAsset) {
|
if (mType == TYPE_ASSET) {
|
||||||
try {
|
try {
|
||||||
mDataStream = mContext.getAssets().open(mPath);
|
mDataStream = mContext.getAssets().open(mPath);
|
||||||
} catch (java.io.FileNotFoundException ex) {
|
} catch (java.io.FileNotFoundException ex) {
|
||||||
// try the rest files included in the package
|
// try the rest files included in the package
|
||||||
mDataStream = mContext.getAssets().openNonAsset(mPath);
|
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 {
|
} else {
|
||||||
if (!mAllowFileAccess) {
|
if (!mAllowFileAccess) {
|
||||||
mHandler.error(EventHandler.FILE_ERROR,
|
mHandler.error(EventHandler.FILE_ERROR,
|
||||||
@@ -131,8 +204,8 @@ class FileLoader extends StreamLoader {
|
|||||||
* file system.
|
* file system.
|
||||||
*/
|
*/
|
||||||
public static void requestUrl(String url, LoadListener loadListener,
|
public static void requestUrl(String url, LoadListener loadListener,
|
||||||
Context context, boolean asset, boolean allowFileAccess) {
|
Context context, int type, boolean allowFileAccess) {
|
||||||
FileLoader loader = new FileLoader(url, loadListener, context, asset,
|
FileLoader loader = new FileLoader(url, loadListener, context, type,
|
||||||
allowFileAccess);
|
allowFileAccess);
|
||||||
loader.load();
|
loader.load();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,11 +142,15 @@ class FrameLoader {
|
|||||||
}
|
}
|
||||||
if (URLUtil.isAssetUrl(url)) {
|
if (URLUtil.isAssetUrl(url)) {
|
||||||
FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
|
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;
|
return true;
|
||||||
} else if (URLUtil.isFileUrl(url)) {
|
} else if (URLUtil.isFileUrl(url)) {
|
||||||
FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
|
FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
|
||||||
false, settings.getAllowFileAccess());
|
FileLoader.TYPE_FILE, settings.getAllowFileAccess());
|
||||||
return true;
|
return true;
|
||||||
} else if (URLUtil.isContentUrl(url)) {
|
} else if (URLUtil.isContentUrl(url)) {
|
||||||
// Send the raw url to the ContentLoader because it will do a
|
// Send the raw url to the ContentLoader because it will do a
|
||||||
|
|||||||
@@ -163,10 +163,10 @@ class Network {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// asset, file system or data stream are handled in the other code path.
|
// asset, res, file system or data stream are handled in the other code
|
||||||
// This only handles network request.
|
// path. This only handles network request.
|
||||||
if (URLUtil.isAssetUrl(url) || URLUtil.isFileUrl(url) ||
|
if (URLUtil.isAssetUrl(url) || URLUtil.isResourceUrl(url)
|
||||||
URLUtil.isDataUrl(url)) {
|
|| URLUtil.isFileUrl(url) || URLUtil.isDataUrl(url)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,13 @@ public final class URLUtil {
|
|||||||
|
|
||||||
private static final String LOGTAG = "webkit";
|
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/";
|
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 FILE_BASE = "file://";
|
||||||
static final String PROXY_BASE = "file:///cookieless_proxy/";
|
static final String PROXY_BASE = "file:///cookieless_proxy/";
|
||||||
|
|
||||||
@@ -167,6 +173,14 @@ public final class URLUtil {
|
|||||||
return (null != url) && url.startsWith(ASSET_BASE);
|
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
|
* @return True iff the url is an proxy url to allow cookieless network
|
||||||
* requests from a file url.
|
* requests from a file url.
|
||||||
@@ -251,6 +265,7 @@ public final class URLUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (isAssetUrl(url) ||
|
return (isAssetUrl(url) ||
|
||||||
|
isResourceUrl(url) ||
|
||||||
isFileUrl(url) ||
|
isFileUrl(url) ||
|
||||||
isAboutUrl(url) ||
|
isAboutUrl(url) ||
|
||||||
isHttpUrl(url) ||
|
isHttpUrl(url) ||
|
||||||
|
|||||||
Reference in New Issue
Block a user