LCOV - code coverage report
Current view: directory - dom/system - nsDeviceMotion.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 138 0 0.0 %
Date: 2012-06-02 Functions: 24 0 0.0 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is mozilla.org code.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Doug Turner <dougt@dougt.org>
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      25                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #include "nsDeviceMotion.h"
      38                 : 
      39                 : #include "nsAutoPtr.h"
      40                 : #include "nsIDOMEvent.h"
      41                 : #include "nsIDOMWindow.h"
      42                 : #include "nsPIDOMWindow.h"
      43                 : #include "nsIDOMDocument.h"
      44                 : #include "nsIDOMEventTarget.h"
      45                 : #include "nsIServiceManager.h"
      46                 : #include "nsIPrivateDOMEvent.h"
      47                 : #include "nsIDOMDeviceOrientationEvent.h"
      48                 : #include "nsIDOMDeviceMotionEvent.h"
      49                 : #include "nsIServiceManager.h"
      50                 : #include "nsIPrefService.h"
      51                 : #include "nsDOMDeviceMotionEvent.h"
      52                 : 
      53                 : static const nsTArray<nsIDOMWindow*>::index_type NoIndex =
      54                 :     nsTArray<nsIDOMWindow*>::NoIndex;
      55                 : 
      56                 : class nsDeviceMotionData : public nsIDeviceMotionData
      57                 : {
      58                 : public:
      59                 :   NS_DECL_ISUPPORTS
      60                 :   NS_DECL_NSIDEVICEMOTIONDATA
      61                 : 
      62                 :   nsDeviceMotionData(unsigned long type, double x, double y, double z);
      63                 : 
      64                 : private:
      65                 :   ~nsDeviceMotionData();
      66                 : 
      67                 : protected:
      68                 :   unsigned long mType;
      69                 :   double mX, mY, mZ;
      70                 : };
      71                 : 
      72               0 : nsDeviceMotionData::nsDeviceMotionData(unsigned long type, double x, double y, double z)
      73               0 :   : mType(type), mX(x), mY(y), mZ(z)
      74                 : {
      75               0 : }
      76                 : 
      77               0 : NS_INTERFACE_MAP_BEGIN(nsDeviceMotionData)
      78               0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDeviceMotionData)
      79               0 : NS_INTERFACE_MAP_END
      80                 : 
      81               0 : NS_IMPL_ADDREF(nsDeviceMotionData)
      82               0 : NS_IMPL_RELEASE(nsDeviceMotionData)
      83                 : 
      84               0 : nsDeviceMotionData::~nsDeviceMotionData()
      85                 : {
      86               0 : }
      87                 : 
      88               0 : NS_IMETHODIMP nsDeviceMotionData::GetType(PRUint32 *aType)
      89                 : {
      90               0 :   NS_ENSURE_ARG_POINTER(aType);
      91               0 :   *aType = mType;
      92               0 :   return NS_OK;
      93                 : }
      94                 : 
      95               0 : NS_IMETHODIMP nsDeviceMotionData::GetX(double *aX)
      96                 : {
      97               0 :   NS_ENSURE_ARG_POINTER(aX);
      98               0 :   *aX = mX;
      99               0 :   return NS_OK;
     100                 : }
     101                 : 
     102               0 : NS_IMETHODIMP nsDeviceMotionData::GetY(double *aY)
     103                 : {
     104               0 :   NS_ENSURE_ARG_POINTER(aY);
     105               0 :   *aY = mY;
     106               0 :   return NS_OK;
     107                 : }
     108                 : 
     109               0 : NS_IMETHODIMP nsDeviceMotionData::GetZ(double *aZ)
     110                 : {
     111               0 :   NS_ENSURE_ARG_POINTER(aZ);
     112               0 :   *aZ = mZ;
     113               0 :   return NS_OK;
     114                 : }
     115                 : 
     116               0 : NS_IMPL_ISUPPORTS2(nsDeviceMotion, nsIDeviceMotion, nsIDeviceMotionUpdate)
     117                 : 
     118               0 : nsDeviceMotion::nsDeviceMotion()
     119                 : : mStarted(false),
     120                 :   mUpdateInterval(50), /* default to 50 ms */
     121               0 :   mEnabled(true)
     122                 : {
     123               0 :   nsCOMPtr<nsIPrefBranch> prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID);
     124               0 :   if (prefSrv) {
     125                 :     PRInt32 value;
     126               0 :     nsresult rv = prefSrv->GetIntPref("device.motion.update.interval", &value);
     127               0 :     if (NS_SUCCEEDED(rv))
     128               0 :       mUpdateInterval = value;
     129                 : 
     130                 :     bool bvalue;
     131               0 :     rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue);
     132               0 :     if (NS_SUCCEEDED(rv) && bvalue == false)
     133               0 :       mEnabled = false;
     134                 :   }
     135               0 : }
     136                 : 
     137               0 : nsDeviceMotion::~nsDeviceMotion()
     138                 : {
     139               0 :   if (mTimeoutTimer)
     140               0 :     mTimeoutTimer->Cancel();
     141               0 : }
     142                 : 
     143                 : void
     144               0 : nsDeviceMotion::StartDisconnectTimer()
     145                 : {
     146               0 :   if (mTimeoutTimer)
     147               0 :     mTimeoutTimer->Cancel();
     148                 : 
     149               0 :   mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
     150               0 :   if (mTimeoutTimer)
     151               0 :     mTimeoutTimer->InitWithFuncCallback(TimeoutHandler,
     152                 :                                         this,
     153                 :                                         2000, 
     154               0 :                                         nsITimer::TYPE_ONE_SHOT);  
     155               0 : }
     156                 : 
     157                 : void
     158               0 : nsDeviceMotion::TimeoutHandler(nsITimer *aTimer, void *aClosure)
     159                 : {
     160                 :   // the reason that we use self, instead of just using nsITimerCallback or nsIObserver
     161                 :   // is so that subclasses are free to use timers without worry about the base classes's
     162                 :   // usage.
     163               0 :   nsDeviceMotion *self = reinterpret_cast<nsDeviceMotion *>(aClosure);
     164               0 :   if (!self) {
     165               0 :     NS_ERROR("no self");
     166               0 :     return;
     167                 :   }
     168                 :   
     169                 :   // what about listeners that don't clean up properly?  they will leak
     170               0 :   if (self->mListeners.Count() == 0 && self->mWindowListeners.Length() == 0) {
     171               0 :     self->Shutdown();
     172               0 :     self->mStarted = false;
     173                 :   }
     174                 : }
     175                 : 
     176               0 : NS_IMETHODIMP nsDeviceMotion::AddListener(nsIDeviceMotionListener *aListener)
     177                 : {
     178               0 :   if (mListeners.IndexOf(aListener) != -1)
     179               0 :     return NS_OK; // already exists
     180                 : 
     181               0 :   if (mStarted == false) {
     182               0 :     mStarted = true;
     183               0 :     Startup();
     184                 :   }
     185                 : 
     186               0 :   mListeners.AppendObject(aListener);
     187               0 :   return NS_OK;
     188                 : }
     189                 : 
     190               0 : NS_IMETHODIMP nsDeviceMotion::RemoveListener(nsIDeviceMotionListener *aListener)
     191                 : {
     192               0 :   if (mListeners.IndexOf(aListener) == -1)
     193               0 :     return NS_OK; // doesn't exist
     194                 : 
     195               0 :   mListeners.RemoveObject(aListener);
     196               0 :   StartDisconnectTimer();
     197               0 :   return NS_OK;
     198                 : }
     199                 : 
     200               0 : NS_IMETHODIMP nsDeviceMotion::AddWindowListener(nsIDOMWindow *aWindow)
     201                 : {
     202               0 :   if (mWindowListeners.IndexOf(aWindow) != NoIndex)
     203               0 :       return NS_OK;
     204                 : 
     205               0 :   if (mStarted == false) {
     206               0 :     mStarted = true;
     207               0 :     Startup();
     208                 :   }
     209                 : 
     210               0 :   mWindowListeners.AppendElement(aWindow);
     211               0 :   return NS_OK;
     212                 : }
     213                 : 
     214               0 : NS_IMETHODIMP nsDeviceMotion::RemoveWindowListener(nsIDOMWindow *aWindow)
     215                 : {
     216               0 :   if (mWindowListeners.IndexOf(aWindow) == NoIndex)
     217               0 :     return NS_OK;
     218                 : 
     219               0 :   mWindowListeners.RemoveElement(aWindow);
     220               0 :   StartDisconnectTimer();
     221               0 :   return NS_OK;
     222                 : }
     223                 : 
     224                 : NS_IMETHODIMP
     225               0 : nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z)
     226                 : {
     227               0 :   if (!mEnabled)
     228               0 :     return NS_ERROR_NOT_INITIALIZED;
     229                 : 
     230               0 :   nsCOMArray<nsIDeviceMotionListener> listeners = mListeners;
     231               0 :   for (PRUint32 i = listeners.Count(); i > 0 ; ) {
     232               0 :     --i;
     233               0 :     nsRefPtr<nsDeviceMotionData> a = new nsDeviceMotionData(type, x, y, z);
     234               0 :     listeners[i]->OnMotionChange(a);
     235                 :   }
     236                 : 
     237               0 :   nsCOMArray<nsIDOMWindow> windowListeners;
     238               0 :   for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) {
     239               0 :     windowListeners.AppendObject(mWindowListeners[i]);
     240                 :   }
     241                 : 
     242               0 :   for (PRUint32 i = windowListeners.Count(); i > 0 ; ) {
     243               0 :     --i;
     244                 : 
     245                 :     // check to see if this window is in the background.  if
     246                 :     // it is, don't send any device motion to it.
     247               0 :     nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(windowListeners[i]);
     248               0 :     if (!pwindow ||
     249               0 :         !pwindow->GetOuterWindow() ||
     250               0 :         pwindow->GetOuterWindow()->IsBackground())
     251               0 :       continue;
     252                 : 
     253               0 :     nsCOMPtr<nsIDOMDocument> domdoc;
     254               0 :     windowListeners[i]->GetDocument(getter_AddRefs(domdoc));
     255                 : 
     256               0 :     if (domdoc) {
     257               0 :       nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(windowListeners[i]);
     258               0 :       if (type == nsIDeviceMotionData::TYPE_ACCELERATION)
     259               0 :         FireDOMMotionEvent(domdoc, target, x, y, z);
     260               0 :       else if (type == nsIDeviceMotionData::TYPE_ORIENTATION)
     261               0 :         FireDOMOrientationEvent(domdoc, target, x, y, z);
     262                 :     }
     263                 :   }
     264               0 :   return NS_OK;
     265                 : }
     266                 : 
     267                 : void
     268               0 : nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc,
     269                 :                                         nsIDOMEventTarget *target,
     270                 :                                         double alpha,
     271                 :                                         double beta,
     272                 :                                         double gamma)
     273                 : {
     274               0 :   nsCOMPtr<nsIDOMEvent> event;
     275               0 :   bool defaultActionEnabled = true;
     276               0 :   domdoc->CreateEvent(NS_LITERAL_STRING("DeviceOrientationEvent"), getter_AddRefs(event));
     277                 : 
     278               0 :   nsCOMPtr<nsIDOMDeviceOrientationEvent> oe = do_QueryInterface(event);
     279                 : 
     280               0 :   if (!oe) {
     281                 :     return;
     282                 :   }
     283                 : 
     284               0 :   oe->InitDeviceOrientationEvent(NS_LITERAL_STRING("deviceorientation"),
     285                 :                                  true,
     286                 :                                  false,
     287                 :                                  alpha,
     288                 :                                  beta,
     289                 :                                  gamma,
     290               0 :                                  true);
     291                 : 
     292               0 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
     293               0 :   if (privateEvent)
     294               0 :     privateEvent->SetTrusted(true);
     295                 :   
     296               0 :   target->DispatchEvent(event, &defaultActionEnabled);
     297                 : }
     298                 : 
     299                 : 
     300                 : void
     301               0 : nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc,
     302                 :                                    nsIDOMEventTarget *target,
     303                 :                                    double x,
     304                 :                                    double y,
     305                 :                                    double z) {
     306               0 :   nsCOMPtr<nsIDOMEvent> event;
     307               0 :   bool defaultActionEnabled = true;
     308               0 :   domdoc->CreateEvent(NS_LITERAL_STRING("DeviceMotionEvent"), getter_AddRefs(event));
     309                 : 
     310               0 :   nsCOMPtr<nsIDOMDeviceMotionEvent> me = do_QueryInterface(event);
     311                 : 
     312               0 :   if (!me) {
     313                 :     return;
     314                 : }
     315                 : 
     316                 :   // Currently acceleration as determined includes gravity.
     317               0 :   nsRefPtr<nsDOMDeviceAcceleration> acceleration = new nsDOMDeviceAcceleration(x, y, z);
     318                 : 
     319               0 :   me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"),
     320                 :                             true,
     321                 :                             false,
     322                 :                             nsnull,
     323                 :                             acceleration,
     324                 :                             nsnull,
     325               0 :                             0);
     326                 : 
     327               0 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
     328               0 :   if (privateEvent)
     329               0 :     privateEvent->SetTrusted(true);
     330                 :   
     331               0 :   target->DispatchEvent(event, &defaultActionEnabled);
     332                 : }
     333                 : 

Generated by: LCOV version 1.7