bug 741284 - add async file request method r=kats

This commit is contained in:
Brad Lassey 2012-04-05 01:50:06 -04:00
Родитель 97e59725ee
Коммит 88fa428f0d
7 изменённых файлов: 195 добавлений и 68 удалений

Просмотреть файл

@ -1867,4 +1867,10 @@ public class GeckoAppShell
public static void unlockScreenOrientation() { public static void unlockScreenOrientation() {
GeckoScreenOrientationListener.getInstance().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) {
}
} }

Просмотреть файл

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

Просмотреть файл

@ -2050,4 +2050,24 @@ public class GeckoAppShell
public static void unlockScreenOrientation() { public static void unlockScreenOrientation() {
GeckoScreenOrientationListener.getInstance().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);
}
} }

Просмотреть файл

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

Просмотреть файл

@ -73,6 +73,8 @@
using namespace mozilla; using namespace mozilla;
NS_IMPL_THREADSAFE_ISUPPORTS0(nsFilePickerCallback)
AndroidBridge *AndroidBridge::sBridge = 0; AndroidBridge *AndroidBridge::sBridge = 0;
AndroidBridge * 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"); 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;"); jShowFilePickerForExtensions = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerForExtensions", "(Ljava/lang/String;)Ljava/lang/String;");
jShowFilePickerForMimeType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerForMimeType", "(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_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"); jAlertsProgressListener_OnCancel = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "alertsProgressListener_OnCancel", "(Ljava/lang/String;)V");
jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I"); jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I");
@ -771,6 +774,20 @@ AndroidBridge::ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString&
aFilePath.Assign(nsJNIString(jstr)); 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 void
AndroidBridge::SetFullScreen(bool aFullScreen) AndroidBridge::SetFullScreen(bool aFullScreen)
{ {

Просмотреть файл

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

Просмотреть файл

@ -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_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_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_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 #ifdef MOZ_JAVA_COMPOSITOR
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv* jenv, jclass); 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(); 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 #endif