Bug 674725 - Part J - Basic implementation of mozSms.send(). r=cjones
authorMounir Lamouri <mounir.lamouri@gmail.com>
Mon, 21 Nov 2011 00:00:46 +0100
changeset 81574 423c6548b52253327ed6c617b1bb25712d202aa5
parent 81573 fcf8b53367112da414349d8eaf36eee47f1c613b
child 81575 70aceb7cc3120b69bb5f5377519157e364e1db78
push idunknown
push userunknown
push dateunknown
reviewerscjones
bugs674725
milestone11.0a1
Bug 674725 - Part J - Basic implementation of mozSms.send(). r=cjones
dom/sms/interfaces/nsIDOMSmsManager.idl
dom/sms/interfaces/nsISmsService.idl
dom/sms/src/SmsManager.cpp
dom/sms/src/android/SmsService.cpp
dom/sms/src/fallback/SmsService.cpp
dom/sms/src/ipc/PSms.ipdl
dom/sms/src/ipc/SmsIPCService.cpp
dom/sms/src/ipc/SmsParent.cpp
dom/sms/src/ipc/SmsParent.h
embedding/android/AndroidManifest.xml.in
embedding/android/GeckoAppShell.java
embedding/android/GeckoSmsManager.java
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
--- a/dom/sms/interfaces/nsIDOMSmsManager.idl
+++ b/dom/sms/interfaces/nsIDOMSmsManager.idl
@@ -31,13 +31,14 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
-[scriptable, function, uuid(acff4eca-ae08-4c4a-bc6d-34a960134314)]
+[scriptable, function, uuid(473547ee-7a26-46d3-8476-f012985cd0c8)]
 interface nsIDOMMozSmsManager : nsISupports
 {
   unsigned short getNumberOfMessagesForText(in DOMString text);
+            void send(in DOMString number, in DOMString message);
 };
--- a/dom/sms/interfaces/nsISmsService.idl
+++ b/dom/sms/interfaces/nsISmsService.idl
@@ -36,14 +36,15 @@
 
 #include "nsISupports.idl"
 
 %{C++
 #define NS_SMSSERVICE_CID { 0xbada3cb8, 0xa568, 0x4dff, { 0xb5, 0x43, 0x52, 0xbb, 0xb3, 0x14, 0x31, 0x21 } }
 #define SMSSERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
 %}
 
-[scriptable, function, uuid(abc95960-c689-4985-a226-7c96d27e2cd8)]
+[scriptable, function, uuid(24edea1d-130a-4ae3-9522-0e2a7ee2885d)]
 interface nsISmsService : nsISupports
 {
-  boolean hasSupport();
+  boolean        hasSupport();
   unsigned short getNumberOfMessagesForText(in DOMString text);
+            void send(in DOMString number, in DOMString message);
 };
--- a/dom/sms/src/SmsManager.cpp
+++ b/dom/sms/src/SmsManager.cpp
@@ -60,11 +60,22 @@ SmsManager::GetNumberOfMessagesForText(c
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMSSERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, NS_OK);
 
   smsService->GetNumberOfMessagesForText(aText, aResult);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+SmsManager::Send(const nsAString& aNumber, const nsAString& aMessage)
+{
+  nsCOMPtr<nsISmsService> smsService = do_GetService(SMSSERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(smsService, NS_OK);
+
+  smsService->Send(aNumber, aMessage);
+
+  return NS_OK;
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/android/SmsService.cpp
+++ b/dom/sms/src/android/SmsService.cpp
@@ -58,11 +58,22 @@ SmsService::GetNumberOfMessagesForText(c
     *aResult = 0;
     return NS_OK;
   }
 
   *aResult = AndroidBridge::Bridge()->GetNumberOfMessagesForText(aText);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+SmsService::Send(const nsAString& aNumber, const nsAString& aMessage)
+{
+  if (!AndroidBridge::Bridge()) {
+    return NS_OK;
+  }
+
+  AndroidBridge::Bridge()->SendMessage(aNumber, aMessage);
+  return NS_OK;
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/fallback/SmsService.cpp
+++ b/dom/sms/src/fallback/SmsService.cpp
@@ -53,11 +53,18 @@ SmsService::HasSupport(bool* aHasSupport
 NS_IMETHODIMP
 SmsService::GetNumberOfMessagesForText(const nsAString& aText, PRUint16* aResult)
 {
   NS_ERROR("We should not be here!");
   *aResult = 0;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+SmsService::Send(const nsAString& aNumber, const nsAString& aMessage)
+{
+  NS_ERROR("We should not be here!");
+  return NS_OK;
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/PSms.ipdl
+++ b/dom/sms/src/ipc/PSms.ipdl
@@ -48,14 +48,16 @@ sync protocol PSms {
 
 parent:
     sync HasSupport()
         returns (bool aHasSupport);
 
     sync GetNumberOfMessagesForText(nsString aText)
         returns (PRUint16 aNumber);
 
+    SendMessage(nsString aNumber, nsString aMessage);
+
     __delete__();
 };
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/SmsIPCService.cpp
+++ b/dom/sms/src/ipc/SmsIPCService.cpp
@@ -69,11 +69,19 @@ SmsIPCService::HasSupport(bool* aHasSupp
 NS_IMETHODIMP
 SmsIPCService::GetNumberOfMessagesForText(const nsAString& aText, PRUint16* aResult)
 {
   GetSmsChild()->SendGetNumberOfMessagesForText(nsString(aText), aResult);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+SmsIPCService::Send(const nsAString& aNumber, const nsAString& aMessage)
+{
+  GetSmsChild()->SendSendMessage(nsString(aNumber), nsString(aMessage));
+
+  return NS_OK;
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/SmsParent.cpp
+++ b/dom/sms/src/ipc/SmsParent.cpp
@@ -61,11 +61,21 @@ SmsParent::RecvGetNumberOfMessagesForTex
 
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMSSERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, true);
 
   smsService->GetNumberOfMessagesForText(aText, aResult);
   return true;
 }
 
+bool
+SmsParent::RecvSendMessage(const nsString& aNumber, const nsString& aMessage)
+{
+  nsCOMPtr<nsISmsService> smsService = do_GetService(SMSSERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(smsService, true);
+
+  smsService->Send(aNumber, aMessage);
+  return true;
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/SmsParent.h
+++ b/dom/sms/src/ipc/SmsParent.h
@@ -43,15 +43,16 @@
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 class SmsParent : public PSmsParent
 {
   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);
 };
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_SmsParent_h
--- a/embedding/android/AndroidManifest.xml.in
+++ b/embedding/android/AndroidManifest.xml.in
@@ -16,16 +16,19 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
 
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.VIBRATE"/>
 
+    <!-- WebSMS -->
+    <uses-permission android:name="android.permission.SEND_SMS"/>
+
     <uses-feature android:name="android.hardware.location" android:required="false"/>
     <uses-feature android:name="android.hardware.location.gps" android:required="false"/>
     <uses-feature android:name="android.hardware.touchscreen"/>
 
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-feature android:name="android.hardware.camera" android:required="false"/>
     <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
  
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -1631,25 +1631,34 @@ public class GeckoAppShell
     public static String handleGeckoMessage(String message) {
         return "";
     }
     // unused
     static void checkUriVisited(String uri) {}
     // unused
     static void markUriVisited(final String uri) {}
 
-
+    /*
+     * Battery API related methods.
+     */
     public static void enableBatteryNotifications() {
         GeckoBatteryManager.enableNotifications();
     }
 
     public static void disableBatteryNotifications() {
         GeckoBatteryManager.disableNotifications();
     }
 
     public static double[] getCurrentBatteryInformation() {
         return GeckoBatteryManager.getCurrentInformation();
     }
 
+    /*
+     * WebSMS related methods.
+     */
     public static int getNumberOfMessagesForText(String aText) {
         return GeckoSmsManager.getNumberOfMessagesForText(aText);
     }
+
+    public static void sendMessage(String aNumber, String aMessage) {
+        GeckoSmsManager.send(aNumber, aMessage);
+    }
 }
--- a/embedding/android/GeckoSmsManager.java
+++ b/embedding/android/GeckoSmsManager.java
@@ -40,12 +40,34 @@ package org.mozilla.gecko;
 import java.util.ArrayList;
 
 import android.util.Log;
 
 import android.telephony.SmsManager;
 
 public class GeckoSmsManager
 {
+  final static int kMaxMessageSize = 160;
+
   public static int getNumberOfMessagesForText(String aText) {
     return SmsManager.getDefault().divideMessage(aText).size();
   }
+
+  public static void send(String aNumber, String aMessage) {
+    /*
+     * TODO:
+     * This is a basic send method that doesn't handle errors, doesn't listen to
+     * sent and received messages. It's only calling the send method.
+     */
+    try {
+      SmsManager sm = SmsManager.getDefault();
+
+      if (aMessage.length() <= kMaxMessageSize) {
+        sm.sendTextMessage(aNumber, "", aMessage, null, null);
+      } else {
+        ArrayList<String> parts = sm.divideMessage(aMessage);
+        sm.sendMultipartTextMessage(aNumber, "", parts, null, null);
+      }
+    } catch (Exception e) {
+      Log.i("GeckoSmsManager", "Failed to send an SMS: ", e);
+    }
+  }
 }
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -165,16 +165,17 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jGetCurrentBatteryInformation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getCurrentBatteryInformation", "()[D");
 
     jGetAccessibilityEnabled = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getAccessibilityEnabled", "()Z");
     jHandleGeckoMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "handleGeckoMessage", "(Ljava/lang/String;)Ljava/lang/String;");
     jCheckUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "checkUriVisited", "(Ljava/lang/String;)V");
     jMarkUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "markUriVisited", "(Ljava/lang/String;)V");
 
     jNumberOfMessages = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getNumberOfMessagesForText", "(Ljava/lang/String;)I");
+    jSendMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "sendMessage", "(Ljava/lang/String;Ljava/lang/String;)V");
 
     jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
     jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
     jEGLSurfaceImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl"));
     jEGLContextImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLContextImpl"));
     jEGLConfigImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLConfigImpl"));
     jEGLDisplayImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLDisplayImpl"));
 
@@ -1364,16 +1365,28 @@ AndroidBridge::GetNumberOfMessagesForTex
 {
     ALOG_BRIDGE("AndroidBridge::GetNumberOfMessagesForText");
 
     AutoLocalJNIFrame jniFrame;
     jstring jText = GetJNIForThread()->NewString(PromiseFlatString(aText).get(), aText.Length());
     return GetJNIForThread()->CallStaticIntMethod(mGeckoAppShellClass, jNumberOfMessages, jText);
 }
 
+void
+AndroidBridge::SendMessage(const nsAString& aNumber, const nsAString& aMessage)
+{
+    ALOG_BRIDGE("AndroidBridge::SendMessage");
+
+    AutoLocalJNIFrame jniFrame;
+    jstring jNumber = GetJNIForThread()->NewString(PromiseFlatString(aNumber).get(), aNumber.Length());
+    jstring jMessage = GetJNIForThread()->NewString(PromiseFlatString(aMessage).get(), aMessage.Length());
+
+    GetJNIForThread()->CallStaticVoidMethod(mGeckoAppShellClass, jSendMessage, jNumber, jMessage);
+}
+
 void *
 AndroidBridge::LockBitmap(jobject bitmap)
 {
     int err;
     void *buf;
 
     if ((err = AndroidBitmap_lockPixels(JNI(), bitmap, &buf)) != 0) {
         ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err);
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -314,16 +314,17 @@ public:
 
     void CloseCamera();
 
     void EnableBatteryNotifications();
     void DisableBatteryNotifications();
     void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
 
     PRUint16 GetNumberOfMessagesForText(const nsAString& aText);
+    void SendMessage(const nsAString& aNumber, const nsAString& aText);
 
 protected:
     static AndroidBridge *sBridge;
 
     // the global JavaVM
     JavaVM *mJavaVM;
 
     // the JNIEnv for the main thread
@@ -398,17 +399,19 @@ protected:
     jmethodID jEnableBatteryNotifications;
     jmethodID jDisableBatteryNotifications;
     jmethodID jGetCurrentBatteryInformation;
     jmethodID jGetAccessibilityEnabled;
     jmethodID jHandleGeckoMessage;
     jmethodID jCheckUriVisited;
     jmethodID jMarkUriVisited;
     jmethodID jEmitGeckoAccessibilityEvent;
+
     jmethodID jNumberOfMessages;
+    jmethodID jSendMessage;
 
     // stuff we need for CallEglCreateWindowSurface
     jclass jEGLSurfaceImplClass;
     jclass jEGLContextImplClass;
     jclass jEGLConfigImplClass;
     jclass jEGLDisplayImplClass;
     jclass jEGLContextClass;
     jclass jEGL10Class;