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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user