am 14467eb2: Merge change I234162b0 into eclair-mr2

Merge commit '14467eb2eea119b4d71dd7dd149479aa092e6de2' into eclair-mr2-plus-aosp

* commit '14467eb2eea119b4d71dd7dd149479aa092e6de2':
  Add "res" support for WebView.
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.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 @@
 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 @@
      *                        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 @@
     @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 @@
      *                        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 @@
         }
         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 @@
             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 @@
 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 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 @@
         }
 
         return (isAssetUrl(url) ||
+                isResourceUrl(url) ||
                 isFileUrl(url) ||
                 isAboutUrl(url) ||
                 isHttpUrl(url) ||