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

Commit 70ca3c25 authored by Leon Scroggins's avatar Leon Scroggins
Browse files

File upload.

Implement java side of file upload.  Requires changes to external/
webkit to not break; requires changes to packages/apps/Browser
before it actually is used.

Fix http://b/issue?id=675743
parent 6e15a70c
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -19,17 +19,21 @@ package android.webkit;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.ParseException;
import android.net.Uri;
import android.net.WebAddress;
import android.net.http.SslCertificate;
import android.os.Handler;
import android.os.Message;
import android.provider.OpenableColumns;
import android.util.Log;
import android.util.TypedValue;

import junit.framework.Assert;

import java.io.InputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
@@ -462,6 +466,60 @@ class BrowserFrame extends Handler {
        mJSInterfaceMap.put(interfaceName, obj);
    }

    /**
     * Called by JNI.  Given a URI, find the associated file and return its size
     * @param uri A String representing the URI of the desired file.
     * @return int The size of the given file.
     */
    private int getFileSize(String uri) {
        int size = 0;
        Cursor cursor = mContext.getContentResolver().query(Uri.parse(uri),
                new String[] { OpenableColumns.SIZE },
                null,
                null,
                null);
        if (cursor != null) {
            try {
                if (cursor.moveToNext()) {
                    size = cursor.getInt(0);
                }
            } finally {
                cursor.close();
            }
        }
        return size;
    }

    /**
     * Called by JNI.  Given a URI, a buffer, and an offset into the buffer,
     * copy the resource into buffer.
     * @param uri A String representing the URI of the desired file.
     * @param buffer The byte array to copy the data into.
     * @param offset The offet into buffer to place the data.
     * @return int The size of the given file, or zero if it fails.
     */
    private int getFile(String uri, byte[] buffer, int offset) {
        int size = 0;
        try {
            InputStream stream = mContext.getContentResolver()
                            .openInputStream(Uri.parse(uri));
            size = stream.available();
            if (buffer != null && buffer.length - offset >= size) {
                stream.read(buffer, offset, size);
            } else {
                size = 0;
            }
            stream.close();
        } catch (java.io.FileNotFoundException e) {
            Log.e(LOGTAG, "FileNotFoundException:" + e);
            size = 0;
        } catch (java.io.IOException e2) {
            Log.e(LOGTAG, "IOException: " + e2);
            size = 0;
        }
        return size;
    }

    /**
     * Start loading a resource.
     * @param loaderHandle The native ResourceLoader that is the target of the
+43 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ class CallbackProxy extends Handler {
    private static final int GEOLOCATION_PERMISSIONS_HIDE_PROMPT = 131;
    private static final int RECEIVED_TOUCH_ICON_URL             = 132;
    private static final int GET_VISITED_HISTORY                 = 133;
    private static final int OPEN_FILE_CHOOSER                   = 134;

    // Message triggered by the client to resume execution
    private static final int NOTIFY                              = 200;
@@ -662,6 +663,12 @@ class CallbackProxy extends Handler {
                    mWebChromeClient.getVisitedHistory((ValueCallback<String[]>)msg.obj);
                }
                break;

            case OPEN_FILE_CHOOSER:
                if (mWebChromeClient != null) {
                    mWebChromeClient.openFileChooser((UploadFile) msg.obj);
                }
                break;
        }
    }

@@ -1348,4 +1355,40 @@ class CallbackProxy extends Handler {
        msg.obj = callback;
        sendMessage(msg);
    }

    private class UploadFile implements ValueCallback<Uri> {
        private Uri mValue;
        public void onReceiveValue(Uri value) {
            mValue = value;
            synchronized (CallbackProxy.this) {
                CallbackProxy.this.notify();
            }
        }
        public Uri getResult() {
            return mValue;
        }
    }

    /**
     * Called by WebViewCore to open a file chooser.
     */
    /* package */ Uri openFileChooser() {
        if (mWebChromeClient == null) {
            return null;
        }
        Message myMessage = obtainMessage(OPEN_FILE_CHOOSER);
        UploadFile uploadFile = new UploadFile();
        myMessage.obj = uploadFile;
        synchronized (this) {
            sendMessage(myMessage);
            try {
                wait();
            } catch (InterruptedException e) {
                Log.e(LOGTAG,
                        "Caught exception while waiting for openFileChooser");
                Log.e(LOGTAG, Log.getStackTraceString(e));
            }
        }
        return uploadFile.getResult();
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.webkit;

import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Message;
import android.view.View;

@@ -302,4 +303,13 @@ public class WebChromeClient {
    public void getVisitedHistory(ValueCallback<String[]> callback) {
    }

    /**
     * Tell the client to open a file chooser.
     * @param uploadFile A ValueCallback to set the URI of the file to upload.
     *      onReceiveValue must be called to wake up the thread.
     * @hide
     */
    public void openFileChooser(ValueCallback<Uri> uploadFile) {
        uploadFile.onReceiveValue(null);
    }
}
+36 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.webkit;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.DrawFilter;
import android.graphics.Paint;
@@ -26,11 +27,13 @@ import android.graphics.Picture;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.provider.Browser;
import android.provider.OpenableColumns;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.KeyEvent;
@@ -273,6 +276,39 @@ final class WebViewCore {
        mCallbackProxy.onJsAlert(url, message);
    }


    /**
     * Called by JNI.  Open a file chooser to upload a file.
     * @return String version of the URI plus the name of the file.
     * FIXME: Just return the URI here, and in FileSystem::pathGetFileName, call
     * into Java to get the filename.
     */
    private String openFileChooser() {
        Uri uri = mCallbackProxy.openFileChooser();
        if (uri == null) return "";
        // Find out the name, and append it to the URI.
        // Webkit will treat the name as the filename, and
        // the URI as the path.  The URI will be used
        // in BrowserFrame to get the actual data.
        Cursor cursor = mContext.getContentResolver().query(
                uri,
                new String[] { OpenableColumns.DISPLAY_NAME },
                null,
                null,
                null);
        String name = "";
        if (cursor != null) {
            try {
                if (cursor.moveToNext()) {
                    name = cursor.getString(0);
                }
            } finally {
                cursor.close();
            }
        }
        return uri.toString() + "/" + name;
    }

    /**
     * Notify the browser that the origin has exceeded it's database quota.
     * @param url The URL that caused the overflow.