bug 605341 - remote orientation api for android r=dougt a=blocking-fennec
authorBrad Lassey <blassey@mozilla.com>
Fri, 05 Nov 2010 13:43:13 -0400
changeset 56943 22121066081de1d89737ba8d8e8b8fcb64a97f08
parent 56942 847df5a157c9b6e7727c2fb93d7f3ca9099eaa81
child 56944 7a62a113eeb0ab54be689c820c02f5c843c87127
push idunknown
push userunknown
push dateunknown
reviewersdougt, blocking-fennec
bugs605341
milestone2.0b8pre
bug 605341 - remote orientation api for android r=dougt a=blocking-fennec
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/src/geolocation/nsGeolocation.cpp
dom/system/android/nsAccelerometerSystem.cpp
dom/system/nsAccelerometer.cpp
dom/system/nsAccelerometer.h
xpcom/system/nsIAccelerometer.idl
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -85,16 +85,18 @@
 #if defined(ANDROID) || defined(LINUX)
 #include <sys/time.h>
 #include <sys/resource.h>
 // TODO: For other platforms that support setpriority, figure out
 //       appropriate values of niceness
 static const int kRelativeNiceness = 10;
 #endif
 
+#include "nsAccelerometer.h"
+
 using namespace mozilla::ipc;
 using namespace mozilla::net;
 using namespace mozilla::places;
 using namespace mozilla::docshell;
 
 namespace mozilla {
 namespace dom {
 class AlertObserver
@@ -482,11 +484,21 @@ ContentChild::RecvAddPermission(const IP
                                  permission.expireType,
                                  permission.expireTime,
                                  nsPermissionManager::eNotify,
                                  nsPermissionManager::eNoDBOperation);
 #endif
 
   return true;
 }
+bool
+ContentChild::RecvAccelerationChanged(const double& x, const double& y,
+                                      const double& z)
+{
+    nsCOMPtr<nsIAccelerometerUpdate> acu = 
+        do_GetService(NS_ACCELEROMETER_CONTRACTID);
+    if (acu)
+        acu->AccelerationChanged(x, y, z);
+    return true;
+}
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -109,16 +109,19 @@ public:
     virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData);
 
     virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
 
     virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);
 
     virtual bool RecvAddPermission(const IPC::Permission& permission);
 
+    virtual bool RecvAccelerationChanged(const double& x, const double& y,
+                                         const double& z);
+
 private:
     NS_OVERRIDE
     virtual void ActorDestroy(ActorDestroyReason why);
 
     NS_OVERRIDE
     virtual void ProcessingError(Result what);
 
     /**
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -67,16 +67,17 @@
 #include "nsIScriptError.h"
 #include "nsConsoleMessage.h"
 
 #ifdef MOZ_PERMISSIONS
 #include "nsPermissionManager.h"
 #endif
 
 #include "mozilla/dom/ExternalHelperAppParent.h"
+#include "nsAccelerometer.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::net;
 using namespace mozilla::places;
 using mozilla::MonitorAutoEnter;
 
 namespace mozilla {
 namespace dom {
@@ -283,17 +284,17 @@ ContentParent::Observe(nsISupports* aSub
         nsCOMPtr<nsIPrefBranch2> prefs 
             (do_GetService(NS_PREFSERVICE_CONTRACTID));
         if (prefs) { 
             if (gSingleton) {
                 prefs->RemoveObserver("", this);
             }
         }
 
-        RecvGeolocationStop();
+        RecvRemoveGeolocationListener();
             
         Close();
         XRE_GetIOMessageLoop()->PostTask(
             FROM_HERE,
             NewRunnableFunction(DeleteSubprocess, mSubprocess));
         mSubprocess = nsnull;
     }
 
@@ -617,42 +618,62 @@ ContentParent::RecvAsyncMessage(const ns
   if (ppm) {
     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
                         aMsg, PR_FALSE, aJSON, nsnull, nsnull);
   }
   return true;
 }
 
 bool
-ContentParent::RecvGeolocationStart()
+ContentParent::RecvAddGeolocationListener()
 {
   if (mGeolocationWatchID == -1) {
     nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
     if (!geo) {
       return true;
     }
     geo->WatchPosition(this, nsnull, nsnull, &mGeolocationWatchID);
   }
   return true;
 }
 
 bool
-ContentParent::RecvGeolocationStop()
+ContentParent::RecvRemoveGeolocationListener()
 {
   if (mGeolocationWatchID != -1) {
     nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
     if (!geo) {
       return true;
     }
     geo->ClearWatch(mGeolocationWatchID);
     mGeolocationWatchID = -1;
   }
   return true;
 }
 
+bool
+ContentParent::RecvAddAccelerometerListener()
+{
+    nsCOMPtr<nsIAccelerometer> ac = 
+        do_GetService(NS_ACCELEROMETER_CONTRACTID);
+    if (ac)
+        ac->AddListener(this);
+    return true;
+}
+
+bool
+ContentParent::RecvRemoveAccelerometerListener()
+{
+    nsCOMPtr<nsIAccelerometer> ac = 
+        do_GetService(NS_ACCELEROMETER_CONTRACTID);
+    if (ac)
+        ac->RemoveListener(this);
+    return true;
+}
+
 NS_IMETHODIMP
 ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
 {
   SendGeolocationUpdate(GeoPosition(postion));
   return NS_OK;
 }
 
 bool
@@ -685,10 +706,24 @@ ContentParent::RecvScriptError(const nsS
                           aLineNumber, aColNumber, aFlags, aCategory.get());
   if (NS_FAILED(rv))
     return true;
 
   svc->LogMessage(msg);
   return true;
 }
 
+NS_IMETHODIMP
+ContentParent::OnAccelerationChange(nsIAcceleration *aAcceleration)
+{
+    double x, y, z;
+    aAcceleration->GetX(&x);
+    aAcceleration->GetY(&y);
+    aAcceleration->GetZ(&z);
+
+    mozilla::dom::ContentParent::GetSingleton()->
+        SendAccelerationChanged(x, y, z);
+    return NS_OK;
+}
+
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -46,31 +46,33 @@
 
 #include "nsIObserver.h"
 #include "nsIThreadInternal.h"
 #include "mozilla/Monitor.h"
 #include "nsNetUtil.h"
 #include "nsIPrefService.h"
 #include "nsIPermissionManager.h"
 #include "nsIDOMGeoPositionCallback.h"
+#include "nsIAccelerometer.h"
 
 namespace mozilla {
 
 namespace ipc {
 class TestShellParent;
 }
 
 namespace dom {
 
 class TabParent;
 
 class ContentParent : public PContentParent
                     , public nsIObserver
                     , public nsIThreadObserver
                     , public nsIDOMGeoPositionCallback
+                    , public nsIAccelerationListener
 {
 private:
     typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
     typedef mozilla::ipc::TestShellParent TestShellParent;
 
 public:
     static ContentParent* GetSingleton(PRBool aForceNew = PR_TRUE);
 
@@ -78,16 +80,17 @@ public:
     // TODO: implement this somewhere!
     static ContentParent* FreeSingleton();
 #endif
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
+    NS_DECL_NSIACCELERATIONLISTENER
 
     TabParent* CreateTab(PRUint32 aChromeFlags);
 
     TestShellParent* CreateTestShell();
     bool DestroyTestShell(TestShellParent* aTestShell);
 
     void ReportChildAlreadyBlocked();
     bool RequestRunToCompletion();
@@ -156,18 +159,20 @@ private:
                                            const nsString& aCookie, const nsString& aName);
 
     virtual bool RecvLoadURIExternal(const IPC::URI& uri);
 
     virtual bool RecvSyncMessage(const nsString& aMsg, const nsString& aJSON,
                                  nsTArray<nsString>* aRetvals);
     virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
 
-    virtual bool RecvGeolocationStart();
-    virtual bool RecvGeolocationStop();
+    virtual bool RecvAddGeolocationListener();
+    virtual bool RecvRemoveGeolocationListener();
+    virtual bool RecvAddAccelerometerListener();
+    virtual bool RecvRemoveAccelerometerListener();
 
     virtual bool RecvConsoleMessage(const nsString& aMessage);
     virtual bool RecvScriptError(const nsString& aMessage,
                                  const nsString& aSourceName,
                                  const nsString& aSourceLine,
                                  const PRUint32& aLineNumber,
                                  const PRUint32& aColNumber,
                                  const PRUint32& aFlags,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -83,16 +83,18 @@ child:
 
     NotifyAlertsObserver(nsCString topic, nsString data);
 
     GeolocationUpdate(GeoPosition somewhere);
 
     // nsIPermissionManager messages
     AddPermission(Permission permission);
 
+    AccelerationChanged(double x, double y, double z);
+
 parent:
     PNecko();
 
     // Services remoting
 
     async StartVisitedQuery(URI uri);
     async VisitURI(URI uri, URI referrer, PRUint32 flags);
     async SetURITitle(URI uri, nsString title);
@@ -117,18 +119,20 @@ parent:
                           PRBool textClickable,
                           nsString cookie,
                           nsString name);
 
     PExternalHelperApp(URI uri, nsCString aMimeContentType,
                        nsCString aContentDisposition, bool aForceSave,
                        PRInt64 aContentLength);
     
-    GeolocationStart();
-    GeolocationStop();
+    AddGeolocationListener();
+    RemoveGeolocationListener();
+    AddAccelerometerListener();
+    RemoveAccelerometerListener();
 
     ConsoleMessage(nsString message);
     ScriptError(nsString message, nsString sourceName, nsString sourceLine,
                 PRUint32 lineNumber, PRUint32 colNumber, PRUint32 flags,
                 nsCString category); 
 
     // nsIPermissionManager messages
     sync ReadPermissions() returns (Permission[] permissions);
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -744,17 +744,17 @@ nsGeolocationService::StartDevice()
   // we do not want to keep the geolocation devices online
   // indefinitely.  Close them down after a reasonable period of
   // inactivivity
   SetDisconnectTimer();
 
 #ifdef MOZ_IPC
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     ContentChild* cpc = ContentChild::GetSingleton();
-    cpc->SendGeolocationStart();
+    cpc->SendAddGeolocationListener();
     return NS_OK;
   }
 #endif
 
   // Start them up!
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs)
     return NS_ERROR_FAILURE;
@@ -789,17 +789,17 @@ nsGeolocationService::StopDevice()
   if(mDisconnectTimer) {
     mDisconnectTimer->Cancel();
     mDisconnectTimer = nsnull;
   }
 
 #ifdef MOZ_IPC
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     ContentChild* cpc = ContentChild::GetSingleton();
-    cpc->SendGeolocationStop();
+    cpc->SendRemoveGeolocationListener();
     return; // bail early
   }
 #endif
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs)
     return;
 
--- a/dom/system/android/nsAccelerometerSystem.cpp
+++ b/dom/system/android/nsAccelerometerSystem.cpp
@@ -30,36 +30,44 @@
  * use your version of this file under the terms of the MPL, indicate your
  * 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 "mozilla/dom/ContentChild.h"
 #include "nsAccelerometerSystem.h"
 
 #include "AndroidBridge.h"
+#include "nsXULAppAPI.h"
 
 using namespace mozilla;
 
 extern nsAccelerometerSystem *gAccel;
 
 nsAccelerometerSystem::nsAccelerometerSystem()
 {
     gAccel = this;
 }
 
 nsAccelerometerSystem::~nsAccelerometerSystem()
 {
 }
 
 void nsAccelerometerSystem::Startup()
 {
-    if (AndroidBridge::Bridge())
+    if (XRE_GetProcessType() == GeckoProcessType_Default)
         AndroidBridge::Bridge()->EnableAccelerometer(true);
+    else
+        mozilla::dom::ContentChild::GetSingleton()->
+            SendAddAccelerometerListener();
 }
 
 void nsAccelerometerSystem::Shutdown()
 {
-    if (AndroidBridge::Bridge())
+    if (XRE_GetProcessType() == GeckoProcessType_Default)
         AndroidBridge::Bridge()->EnableAccelerometer(false);
+    else
+        mozilla::dom::ContentChild::GetSingleton()->
+            SendRemoveAccelerometerListener();
 }
--- a/dom/system/nsAccelerometer.cpp
+++ b/dom/system/nsAccelerometer.cpp
@@ -92,17 +92,17 @@ NS_IMETHODIMP nsAcceleration::GetY(doubl
 
 NS_IMETHODIMP nsAcceleration::GetZ(double *aZ)
 {
   NS_ENSURE_ARG_POINTER(aZ);
   *aZ = mZ;
   return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS1(nsAccelerometer, nsIAccelerometer)
+NS_IMPL_ISUPPORTS2(nsAccelerometer, nsIAccelerometer, nsIAccelerometerUpdate)
 
 nsAccelerometer::nsAccelerometer()
 : mLastX(10), /* initialize to values that can't be possible */
   mLastY(10),
   mLastZ(10),
   mStarted(PR_FALSE),
   mNewListener(PR_FALSE),
   mUpdateInterval(50), /* default to 50 ms */
@@ -195,21 +195,21 @@ NS_IMETHODIMP nsAccelerometer::AddWindow
 NS_IMETHODIMP nsAccelerometer::RemoveWindowListener(nsIDOMWindow *aWindow)
 {
   mWindowListeners.RemoveObject(aWindow);
   StartDisconnectTimer();
 
   return NS_OK;
 }
 
-void 
+NS_IMETHODIMP
 nsAccelerometer::AccelerationChanged(double x, double y, double z)
 {
   if (!mEnabled)
-    return;
+    return NS_ERROR_NOT_INITIALIZED;
 
   if (x > 1)
     x = 1;
   if (y > 1)
     y = 1;
   if (z > 1)
     z = 1;
   if (x < -1)
@@ -218,17 +218,17 @@ nsAccelerometer::AccelerationChanged(dou
     y = -1;
   if (z < -1)
     z = -1;
 
   if (!mNewListener) {
     if (PR_ABS(mLastX - x) < .01 &&
         PR_ABS(mLastY - y) < .01 &&
         PR_ABS(mLastZ - z) < .01)
-      return;
+      return NS_OK;
   }
 
   mLastX = x;
   mLastY = y;
   mLastZ = z;
   mNewListener = PR_FALSE;
 
   for (PRUint32 i = mListeners.Count(); i > 0 ; ) {
@@ -265,9 +265,10 @@ nsAccelerometer::AccelerationChanged(dou
         if (privateEvent)
           privateEvent->SetTrusted(PR_TRUE);
         
         nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mWindowListeners[i]));
         target->DispatchEvent(event, &defaultActionEnabled);
       }
     }
   }
+  return NS_OK;
 }
--- a/dom/system/nsAccelerometer.h
+++ b/dom/system/nsAccelerometer.h
@@ -45,29 +45,27 @@
 #define NS_ACCELEROMETER_CID \
 { 0xecba5203, 0x77da, 0x465a, \
 { 0x86, 0x5e, 0x78, 0xb7, 0xaf, 0x10, 0xd8, 0xf7 } }
 
 #define NS_ACCELEROMETER_CONTRACTID "@mozilla.org/accelerometer;1"
 
 class nsIDOMWindow;
 
-class nsAccelerometer : public nsIAccelerometer
+class nsAccelerometer : public nsIAccelerometerUpdate
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIACCELEROMETER
+  NS_DECL_NSIACCELEROMETERUPDATE
 
   nsAccelerometer();
 
   virtual ~nsAccelerometer();
 
-  /* must be called on the main thread or else */
-  void AccelerationChanged(double x, double y, double z);
-
   double mLastX;
   double mLastY;
   double mLastZ;
 
 private:
   nsCOMArray<nsIAccelerationListener> mListeners;
   nsCOMArray<nsIDOMWindow> mWindowListeners;
 
--- a/xpcom/system/nsIAccelerometer.idl
+++ b/xpcom/system/nsIAccelerometer.idl
@@ -57,8 +57,18 @@ interface nsIAccelerometer : nsISupports
 {
   void addListener(in nsIAccelerationListener aListener);
   void removeListener(in nsIAccelerationListener aListener);
 
   void addWindowListener(in nsIDOMWindow aWindow);
   void removeWindowListener(in nsIDOMWindow aWindow);
 
 };
+
+/* for use by IPC system to notify non-chrome processes of 
+ * accelerometer events
+ */
+[uuid(22dd1d8a-51bf-406f-8b6d-d1919f8f1c7d)]
+interface nsIAccelerometerUpdate : nsIAccelerometer
+{
+  /* must be called on the main thread or else */
+  void accelerationChanged(in double x, in double y, in double z);
+};