bug 741284 - add async file request method r=kats

This commit is contained in:
Brad Lassey 2012-04-05 01:50:06 -04:00
parent 8e33c30908
commit 3b454dc61d
7 changed files with 195 additions and 68 deletions

View File

@ -1867,4 +1867,10 @@ public class GeckoAppShell
public static void unlockScreenOrientation() {
GeckoScreenOrientationListener.getInstance().unlockScreenOrientation();
}
static native void notifyFilePickerResult(String filePath, long id);
/* Stubbed out because this is called from AndroidBridge for Native Fennec */
public static void showFilePickerAsync(String aMimeType, long id) {
}
}

View File

@ -165,10 +165,11 @@ abstract public class GeckoApp
Launched, GeckoRunning, GeckoExiting};
private static LaunchState sLaunchState = LaunchState.Launching;
private static final int FILE_PICKER_REQUEST = 1;
private static final int AWESOMEBAR_REQUEST = 2;
private static final int CAMERA_IMAGE_CAPTURE_REQUEST = 3;
private static final int CAMERA_VIDEO_CAPTURE_REQUEST = 4;
private ActivityResultHandlerMap mActivityResultHandlerMap = new ActivityResultHandlerMap();
private FilePickerResultHandlerSync mFilePickerResultHandlerSync = new FilePickerResultHandlerSync();
private AwesomebarResultHandler mAwesomebarResultHandler = new AwesomebarResultHandler();
private CameraImageResultHandler mCameraImageResultHandler = new CameraImageResultHandler();
private CameraVideoResultHandler mCameraVideoResultHandler = new CameraVideoResultHandler();
public static boolean checkLaunchState(LaunchState checkState) {
synchronized(sLaunchState) {
@ -2440,6 +2441,16 @@ abstract public class GeckoApp
private String mImageFilePath = "";
private SynchronousQueue<String> mFilePickerResult = new SynchronousQueue<String>();
public boolean showFilePicker(String aMimeType, ActivityResultHandler handler) {
Intent intent = getFilePickerIntent(aMimeType);
if (intent == null) {
return false;
}
startActivityForResult(intent, mActivityResultHandlerMap.put(handler));
return true;
}
public String showFilePicker(String aMimeType) {
Intent intent = getFilePickerIntent(aMimeType);
@ -2448,11 +2459,11 @@ abstract public class GeckoApp
}
if (intent.getAction().equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE)) {
startActivityForResult(intent, CAMERA_IMAGE_CAPTURE_REQUEST);
startActivityForResult(intent, mActivityResultHandlerMap.put(mCameraImageResultHandler));
} else if (intent.getAction().equals(android.provider.MediaStore.ACTION_VIDEO_CAPTURE)) {
startActivityForResult(intent, CAMERA_VIDEO_CAPTURE_REQUEST);
startActivityForResult(intent, mActivityResultHandlerMap.put(mCameraVideoResultHandler));
} else if (intent.getAction().equals(Intent.ACTION_GET_CONTENT)) {
startActivityForResult(intent, FILE_PICKER_REQUEST);
startActivityForResult(intent, mActivityResultHandlerMap.put(mFilePickerResultHandlerSync));
} else {
Log.e(LOGTAG, "We should not get an intent with another action!");
return "";
@ -2491,7 +2502,7 @@ abstract public class GeckoApp
}
}
}
startActivityForResult(intent, AWESOMEBAR_REQUEST);
startActivityForResult(intent, mActivityResultHandlerMap.put(mAwesomebarResultHandler));
return true;
}
@ -2563,66 +2574,96 @@ abstract public class GeckoApp
static int kCaptureIndex = 0;
public interface ActivityResultHandler {
public void onActivityResult(int resultCode, Intent data);
}
class ActivityResultHandlerMap {
private Map<Integer, ActivityResultHandler> mMap = new HashMap<Integer, ActivityResultHandler>();
private int mCounter = 0;
synchronized int put(ActivityResultHandler handler) {
mMap.put(mCounter, handler);
return mCounter++;
}
synchronized ActivityResultHandler getAndRemove(int i) {
return mMap.remove(i);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case FILE_PICKER_REQUEST:
String filePickerResult = "";
if (data != null && resultCode == RESULT_OK) {
try {
ContentResolver cr = getContentResolver();
Uri uri = data.getData();
Cursor cursor = GeckoApp.mAppContext.getContentResolver().query(
uri,
new String[] { OpenableColumns.DISPLAY_NAME },
null,
null,
null);
String name = null;
if (cursor != null) {
try {
if (cursor.moveToNext()) {
name = cursor.getString(0);
}
} finally {
cursor.close();
}
}
String fileName = "tmp_";
String fileExt = null;
int period;
if (name == null || (period = name.lastIndexOf('.')) == -1) {
String mimeType = cr.getType(uri);
fileExt = "." + GeckoAppShell.getExtensionFromMimeType(mimeType);
} else {
fileExt = name.substring(period);
fileName = name.substring(0, period);
}
File file = File.createTempFile(fileName, fileExt, GeckoAppShell.getGREDir(GeckoApp.mAppContext));
ActivityResultHandler handler = mActivityResultHandlerMap.getAndRemove(requestCode);
if (handler != null)
handler.onActivityResult(resultCode, data);
else
super.onActivityResult(requestCode, resultCode, data);
}
FileOutputStream fos = new FileOutputStream(file);
InputStream is = cr.openInputStream(uri);
byte[] buf = new byte[4096];
int len = is.read(buf);
while (len != -1) {
fos.write(buf, 0, len);
len = is.read(buf);
}
fos.close();
filePickerResult = file.getAbsolutePath();
}catch (Exception e) {
Log.e(LOGTAG, "showing file picker", e);
}
}
static abstract class FilePickerResultHandler implements ActivityResultHandler {
String handleActivityResult(int resultCode, Intent data) {
if (data == null && resultCode != RESULT_OK)
return null;
Uri uri = data.getData();
if ("file".equals(uri.getScheme()))
return uri.getPath();
try {
mFilePickerResult.put(filePickerResult);
ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
Cursor cursor = cr.query(uri, new String[] { OpenableColumns.DISPLAY_NAME },
null, null, null);
String name = null;
if (cursor != null) {
try {
if (cursor.moveToNext()) {
name = cursor.getString(0);
}
} finally {
cursor.close();
}
}
String fileName = "tmp_";
String fileExt = null;
int period;
if (name == null || (period = name.lastIndexOf('.')) == -1) {
String mimeType = cr.getType(uri);
fileExt = "." + GeckoAppShell.getExtensionFromMimeType(mimeType);
} else {
fileExt = name.substring(period);
fileName = name.substring(0, period);
}
File file = File.createTempFile(fileName, fileExt, GeckoAppShell.getGREDir(GeckoApp.mAppContext));
FileOutputStream fos = new FileOutputStream(file);
InputStream is = cr.openInputStream(uri);
byte[] buf = new byte[4096];
int len = is.read(buf);
while (len != -1) {
fos.write(buf, 0, len);
len = is.read(buf);
}
fos.close();
return file.getAbsolutePath();
} catch (Exception e) {
Log.e(LOGTAG, "showing file picker", e);
}
return null;
}
}
class FilePickerResultHandlerSync extends FilePickerResultHandler {
public void onActivityResult(int resultCode, Intent data) {
try {
mFilePickerResult.put(handleActivityResult(resultCode, data));
} catch (InterruptedException e) {
Log.i(LOGTAG, "error returning file picker result", e);
}
break;
case AWESOMEBAR_REQUEST:
}
}
class AwesomebarResultHandler implements ActivityResultHandler {
public void onActivityResult(int resultCode, Intent data) {
if (data != null) {
String url = data.getStringExtra(AwesomeBar.URL_KEY);
AwesomeBar.Type type = AwesomeBar.Type.valueOf(data.getStringExtra(AwesomeBar.TYPE_KEY));
@ -2631,12 +2672,15 @@ abstract public class GeckoApp
if (url != null && url.length() > 0)
loadRequest(url, type, searchEngine, userEntered);
}
break;
case CAMERA_IMAGE_CAPTURE_REQUEST:
}
}
class CameraImageResultHandler implements ActivityResultHandler {
public void onActivityResult(int resultCode, Intent data) {
try {
if (resultCode != Activity.RESULT_OK) {
mFilePickerResult.put("");
break;
return;
}
File file = new File(Environment.getExternalStorageDirectory(), mImageFilePath);
@ -2645,13 +2689,15 @@ abstract public class GeckoApp
} catch (InterruptedException e) {
Log.i(LOGTAG, "error returning file picker result", e);
}
}
}
break;
case CAMERA_VIDEO_CAPTURE_REQUEST:
class CameraVideoResultHandler implements ActivityResultHandler {
public void onActivityResult(int resultCode, Intent data) {
try {
if (data == null || resultCode != Activity.RESULT_OK) {
mFilePickerResult.put("");
break;
return;
}
Cursor cursor = managedQuery(data.getData(),
@ -2665,8 +2711,7 @@ abstract public class GeckoApp
Log.i(LOGTAG, "error returning file picker result", e);
}
break;
}
}
}
// If searchEngine is provided, url will be used as the search query.

View File

@ -2050,4 +2050,24 @@ public class GeckoAppShell
public static void unlockScreenOrientation() {
GeckoScreenOrientationListener.getInstance().unlockScreenOrientation();
}
static class AsyncResultHandler extends GeckoApp.FilePickerResultHandler {
private long mId;
AsyncResultHandler(long id) {
mId = id;
}
public void onActivityResult(int resultCode, Intent data) {
GeckoAppShell.notifyFilePickerResult(handleActivityResult(resultCode, data), mId);
}
}
static native void notifyFilePickerResult(String filePath, long id);
/* Called by JNI from AndroidBridge */
public static void showFilePickerAsync(String aMimeType, long id) {
if (!GeckoApp.mAppContext.showFilePicker(aMimeType, new AsyncResultHandler(id)))
GeckoAppShell.notifyFilePickerResult("", id);
}
}

View File

@ -349,6 +349,7 @@ SHELL_WRAPPER2(notifyNoMessageInList, jint, jlong)
SHELL_WRAPPER8(notifyListCreated, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
SHELL_WRAPPER7(notifyGotNextMessage, jint, jstring, jstring, jstring, jlong, jint, jlong)
SHELL_WRAPPER3(notifyReadingMessageListFailed, jint, jint, jlong)
SHELL_WRAPPER2(notifyFilePickerResult, jstring, jlong)
static void * xul_handle = NULL;
static void * sqlite_handle = NULL;
@ -764,6 +765,7 @@ loadGeckoLibs(const char *apkName)
GETFUNC(notifyListCreated);
GETFUNC(notifyGotNextMessage);
GETFUNC(notifyReadingMessageListFailed);
GETFUNC(notifyFilePickerResult);
#undef GETFUNC
sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
gettimeofday(&t1, 0);

View File

@ -73,6 +73,8 @@
using namespace mozilla;
NS_IMPL_THREADSAFE_ISUPPORTS0(nsFilePickerCallback)
AndroidBridge *AndroidBridge::sBridge = 0;
AndroidBridge *
@ -134,6 +136,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jShowAlertNotification = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showAlertNotification", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
jShowFilePickerForExtensions = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerForExtensions", "(Ljava/lang/String;)Ljava/lang/String;");
jShowFilePickerForMimeType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerForMimeType", "(Ljava/lang/String;)Ljava/lang/String;");
jShowFilePickerAsync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerAsync", "(Ljava/lang/String;J)V");
jAlertsProgressListener_OnProgress = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "alertsProgressListener_OnProgress", "(Ljava/lang/String;JJLjava/lang/String;)V");
jAlertsProgressListener_OnCancel = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "alertsProgressListener_OnCancel", "(Ljava/lang/String;)V");
jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I");
@ -771,6 +774,20 @@ AndroidBridge::ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString&
aFilePath.Assign(nsJNIString(jstr));
}
void
AndroidBridge::ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback)
{
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
jstring jMimeType = env->NewString(nsPromiseFlatString(aMimeType).get(),
aMimeType.Length());
callback->AddRef();
env->CallStaticVoidMethod(mGeckoAppShellClass, jShowFilePickerAsync, jMimeType, (jlong) callback);
}
void
AndroidBridge::SetFullScreen(bool aFullScreen)
{

View File

@ -111,6 +111,15 @@ typedef struct AndroidSystemColors {
nscolor panelColorBackground;
} AndroidSystemColors;
class nsFilePickerCallback : nsISupports {
public:
NS_DECL_ISUPPORTS
virtual void handleResult(nsAString& filePath) = 0;
nsFilePickerCallback() {}
protected:
virtual ~nsFilePickerCallback() {}
};
class AndroidBridge
{
public:
@ -242,6 +251,7 @@ public:
void ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions);
void ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType);
void ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback);
void PerformHapticFeedback(bool aIsLongPress);
@ -482,6 +492,7 @@ protected:
jmethodID jShowAlertNotification;
jmethodID jShowFilePickerForExtensions;
jmethodID jShowFilePickerForMimeType;
jmethodID jShowFilePickerAsync;
jmethodID jAlertsProgressListener_OnProgress;
jmethodID jAlertsProgressListener_OnCancel;
jmethodID jGetDpi;

View File

@ -102,6 +102,7 @@ extern "C" {
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyListCreated(JNIEnv* jenv, jclass, jint, jint, jstring, jstring, jstring, jlong, jint, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyGotNextMessage(JNIEnv* jenv, jclass, jint, jstring, jstring, jstring, jlong, jint, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyReadingMessageListFailed(JNIEnv* jenv, jclass, jint, jint, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyFilePickerResult(JNIEnv* jenv, jclass, jstring fileDir, jlong callback);
#ifdef MOZ_JAVA_COMPOSITOR
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv* jenv, jclass);
@ -909,4 +910,29 @@ Java_org_mozilla_gecko_GeckoAppShell_scheduleResumeComposition(JNIEnv*, jclass)
nsWindow::ScheduleResumeComposition();
}
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_notifyFilePickerResult(JNIEnv* jenv, jclass, jstring filePath, jlong callback)
{
class NotifyFilePickerResultRunnable : public nsRunnable {
public:
NotifyFilePickerResultRunnable(nsString& fileDir, long callback) :
mFileDir(fileDir), mCallback(callback) {}
NS_IMETHODIMP Run() {
nsFilePickerCallback* handler = (nsFilePickerCallback*)mCallback;
handler->handleResult(mFileDir);
handler->Release();
return NS_OK;
}
private:
nsString mFileDir;
long mCallback;
};
nsString path = nsJNIString(filePath, jenv);
nsCOMPtr<nsIRunnable> runnable =
new NotifyFilePickerResultRunnable(path, (long)callback);
NS_DispatchToMainThread(runnable);
}
#endif