Bug 674725 - Part Y - Notify when send() fails. r=smaug,cjones sr=sicking
authorMounir Lamouri <mounir.lamouri@gmail.com>
Thu, 22 Dec 2011 23:06:35 +0100
changeset 85935 a09cc4f2fbe92ba7c9050f8e7c9928c807ec0067
parent 85934 070bd086ef5b029d470a953a7acc545bfe91db2e
child 85936 6148455f5ddc84a1fb6fb765db6435cf91cddb78
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, cjones, sicking
bugs674725
milestone12.0a1
Bug 674725 - Part Y - Notify when send() fails. r=smaug,cjones sr=sicking
dom/sms/src/Makefile.in
dom/sms/src/SmsRequest.cpp
dom/sms/src/SmsRequest.h
dom/sms/src/SmsRequestManager.cpp
dom/sms/src/SmsRequestManager.h
dom/sms/src/ipc/PSms.ipdl
dom/sms/src/ipc/SmsChild.cpp
dom/sms/src/ipc/SmsChild.h
embedding/android/GeckoAppShell.java
embedding/android/GeckoSmsManager.java
mozglue/android/APKOpen.cpp
widget/android/AndroidJNI.cpp
--- a/dom/sms/src/Makefile.in
+++ b/dom/sms/src/Makefile.in
@@ -63,16 +63,17 @@ EXPORTS_NAMESPACES = mozilla/dom/sms
 EXPORTS_mozilla/dom/sms = \
   SmsChild.h \
   SmsParent.h \
   SmsServicesFactory.h \
   Constants.h \
   Types.h \
   SmsMessage.h \
   SmsRequestManager.h \
+  SmsRequest.h \
   $(NULL)
 
 CPPSRCS = \
   SmsManager.cpp \
   SmsService.cpp \
   SmsIPCService.cpp \
   SmsServicesFactory.cpp \
   SmsParent.cpp \
--- a/dom/sms/src/SmsRequest.cpp
+++ b/dom/sms/src/SmsRequest.cpp
@@ -187,16 +187,22 @@ SmsRequest::GetError(nsAString& aError)
 
   NS_ASSERTION(mError == eNoError || mResult == JSVAL_VOID,
                "mResult should be void when there is an error!");
 
   switch (mError) {
     case eNoError:
       SetDOMStringToNull(aError);
       break;
+    case eNoSignalError:
+      aError.AssignLiteral("NoSignalError");
+      break;
+    case eUnknownError:
+      aError.AssignLiteral("UnknownError");
+      break;
     case eInternalError:
       aError.AssignLiteral("InternalError");
       break;
   }
 
   return NS_OK;
 }
 
--- a/dom/sms/src/SmsRequest.h
+++ b/dom/sms/src/SmsRequest.h
@@ -48,18 +48,25 @@ namespace dom {
 namespace sms {
 
 class SmsRequest : public nsIDOMMozSmsRequest
                  , public nsDOMEventTargetWrapperCache
 {
 public:
   friend class SmsRequestManager;
 
+  /**
+   * All SMS related errors that could apply to SmsRequest objects.
+   * Make sure to keep this list in sync with the list in:
+   * embedding/android/GeckoSmsManager.java
+   */
   enum ErrorType {
     eNoError = 0,
+    eNoSignalError,
+    eUnknownError,
     eInternalError,
   };
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMOZSMSREQUEST
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetWrapperCache::)
 
--- a/dom/sms/src/SmsRequestManager.cpp
+++ b/dom/sms/src/SmsRequestManager.cpp
@@ -31,17 +31,16 @@
  * decision by deleting the provisions above and replace them with the notice
  * 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 "SmsRequestManager.h"
-#include "SmsRequest.h"
 #include "nsIDOMSmsMessage.h"
 #include "nsDOMEvent.h"
 
 /**
  * We have to use macros here because our leak analysis tool things we are
  * leaking strings when we have |static const nsString|. Sad :(
  */
 #define SUCCESS_EVENT_NAME NS_LITERAL_STRING("success")
@@ -129,11 +128,27 @@ SmsRequestManager::NotifySmsSent(PRInt32
   SmsRequest* request = static_cast<SmsRequest*>(mRequests[aRequestId]);
   request->SetSuccess(aMessage);
 
   DispatchTrustedEventToRequest(SUCCESS_EVENT_NAME, request);
 
   mRequests.ReplaceObjectAt(nsnull, aRequestId);
 }
 
+void
+SmsRequestManager::NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError)
+{
+  NS_ASSERTION(mRequests.Count() > aRequestId && mRequests[aRequestId],
+               "Got an invalid request id or it has been already deleted!");
+
+  // It's safe to use the static_cast here given that we did call
+  // |new SmsRequest()|.
+  SmsRequest* request = static_cast<SmsRequest*>(mRequests[aRequestId]);
+  request->SetError(aError);
+
+  DispatchTrustedEventToRequest(ERROR_EVENT_NAME, request);
+
+  mRequests.ReplaceObjectAt(nsnull, aRequestId);
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/SmsRequestManager.h
+++ b/dom/sms/src/SmsRequestManager.h
@@ -35,16 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_sms_SmsRequestManager_h
 #define mozilla_dom_sms_SmsRequestManager_h
 
 #include "nsCOMArray.h"
+#include "SmsRequest.h"
 
 class nsIDOMMozSmsRequest;
 class nsPIDOMWindow;
 class nsIScriptContext;
 class nsIDOMMozSmsMessage;
 
 namespace mozilla {
 namespace dom {
@@ -57,16 +58,17 @@ public:
   static void Shutdown();
   static SmsRequestManager* GetInstance();
 
   PRInt32 CreateRequest(nsPIDOMWindow* aWindow,
                         nsIScriptContext* aScriptContext,
                         nsIDOMMozSmsRequest** aRequest);
 
   void NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage);
+  void NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError);
 
 private:
   static SmsRequestManager* sInstance;
 
   nsresult DispatchTrustedEventToRequest(const nsAString& aEventName,
                                          nsIDOMMozSmsRequest* aRequest);
 
   nsCOMArray<nsIDOMMozSmsRequest> mRequests;
--- a/dom/sms/src/ipc/PSms.ipdl
+++ b/dom/sms/src/ipc/PSms.ipdl
@@ -63,16 +63,19 @@ child:
 
     NotifySentMessage(SmsMessageData aMessageData);
 
     NotifyDeliveredMessage(SmsMessageData aMessageData);
 
     NotifyRequestSmsSent(SmsMessageData aMessageData, PRInt32 aRequestId,
                          PRUint64 aProcessId);
 
+    NotifyRequestSmsSendFailed(PRInt32 aError, PRInt32 aRequestId,
+                               PRUint64 aProcessId);
+
 parent:
     sync HasSupport()
         returns (bool aHasSupport);
 
     sync GetNumberOfMessagesForText(nsString aText)
         returns (PRUint16 aNumber);
 
     SendMessage(nsString aNumber, nsString aMessage, PRInt32 aRequestId,
--- a/dom/sms/src/ipc/SmsChild.cpp
+++ b/dom/sms/src/ipc/SmsChild.cpp
@@ -37,16 +37,17 @@
 
 #include "SmsChild.h"
 #include "SmsMessage.h"
 #include "Constants.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/ContentChild.h"
 #include "SmsRequestManager.h"
+#include "SmsRequest.h"
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 bool
 SmsChild::RecvNotifyReceivedMessage(const SmsMessageData& aMessageData)
 {
@@ -99,11 +100,26 @@ SmsChild::RecvNotifyRequestSmsSent(const
   }
 
   nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(aMessage);
   SmsRequestManager::GetInstance()->NotifySmsSent(aRequestId, message);
 
   return true;
 }
 
+bool
+SmsChild::RecvNotifyRequestSmsSendFailed(const PRInt32& aError,
+                                         const PRInt32& aRequestId,
+                                         const PRUint64& aProcessId)
+{
+  if (ContentChild::GetSingleton()->GetID() != aProcessId) {
+    return true;
+  }
+
+  SmsRequestManager::GetInstance()->NotifySmsSendFailed(aRequestId,
+                                                        SmsRequest::ErrorType(aError));
+
+  return true;
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/SmsChild.h
+++ b/dom/sms/src/ipc/SmsChild.h
@@ -46,15 +46,16 @@ namespace sms {
 
 class SmsChild : public PSmsChild
 {
 public:
   NS_OVERRIDE virtual bool RecvNotifyReceivedMessage(const SmsMessageData& aMessage);
   NS_OVERRIDE virtual bool RecvNotifySentMessage(const SmsMessageData& aMessage);
   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);
 };
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_SmsChild_h
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -120,16 +120,17 @@ public class GeckoAppShell
     public static native void processNextNativeEvent();
 
     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 int  saveMessageInSentbox(String aReceiver, String aBody, long aTimestamp);
     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);
 
     // A looper thread, accessed by GeckoAppShell.getHandler
     private static class LooperThread extends Thread {
         public SynchronousQueue<Handler> mHandlerQueue =
             new SynchronousQueue<Handler>();
         
         public void run() {
             Looper.prepare();
--- a/embedding/android/GeckoSmsManager.java
+++ b/embedding/android/GeckoSmsManager.java
@@ -93,20 +93,26 @@ class Envelope
   protected int[]     mRemainingParts;
 
   /**
    * Whether sending/delivering is currently failing.
    * @note The array has much slots as SubParts items.
    */
   protected boolean[] mFailing;
 
+  /**
+   * Error type (only for sent).
+   */
+  protected int       mError;
+
   public Envelope(int aId, int aParts) {
     mId = aId;
     mMessageId = -1;
     mMessageTimestamp = 0;
+    mError = GeckoSmsManager.kNoError;
 
     int size = Envelope.SubParts.values().length;
     mRemainingParts = new int[size];
     mFailing = new boolean[size];
 
     for (int i=0; i<size; ++i) {
       mRemainingParts[i] = aParts;
       mFailing[i] = false;
@@ -144,16 +150,24 @@ class Envelope
 
   public long getMessageTimestamp() {
     return mMessageTimestamp;
   }
 
   public void setMessageTimestamp(long aMessageTimestamp) {
     mMessageTimestamp = aMessageTimestamp;
   }
+
+  public int getError() {
+    return mError;
+  }
+
+  public void setError(int aError) {
+    mError = aError;
+  }
 }
 
 /**
  * Postman class is a singleton that manages Envelope instances.
  */
 class Postman
 {
   public static final int kUnknownEnvelopeId = -1;
@@ -216,16 +230,25 @@ public class GeckoSmsManager
   extends BroadcastReceiver
 {
   public final static String ACTION_SMS_RECEIVED  = "android.provider.Telephony.SMS_RECEIVED";
   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
+   */
+  public final static int kNoError       = 0;
+  public final static int kNoSignalError = 1;
+  public final static int kUnknownError  = 2;
+  public final static int kInternalError = 3;
+
   @Override
   public void onReceive(Context context, Intent intent) {
     if (intent.getAction().equals(ACTION_SMS_RECEIVED)) {
       // TODO: Try to find the receiver number to be able to populate
       //       SmsMessage.receiver.
       // TODO: Get the id and the date from the stock app saved message.
       //       Using the stock app saved message require us to wait for it to
       //       be saved which can lead to race conditions.
@@ -271,28 +294,42 @@ public class GeckoSmsManager
 
       Envelope.SubParts part = intent.getAction().equals(ACTION_SMS_SENT)
                                  ? Envelope.SubParts.SENT_PART
                                  : Envelope.SubParts.DELIVERED_PART;
       envelope.decreaseRemainingParts(part);
  
 
       if (getResultCode() != Activity.RESULT_OK) {
-        // TODO: manage error types.
+        switch (getResultCode()) {
+          case SmsManager.RESULT_ERROR_NULL_PDU:
+            envelope.setError(kInternalError);
+            break;
+          case SmsManager.RESULT_ERROR_NO_SERVICE:
+          case SmsManager.RESULT_ERROR_RADIO_OFF:
+            envelope.setError(kNoSignalError);
+            break;
+          case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
+          default:
+            envelope.setError(kUnknownError);
+            break;
+        }
+        envelope.markAsFailed(part);
         Log.i("GeckoSmsManager", "SMS part sending failed!");
-        envelope.markAsFailed(part);
       }
 
       if (envelope.arePartsRemaining(part)) {
         return;
       }
 
       if (envelope.isFailing(part)) {
         if (part == Envelope.SubParts.SENT_PART) {
-          // TODO: inform about the send failure.
+          GeckoAppShell.notifySmsSendFailed(envelope.getError(),
+                                            bundle.getInt("requestId"),
+                                            bundle.getLong("processId"));
           Log.i("GeckoSmsManager", "SMS sending failed!");
         } else {
           // It seems unlikely to get a result code for a failure to deliver.
           // Even if, we don't want to do anything with this.
           Log.e("GeckoSmsManager", "SMS failed to be delivered... is that even possible?");
         }
       } else {
         if (part == Envelope.SubParts.SENT_PART) {
@@ -329,21 +366,16 @@ public class GeckoSmsManager
     }
   }
 
   public static int getNumberOfMessagesForText(String aText) {
     return SmsManager.getDefault().divideMessage(aText).size();
   }
 
   public static void send(String aNumber, String aMessage, int aRequestId, long aProcessId) {
-    /*
-     * TODO:
-     * This is a basic send method that doesn't handle errors and doesn't listen to
-     * delivered messages.
-     */
     int envelopeId = Postman.kUnknownEnvelopeId;
 
     try {
       SmsManager sm = SmsManager.getDefault();
 
       Intent sentIntent = new Intent(ACTION_SMS_SENT);
       Intent deliveredIntent = new Intent(ACTION_SMS_DELIVERED);
 
@@ -414,16 +446,18 @@ public class GeckoSmsManager
                                     deliveredPendingIntents);
       }
     } catch (Exception e) {
       Log.e("GeckoSmsManager", "Failed to send an SMS: ", e);
 
       if (envelopeId != Postman.kUnknownEnvelopeId) {
         Postman.getInstance().destroyEnvelope(envelopeId);
       }
+
+      GeckoAppShell.notifySmsSendFailed(kUnknownError, aRequestId, aProcessId);
     }
   }
 
   public static int saveSentMessage(String aRecipient, String aBody, long aDate) {
     class IdTooHighException extends Exception { }
 
     try {
       ContentValues values = new ContentValues();
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -250,16 +250,17 @@ SHELL_WRAPPER0(executeNextRunnable)
 SHELL_WRAPPER1(cameraCallbackBridge, jbyteArray)
 SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble);
 SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong);
 SHELL_WRAPPER0(bindWidgetTexture);
 SHELL_WRAPPER0_WITH_RETURN(testDirectTexture, bool);
 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);
 
 static void * xul_handle = NULL;
 static time_t apk_mtime = 0;
 #ifdef DEBUG
 extern "C" int extractLibs = 1;
 #else
 extern "C" int extractLibs = 0;
 #endif
@@ -640,16 +641,17 @@ loadLibs(const char *apkName)
   GETFUNC(cameraCallbackBridge);
   GETFUNC(notifyBatteryChange);
   GETFUNC(notifySmsReceived);
   GETFUNC(bindWidgetTexture);
   GETFUNC(testDirectTexture);
   GETFUNC(saveMessageInSentbox);
   GETFUNC(notifySmsSent);
   GETFUNC(notifySmsDelivered);
+  GETFUNC(notifySmsSendFailed);
 #undef GETFUNC
   sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
   gettimeofday(&t1, 0);
   struct rusage usage2;
   getrusage(RUSAGE_THREAD, &usage2);
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loaded libs in %dms total, %dms user, %dms system, %d faults",
                       (t1.tv_sec - t0.tv_sec)*1000 + (t1.tv_usec - t0.tv_usec)/1000, 
                       (usage2.ru_utime.tv_sec - usage1.ru_utime.tv_sec)*1000 + (usage2.ru_utime.tv_usec - usage1.ru_utime.tv_usec)/1000,
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -61,16 +61,17 @@
 
 #include "mozilla/unused.h"
 
 #include "mozilla/dom/sms/SmsMessage.h"
 #include "mozilla/dom/sms/Constants.h"
 #include "mozilla/dom/sms/Types.h"
 #include "mozilla/dom/sms/PSms.h"
 #include "mozilla/dom/sms/SmsRequestManager.h"
+#include "mozilla/dom/sms/SmsRequest.h"
 #include "mozilla/dom/sms/SmsParent.h"
 #include "nsISmsDatabaseService.h"
 
 using namespace mozilla;
 using namespace mozilla::dom::sms;
 
 /* Forward declare all the JNI methods as extern "C" */
 
@@ -88,16 +89,17 @@ extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass);
     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 PRInt32 JNICALL Java_org_mozilla_gecko_GeckoAppShell_saveMessageInSentbox(JNIEnv* jenv, jclass, jstring, jstring, jlong);
     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);
 
 #ifdef MOZ_JAVA_COMPOSITOR
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass);
     NS_EXPORT bool JNICALL Java_org_mozilla_gecko_GeckoAppShell_testDirectTexture(JNIEnv* jenv, jclass);
 #endif
 }
 
 
@@ -395,16 +397,60 @@ Java_org_mozilla_gecko_GeckoAppShell_not
     SmsMessageData message(aId, eDeliveryState_Sent, EmptyString(),
                            nsJNIString(aReceiver, jenv),
                            nsJNIString(aBody, jenv), aTimestamp);
 
     nsCOMPtr<nsIRunnable> runnable = new NotifySmsDeliveredRunnable(message);
     NS_DispatchToMainThread(runnable);
 }
 
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_notifySmsSendFailed(JNIEnv* jenv, jclass,
+                                                         jint aError,
+                                                         jint aRequestId,
+                                                         jlong aProcessId)
+{
+    class NotifySmsSendFailedRunnable : public nsRunnable {
+    public:
+      NotifySmsSendFailedRunnable(SmsRequest::ErrorType aError,
+                                  PRInt32 aRequestId, PRUint64 aProcessId)
+        : mError(aError)
+        , mRequestId(aRequestId)
+        , mProcessId(aProcessId)
+      {}
+
+      NS_IMETHODIMP Run() {
+        if (mProcessId == 0) { // Parent process.
+          SmsRequestManager::GetInstance()->NotifySmsSendFailed(mRequestId, mError);
+        } else { // Content process.
+          nsTArray<SmsParent*> spList;
+          SmsParent::GetAll(spList);
+
+          for (PRUint32 i=0; i<spList.Length(); ++i) {
+            unused << spList[i]->SendNotifyRequestSmsSendFailed(mError,
+                                                                mRequestId,
+                                                                mProcessId);
+          }
+        }
+
+        return NS_OK;
+      }
+
+    private:
+      SmsRequest::ErrorType mError;
+      PRInt32               mRequestId;
+      PRUint64              mProcessId;
+    };
+
+
+    nsCOMPtr<nsIRunnable> runnable =
+      new NotifySmsSendFailedRunnable(SmsRequest::ErrorType(aError), aRequestId, aProcessId);
+    NS_DispatchToMainThread(runnable);
+}
+
 #ifdef MOZ_JAVA_COMPOSITOR
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass)
 {
     nsWindow::BindToTexture();
 }