Bug 674725 - Part AC - Implement getMessage() on Android. r=cjones

This commit is contained in:
Mounir Lamouri 2011-12-22 23:08:58 +01:00
parent d81a86b2d8
commit 367ad7c015
12 changed files with 232 additions and 5 deletions

View File

@ -118,7 +118,8 @@ SmsRequestManager::DispatchTrustedEventToRequest(const nsAString& aEventName,
}
void
SmsRequestManager::NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage)
SmsRequestManager::NotifySuccessWithMessage(PRInt32 aRequestId,
nsIDOMMozSmsMessage* aMessage)
{
NS_ASSERTION(mRequests.Count() > aRequestId && mRequests[aRequestId],
"Got an invalid request id or it has been already deleted!");
@ -133,6 +134,12 @@ SmsRequestManager::NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessa
mRequests.ReplaceObjectAt(nsnull, aRequestId);
}
void
SmsRequestManager::NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage)
{
NotifySuccessWithMessage(aRequestId, aMessage);
}
void
SmsRequestManager::NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError)
{
@ -149,6 +156,12 @@ SmsRequestManager::NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType
mRequests.ReplaceObjectAt(nsnull, aRequestId);
}
void
SmsRequestManager::NotifyGotSms(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage)
{
NotifySuccessWithMessage(aRequestId, aMessage);
}
} // namespace sms
} // namespace dom
} // namespace mozilla

View File

@ -64,12 +64,15 @@ public:
void NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage);
void NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError);
void NotifyGotSms(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage);
private:
static SmsRequestManager* sInstance;
nsresult DispatchTrustedEventToRequest(const nsAString& aEventName,
nsIDOMMozSmsRequest* aRequest);
void NotifySuccessWithMessage(PRInt32 aRequestId,
nsIDOMMozSmsMessage* aMessage);
nsCOMArray<nsIDOMMozSmsRequest> mRequests;
};

View File

@ -63,7 +63,11 @@ NS_IMETHODIMP
SmsDatabaseService::GetMessageMoz(PRInt32 aMessageId, PRInt32 aRequestId,
PRUint64 aProcessId)
{
// TODO: implement
if (!AndroidBridge::Bridge()) {
return NS_OK;
}
AndroidBridge::Bridge()->GetMessage(aMessageId, aRequestId, aProcessId);
return NS_OK;
}

View File

@ -71,6 +71,9 @@ child:
NotifyRequestSmsSendFailed(PRInt32 aError, PRInt32 aRequestId,
PRUint64 aProcessId);
NotifyRequestGotSms(SmsMessageData aMessageData, PRInt32 aRequestId,
PRUint64 aProcessId);
parent:
sync HasSupport()
returns (bool aHasSupport);

View File

@ -120,6 +120,21 @@ SmsChild::RecvNotifyRequestSmsSendFailed(const PRInt32& aError,
return true;
}
bool
SmsChild::RecvNotifyRequestGotSms(const SmsMessageData& aMessage,
const PRInt32& aRequestId,
const PRUint64& aProcessId)
{
if (ContentChild::GetSingleton()->GetID() != aProcessId) {
return true;
}
nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(aMessage);
SmsRequestManager::GetInstance()->NotifyGotSms(aRequestId, message);
return true;
}
} // namespace sms
} // namespace dom
} // namespace mozilla

View File

@ -52,6 +52,7 @@ public:
NS_OVERRIDE virtual bool RecvNotifyDeliveredMessage(const SmsMessageData& aMessage);
NS_OVERRIDE virtual bool RecvNotifyRequestSmsSent(const SmsMessageData& aMessage, const PRInt32& aRequestId, const PRUint64& aProcessId);
NS_OVERRIDE virtual bool RecvNotifyRequestSmsSendFailed(const PRInt32& aError, const PRInt32& aRequestId, const PRUint64& aProcessId);
NS_OVERRIDE virtual bool RecvNotifyRequestGotSms(const SmsMessageData& aMessage, const PRInt32& aRequestId, const PRUint64& aProcessId);
};
} // namespace sms

View File

@ -126,6 +126,7 @@ public class GeckoAppShell
public static native void notifySmsSent(int aId, String aReceiver, String aBody, long aTimestamp, int aRequestId, long aProcessId);
public static native void notifySmsDelivered(int aId, String aReceiver, String aBody, long aTimestamp);
public static native void notifySmsSendFailed(int aError, int aRequestId, long aProcessId);
public static native void notifyGetSms(int aId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
// A looper thread, accessed by GeckoAppShell.getHandler
private static class LooperThread extends Thread {
@ -1704,6 +1705,10 @@ public class GeckoAppShell
return GeckoSmsManager.saveSentMessage(aRecipient, aBody, aDate);
}
public static void getMessage(int aMessageId, int aRequestId, long aProcessId) {
GeckoSmsManager.getMessage(aMessageId, aRequestId, aProcessId);
}
public static boolean isTablet() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
Configuration config = GeckoApp.mAppContext.getResources().getConfiguration();

View File

@ -45,6 +45,8 @@ import android.util.Log;
import android.app.PendingIntent;
import android.app.Activity;
import android.database.Cursor;
import android.content.Intent;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -257,8 +259,6 @@ public class GeckoSmsManager
public final static String ACTION_SMS_SENT = "org.mozilla.gecko.SMS_SENT";
public final static String ACTION_SMS_DELIVERED = "org.mozilla.gecko.SMS_DELIVERED";
private final static int kMaxMessageSize = 160;
/*
* Keep the following error codes in sync with |ErrorType| in:
* dom/sms/src/SmsRequest.h
@ -268,6 +268,14 @@ public class GeckoSmsManager
public final static int kUnknownError = 2;
public final static int kInternalError = 3;
private final static int kMaxMessageSize = 160;
private final static Uri kSmsContentUri = Uri.parse("content://sms");
private final static Uri kSmsSentContentUri = Uri.parse("content://sms/sent");
private final static int kSmsTypeInbox = 1;
private final static int kSmsTypeSentbox = 2;
public static void init() {
SmsIOThread.getInstance().start();
}
@ -494,7 +502,7 @@ public class GeckoSmsManager
values.put("date", aDate);
ContentResolver cr = GeckoApp.surfaceView.getContext().getContentResolver();
Uri uri = cr.insert(Uri.parse("content://sms/sent"), values);
Uri uri = cr.insert(kSmsSentContentUri, values);
long id = ContentUris.parseId(uri);
@ -514,6 +522,95 @@ public class GeckoSmsManager
}
}
public static void getMessage(int aMessageId, int aRequestId, long aProcessId) {
class GetMessageRunnable implements Runnable {
private int mMessageId;
private int mRequestId;
private long mProcessId;
GetMessageRunnable(int aMessageId, int aRequestId, long aProcessId) {
mMessageId = aMessageId;
mRequestId = aRequestId;
mProcessId = aProcessId;
}
@Override
public void run() {
class NotFoundException extends Exception { }
class UnmatchingIdException extends Exception { }
class TooManyResultsException extends Exception { }
class InvalidTypeException extends Exception { }
Cursor cursor = null;
try {
ContentResolver cr = GeckoApp.surfaceView.getContext().getContentResolver();
Uri message = ContentUris.withAppendedId(kSmsContentUri, mMessageId);
cursor = cr.query(message,
new String[] { "_id", "address", "body", "date", "type" },
null, null, null);
if (cursor == null || cursor.getCount() == 0) {
throw new NotFoundException();
}
if (cursor.getCount() != 1) {
throw new TooManyResultsException();
}
cursor.moveToFirst();
if (cursor.getInt(cursor.getColumnIndex("_id")) != mMessageId) {
throw new UnmatchingIdException();
}
int type = cursor.getInt(cursor.getColumnIndex("type"));
String sender = "";
String receiver = "";
if (type == kSmsTypeInbox) {
sender = cursor.getString(cursor.getColumnIndex("address"));
} else if (type == kSmsTypeSentbox) {
receiver = cursor.getString(cursor.getColumnIndex("address"));
} else {
throw new InvalidTypeException();
}
GeckoAppShell.notifyGetSms(cursor.getInt(cursor.getColumnIndex("_id")),
receiver, sender,
cursor.getString(cursor.getColumnIndex("body")),
cursor.getLong(cursor.getColumnIndex("date")),
mRequestId, mProcessId);
} catch (NotFoundException e) {
// TODO: send failure notification
Log.i("GeckoSmsManager", "Message id " + mMessageId + " not found");
} catch (UnmatchingIdException e) {
// TODO: send failure notification
Log.e("GeckoSmsManager", "Requested message id (" + mMessageId +
") is different from the one we got.");
} catch (TooManyResultsException e) {
// TODO: send failure notification
Log.e("GeckoSmsManager", "Get too many results for id " + mMessageId);
} catch (InvalidTypeException e) {
// TODO: send failure notification
Log.i("GeckoSmsManager", "Message has an invalid type, we ignore it.");
} catch (Exception e) {
// TODO: send failure notification
Log.e("GeckoSmsManager", "Error while trying to get message: " + e);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}
if (!SmsIOThread.getInstance().execute(new GetMessageRunnable(aMessageId, aRequestId, aProcessId))) {
// TODO: send failure notification
Log.e("GeckoSmsManager", "Failed to add GetMessageRunnable to the SmsIOThread");
}
}
public static void shutdown() {
SmsIOThread.getInstance().interrupt();
}

View File

@ -234,6 +234,24 @@ Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one
return f_ ## name(jenv, jc, one, two, three, four, five, six); \
}
#define SHELL_WRAPPER7(name,type1,type2,type3,type4,type5,type6,type7) \
typedef void (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven); \
static name ## _t f_ ## name; \
extern "C" NS_EXPORT void JNICALL \
Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven) \
{ \
f_ ## name(jenv, jc, one, two, three, four, five, six, seven); \
}
#define SHELL_WRAPPER7_WITH_RETURN(name, return_type, type1, type2, type3, type4, type5, type6, type7) \
typedef return_type (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven); \
static name ## _t f_ ## name; \
extern "C" NS_EXPORT return_type JNICALL \
Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven) \
{ \
return f_ ## name(jenv, jc, one, two, three, four, five, six, seven); \
}
SHELL_WRAPPER0(nativeInit)
SHELL_WRAPPER1(nativeRun, jstring)
SHELL_WRAPPER1(notifyGeckoOfEvent, jobject)
@ -256,6 +274,7 @@ SHELL_WRAPPER3_WITH_RETURN(saveMessageInSentbox, jint, jstring, jstring, jlong);
SHELL_WRAPPER6(notifySmsSent, jint, jstring, jstring, jlong, jint, jlong);
SHELL_WRAPPER4(notifySmsDelivered, jint, jstring, jstring, jlong);
SHELL_WRAPPER3(notifySmsSendFailed, jint, jint, jlong);
SHELL_WRAPPER7(notifyGetSms, jint, jstring, jstring, jstring, jlong, jint, jlong);
static void * xul_handle = NULL;
static time_t apk_mtime = 0;
@ -647,6 +666,7 @@ loadLibs(const char *apkName)
GETFUNC(notifySmsSent);
GETFUNC(notifySmsDelivered);
GETFUNC(notifySmsSendFailed);
GETFUNC(notifyGetSms);
#undef GETFUNC
sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
gettimeofday(&t1, 0);

View File

@ -169,6 +169,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jNumberOfMessages = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getNumberOfMessagesForText", "(Ljava/lang/String;)I");
jSendMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "sendMessage", "(Ljava/lang/String;Ljava/lang/String;IJ)V");
jSaveSentMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "saveSentMessage", "(Ljava/lang/String;Ljava/lang/String;J)I");
jGetMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getMessage", "(IIJ)V");
jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
@ -1366,6 +1367,14 @@ AndroidBridge::SaveSentMessage(const nsAString& aRecipient,
return GetJNIForThread()->CallStaticIntMethod(mGeckoAppShellClass, jSaveSentMessage, jRecipient, jBody, aDate);
}
void
AndroidBridge::GetMessage(PRInt32 aMessageId, PRInt32 aRequestId, PRUint64 aProcessId)
{
ALOG_BRIDGE("AndroidBridge::GetMessage");
JNI()->CallStaticVoidMethod(mGeckoAppShellClass, jGetMessage, aMessageId, aRequestId, aProcessId);
}
void *
AndroidBridge::LockBitmap(jobject bitmap)
{

View File

@ -337,6 +337,7 @@ public:
PRUint16 GetNumberOfMessagesForText(const nsAString& aText);
void SendMessage(const nsAString& aNumber, const nsAString& aText, PRInt32 aRequestId, PRUint64 aProcessId);
PRInt32 SaveSentMessage(const nsAString& aRecipient, const nsAString& aBody, PRUint64 aDate);
void GetMessage(PRInt32 aMessageId, PRInt32 aRequestId, PRUint64 aProcessId);
bool IsTablet();
@ -428,6 +429,7 @@ protected:
jmethodID jNumberOfMessages;
jmethodID jSendMessage;
jmethodID jSaveSentMessage;
jmethodID jGetMessage;
// stuff we need for CallEglCreateWindowSurface
jclass jEGLSurfaceImplClass;

View File

@ -95,6 +95,7 @@ extern "C" {
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsSent(JNIEnv* jenv, jclass, jint, jstring, jstring, jlong, jint, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsDelivered(JNIEnv* jenv, jclass, jint, jstring, jstring, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsSendFailed(JNIEnv* jenv, jclass, jint, jint, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyGetSms(JNIEnv* jenv, jclass, jint, jstring, jstring, jstring, jlong, jint, jlong);
#ifdef MOZ_JAVA_COMPOSITOR
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass);
@ -446,6 +447,60 @@ Java_org_mozilla_gecko_GeckoAppShell_notifySmsSendFailed(JNIEnv* jenv, jclass,
NS_DispatchToMainThread(runnable);
}
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_notifyGetSms(JNIEnv* jenv, jclass,
jint aId,
jstring aReceiver,
jstring aSender,
jstring aBody,
jlong aTimestamp,
jint aRequestId,
jlong aProcessId)
{
class NotifyGetSmsRunnable : public nsRunnable {
public:
NotifyGetSmsRunnable(const SmsMessageData& aMessageData,
PRInt32 aRequestId, PRUint64 aProcessId)
: mMessageData(aMessageData)
, mRequestId(aRequestId)
, mProcessId(aProcessId)
{}
NS_IMETHODIMP Run() {
if (mProcessId == 0) { // Parent process.
nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
SmsRequestManager::GetInstance()->NotifyGotSms(mRequestId, message);
} else { // Content process.
nsTArray<SmsParent*> spList;
SmsParent::GetAll(spList);
for (PRUint32 i=0; i<spList.Length(); ++i) {
unused << spList[i]->SendNotifyRequestGotSms(mMessageData,
mRequestId,
mProcessId);
}
}
return NS_OK;
}
private:
SmsMessageData mMessageData;
PRInt32 mRequestId;
PRUint64 mProcessId;
};
nsJNIString receiver = nsJNIString(aReceiver, jenv);
DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
: eDeliveryState_Sent;
SmsMessageData message(aId, state, nsJNIString(aSender, jenv), receiver,
nsJNIString(aBody, jenv), aTimestamp);
nsCOMPtr<nsIRunnable> runnable = new NotifyGetSmsRunnable(message, aRequestId, aProcessId);
NS_DispatchToMainThread(runnable);
}
#ifdef MOZ_JAVA_COMPOSITOR
NS_EXPORT void JNICALL