Bug 674725 - Part R - Save sent messages in the Android database. r=cjones

This commit is contained in:
Mounir Lamouri 2012-01-13 14:25:47 +01:00
parent 921b5a2395
commit 205528614d
14 changed files with 176 additions and 6 deletions

View File

@ -38,14 +38,14 @@
%{C++
#define SMS_DATABASE_SERVICE_CID \
{ 0xb5bd6b55, 0x2e56, 0x4f1d, \
{ 0xa4, 0x38, 0x1d, 0x10, 0xd6, 0xf3, 0x4d, 0xe5 } }
{ 0x1cb004a0, 0xe003, 0x48b9, \
{ 0x9f, 0xd6, 0xe9, 0x1f, 0xbb, 0xb1, 0x97, 0x89 } }
#define SMS_DATABASE_SERVICE_CONTRACTID "@mozilla.org/sms/smsdatabaseservice;1"
%}
interface nsIDOMMozSmsMessage;
[scriptable, function, uuid(ff6128fd-8caf-4b2b-898e-fb4051996767)]
[scriptable, function, uuid(ab23f736-f545-4fcd-a298-3d6e2b380042)]
interface nsISmsDatabaseService : nsISupports
{
// Takes some information required to save the message and returns its id.
long saveSentMessage(in DOMString aReceiver, in DOMString aBody, in unsigned long long aDate);
};

View File

@ -44,6 +44,21 @@ namespace sms {
NS_IMPL_ISUPPORTS1(SmsDatabaseService, nsISmsDatabaseService)
NS_IMETHODIMP
SmsDatabaseService::SaveSentMessage(const nsAString& aReceiver,
const nsAString& aBody,
PRUint64 aDate, PRInt32* aId)
{
*aId = -1;
if (!AndroidBridge::Bridge()) {
return NS_OK;
}
*aId = AndroidBridge::Bridge()->SaveSentMessage(aReceiver, aBody, aDate);
return NS_OK;
}
} // namespace sms
} // namespace dom
} // namespace mozilla

View File

@ -43,6 +43,16 @@ namespace sms {
NS_IMPL_ISUPPORTS1(SmsDatabaseService, nsISmsDatabaseService)
NS_IMETHODIMP
SmsDatabaseService::SaveSentMessage(const nsAString& aReceiver,
const nsAString& aBody,
PRUint64 aDate, PRInt32* aId)
{
*aId = -1;
NS_ERROR("We should not be here!");
return NS_OK;
}
} // namespace sms
} // namespace dom
} // namespace mozilla

View File

@ -70,6 +70,9 @@ parent:
SendMessage(nsString aNumber, nsString aMessage);
sync SaveSentMessage(nsString aReceiver, nsString aBody, PRUint64 aDate)
returns (PRInt32 aId);
__delete__();
};

View File

@ -60,6 +60,9 @@ SmsIPCService::GetSmsChild()
return sSmsChild;
}
/*
* Implementation of nsISmsService.
*/
NS_IMETHODIMP
SmsIPCService::HasSupport(bool* aHasSupport)
{
@ -98,6 +101,20 @@ SmsIPCService::CreateSmsMessage(PRInt32 aId,
aId, aDelivery, aSender, aReceiver, aBody, aTimestamp, aCx, aMessage);
}
/*
* Implementation of nsISmsDatabaseService.
*/
NS_IMETHODIMP
SmsIPCService::SaveSentMessage(const nsAString& aReceiver,
const nsAString& aBody,
PRUint64 aDate, PRInt32* aId)
{
GetSmsChild()->SendSaveSentMessage(nsString(aReceiver), nsString(aBody),
aDate, aId);
return NS_OK;
}
} // namespace sms
} // namespace dom
} // namespace mozilla

View File

@ -43,6 +43,7 @@
#include "nsIDOMSmsMessage.h"
#include "mozilla/unused.h"
#include "SmsMessage.h"
#include "nsISmsDatabaseService.h"
namespace mozilla {
namespace dom {
@ -123,6 +124,21 @@ SmsParent::RecvSendMessage(const nsString& aNumber, const nsString& aMessage)
return true;
}
bool
SmsParent::RecvSaveSentMessage(const nsString& aRecipient,
const nsString& aBody,
const PRUint64& aDate, PRInt32* aId)
{
*aId = -1;
nsCOMPtr<nsISmsDatabaseService> smsDBService =
do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(smsDBService, true);
smsDBService->SaveSentMessage(aRecipient, aBody, aDate, aId);
return true;
}
} // namespace sms
} // namespace dom
} // namespace mozilla

View File

@ -57,6 +57,7 @@ public:
NS_OVERRIDE virtual bool RecvHasSupport(bool* aHasSupport);
NS_OVERRIDE virtual bool RecvGetNumberOfMessagesForText(const nsString& aText, PRUint16* aResult);
NS_OVERRIDE virtual bool RecvSendMessage(const nsString& aNumber, const nsString& aMessage);
NS_OVERRIDE virtual bool RecvSaveSentMessage(const nsString& aRecipient, const nsString& aBody, const PRUint64& aDate, PRInt32* aId);
protected:
virtual void ActorDestroy(ActorDestroyReason why);

View File

@ -24,6 +24,8 @@
<!-- WebSMS -->
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-feature android:name="android.hardware.location" android:required="false"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>

View File

@ -122,6 +122,7 @@ public class GeckoAppShell
public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
public static native void onSmsSent(String aReceiver, String aBody, long aTimestamp);
// A looper thread, accessed by GeckoAppShell.getHandler
private static class LooperThread extends Thread {
@ -1696,6 +1697,10 @@ public class GeckoAppShell
GeckoSmsManager.send(aNumber, aMessage);
}
public static int saveSentMessage(String aRecipient, String aBody, long aDate) {
return GeckoSmsManager.saveSentMessage(aRecipient, aBody, aDate);
}
public static boolean isTablet() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
Configuration config = GeckoApp.mAppContext.getResources().getConfiguration();

View File

@ -48,6 +48,11 @@ import android.app.Activity;
import android.content.Intent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.ContentUris;
import android.net.Uri;
import android.os.Bundle;
@ -224,7 +229,9 @@ public class GeckoSmsManager
// TODO: inform about the send failure.
Log.i("GeckoSmsManager", "SMS sending failed!");
} else {
// TODO: inform about the send success.
GeckoAppShell.onSmsSent(bundle.getString("number"),
bundle.getString("message"),
System.currentTimeMillis());
Log.i("GeckoSmsManager", "SMS sending was successfull!");
}
@ -305,4 +312,34 @@ public class GeckoSmsManager
}
}
}
public static int saveSentMessage(String aRecipient, String aBody, long aDate) {
class IdTooHighException extends Exception { }
try {
ContentValues values = new ContentValues();
values.put("address", aRecipient);
values.put("body", aBody);
values.put("date", aDate);
ContentResolver cr = GeckoApp.surfaceView.getContext().getContentResolver();
Uri uri = cr.insert(Uri.parse("content://sms/sent"), values);
long id = ContentUris.parseId(uri);
// The DOM API takes a 32bits unsigned int for the id. It's unlikely that
// we happen to need more than that but it doesn't cost to check.
if (id > Integer.MAX_VALUE) {
throw new IdTooHighException();
}
return (int)id;
} catch (IdTooHighException e) {
Log.e("GeckoSmsManager", "The id we received is higher than the higher allowed value.");
return -1;
} catch (Exception e) {
Log.e("GeckoSmsManager", "Something went wrong when trying to write a sent message: " + e);
return -1;
}
}
}

View File

@ -198,6 +198,7 @@ SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble);
SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong);
SHELL_WRAPPER0(bindWidgetTexture);
SHELL_WRAPPER0_WITH_RETURN(testDirectTexture, bool);
SHELL_WRAPPER3(onSmsSent, jstring, jstring, jlong);
static void * xul_handle = NULL;
static time_t apk_mtime = 0;
@ -585,6 +586,7 @@ loadLibs(const char *apkName)
GETFUNC(notifySmsReceived);
GETFUNC(bindWidgetTexture);
GETFUNC(testDirectTexture);
GETFUNC(onSmsSent);
#undef GETFUNC
sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
gettimeofday(&t1, 0);

View File

@ -168,6 +168,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;)V");
jSaveSentMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "saveSentMessage", "(Ljava/lang/String;Ljava/lang/String;J)I");
jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
@ -1353,6 +1354,18 @@ AndroidBridge::SendMessage(const nsAString& aNumber, const nsAString& aMessage)
GetJNIForThread()->CallStaticVoidMethod(mGeckoAppShellClass, jSendMessage, jNumber, jMessage);
}
PRInt32
AndroidBridge::SaveSentMessage(const nsAString& aRecipient,
const nsAString& aBody, PRUint64 aDate)
{
ALOG_BRIDGE("AndroidBridge::SaveSentMessage");
AutoLocalJNIFrame jniFrame;
jstring jRecipient = GetJNIForThread()->NewString(PromiseFlatString(aRecipient).get(), aRecipient.Length());
jstring jBody = GetJNIForThread()->NewString(PromiseFlatString(aBody).get(), aBody.Length());
return GetJNIForThread()->CallStaticIntMethod(mGeckoAppShellClass, jSaveSentMessage, jRecipient, jBody, aDate);
}
void *
AndroidBridge::LockBitmap(jobject bitmap)
{

View File

@ -60,6 +60,7 @@
// #define DEBUG_ANDROID_WIDGET
class nsWindow;
class nsIDOMMozSmsMessage;
namespace mozilla {
@ -335,6 +336,7 @@ public:
PRUint16 GetNumberOfMessagesForText(const nsAString& aText);
void SendMessage(const nsAString& aNumber, const nsAString& aText);
PRInt32 SaveSentMessage(const nsAString& aRecipient, const nsAString& aBody, PRUint64 aDate);
bool IsTablet();
@ -425,6 +427,7 @@ protected:
jmethodID jNumberOfMessages;
jmethodID jSendMessage;
jmethodID jSaveSentMessage;
// stuff we need for CallEglCreateWindowSurface
jclass jEGLSurfaceImplClass;

View File

@ -63,6 +63,7 @@
#include "mozilla/dom/sms/Constants.h"
#include "mozilla/dom/sms/Types.h"
#include "mozilla/dom/sms/PSms.h"
#include "nsISmsDatabaseService.h"
using namespace mozilla;
using namespace mozilla::dom::sms;
@ -85,6 +86,7 @@ extern "C" {
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass, jstring, jstring, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onSmsSent(JNIEnv* jenv, jclass, jstring, jstring, jlong);
#ifdef MOZ_JAVA_COMPOSITOR
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass);
@ -273,6 +275,50 @@ Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass,
NS_DispatchToMainThread(runnable);
}
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_onSmsSent(JNIEnv* jenv, jclass,
jstring aReceiver,
jstring aBody,
jlong aTimestamp)
{
class OnSmsSentRunnable : public nsRunnable {
public:
OnSmsSentRunnable(const nsAString& aReceiver, const nsAString& aBody, PRUint64 aTimestamp)
: mReceiver(aReceiver)
, mBody(aBody)
, mTimestamp(aTimestamp)
{}
NS_IMETHODIMP Run() {
nsCOMPtr<nsISmsDatabaseService> smsDBService =
do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
if (!smsDBService) {
NS_ERROR("Sms Database Service not available!");
return NS_OK;
}
int id;
smsDBService->SaveSentMessage(mReceiver, mBody, mTimestamp, &id);
// TODO: use the ID to build a SmsMessage object and notify about the
// sent message.
return NS_OK;
}
private:
nsString mReceiver;
nsString mBody;
PRUint64 mTimestamp;
};
nsCOMPtr<nsIRunnable> runnable =
new OnSmsSentRunnable(nsJNIString(aReceiver, jenv),
nsJNIString(aBody, jenv), aTimestamp);
NS_DispatchToMainThread(runnable);
}
#ifdef MOZ_JAVA_COMPOSITOR
NS_EXPORT void JNICALL