dom/camera/CameraControlImpl.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "CameraControlImpl.h"
     6 #include "base/basictypes.h"
     7 #include "mozilla/Assertions.h"
     8 #include "mozilla/unused.h"
     9 #include "nsIWeakReferenceUtils.h"
    10 #include "CameraRecorderProfiles.h"
    11 #include "CameraCommon.h"
    12 #include "nsGlobalWindow.h"
    13 #include "DeviceStorageFileDescriptor.h"
    14 #include "CameraControlListener.h"
    16 using namespace mozilla;
    18 nsWeakPtr CameraControlImpl::sCameraThread;
    20 CameraControlImpl::CameraControlImpl(uint32_t aCameraId)
    21   : mCameraId(aCameraId)
    22   , mPreviewState(CameraControlListener::kPreviewStopped)
    23   , mHardwareState(CameraControlListener::kHardwareClosed)
    24 {
    25   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
    27   // reuse the same camera thread to conserve resources
    28   nsCOMPtr<nsIThread> ct = do_QueryReferent(sCameraThread);
    29   if (ct) {
    30     mCameraThread = ct.forget();
    31   } else {
    32     nsresult rv = NS_NewNamedThread("CameraThread", getter_AddRefs(mCameraThread));
    33     unused << rv; // swallow rv to suppress a compiler warning when the macro
    34                   // is #defined to nothing (i.e. in non-DEBUG builds).
    35     MOZ_ASSERT(NS_SUCCEEDED(rv));
    37     // keep a weak reference to the new thread
    38     sCameraThread = do_GetWeakReference(mCameraThread);
    39   }
    41   // Care must be taken with the mListenerLock read-write lock to prevent
    42   // deadlocks. Currently this is handled by ensuring that any attempts to
    43   // acquire the lock for writing (as in Add/RemoveListener()) happen in a
    44   // runnable dispatched to the Camera Thread--even if the method is being
    45   // called from that thread. This ensures that if a registered listener
    46   // (which is invoked with a read-lock) tries to call Add/RemoveListener(),
    47   // the lock-for-writing attempt won't happen until the listener has
    48   // completed.
    49   //
    50   // Multiple parallel listeners being invoked are not a problem because
    51   // the read-write lock allows multiple simultaneous read-locks.
    52   mListenerLock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "CameraControlImpl.Listeners.Lock");
    53 }
    55 CameraControlImpl::~CameraControlImpl()
    56 {
    57   if (mListenerLock) {
    58     PR_DestroyRWLock(mListenerLock);
    59     mListenerLock = nullptr;
    60   }
    61 }
    63 already_AddRefed<RecorderProfileManager>
    64 CameraControlImpl::GetRecorderProfileManager()
    65 {
    66   return GetRecorderProfileManagerImpl();
    67 }
    69 void
    70 CameraControlImpl::Shutdown()
    71 {
    72   DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
    73 }
    75 void
    76 CameraControlImpl::OnHardwareStateChange(CameraControlListener::HardwareState aNewState)
    77 {
    78   // This callback can run on threads other than the Main Thread and
    79   //  the Camera Thread. On Gonk, it may be called from the camera's
    80   //  local binder thread, should the mediaserver process die.
    81   RwLockAutoEnterRead lock(mListenerLock);
    83   if (aNewState == mHardwareState) {
    84     DOM_CAMERA_LOGI("OnHardwareStateChange: state did not change from %d\n", mHardwareState);
    85     return;
    86   }
    88 #ifdef PR_LOGGING
    89   const char* state[] = { "open", "closed", "failed" };
    90   MOZ_ASSERT(aNewState >= 0);
    91   if (static_cast<unsigned int>(aNewState) < sizeof(state) / sizeof(state[0])) {
    92     DOM_CAMERA_LOGI("New hardware state is '%s'\n", state[aNewState]);
    93   } else {
    94     DOM_CAMERA_LOGE("OnHardwareStateChange: got invalid HardwareState value %d\n", aNewState);
    95   }
    96 #endif
    98   mHardwareState = aNewState;
   100   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   101     CameraControlListener* l = mListeners[i];
   102     l->OnHardwareStateChange(mHardwareState);
   103   }
   104 }
   106 void
   107 CameraControlImpl::OnConfigurationChange()
   108 {
   109   MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread);
   110   RwLockAutoEnterRead lock(mListenerLock);
   112   DOM_CAMERA_LOGI("OnConfigurationChange : %d listeners\n", mListeners.Length());
   114   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   115     CameraControlListener* l = mListeners[i];
   116     l->OnConfigurationChange(mCurrentConfiguration);
   117   }
   118 }
   120 void
   121 CameraControlImpl::OnAutoFocusComplete(bool aAutoFocusSucceeded)
   122 {
   123   // This callback can run on threads other than the Main Thread and
   124   //  the Camera Thread. On Gonk, it is called from the camera
   125   //  library's auto focus thread.
   126   RwLockAutoEnterRead lock(mListenerLock);
   128   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   129     CameraControlListener* l = mListeners[i];
   130     l->OnAutoFocusComplete(aAutoFocusSucceeded);
   131   }
   132 }
   134 void
   135 CameraControlImpl::OnAutoFocusMoving(bool aIsMoving)
   136 {
   137   RwLockAutoEnterRead lock(mListenerLock);
   139   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   140     CameraControlListener* l = mListeners[i];
   141     l->OnAutoFocusMoving(aIsMoving);
   142   }
   143 }
   145 void
   146 CameraControlImpl::OnFacesDetected(const nsTArray<Face>& aFaces)
   147 {
   148   // This callback can run on threads other than the Main Thread and
   149   //  the Camera Thread. On Gonk, it is called from the camera
   150   //  library's face detection thread.
   151   RwLockAutoEnterRead lock(mListenerLock);
   153   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   154     CameraControlListener* l = mListeners[i];
   155     l->OnFacesDetected(aFaces);
   156   }
   157 }
   159 void
   160 CameraControlImpl::OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
   161 {
   162   // This callback can run on threads other than the Main Thread and
   163   //  the Camera Thread. On Gonk, it is called from the camera
   164   //  library's snapshot thread.
   165   RwLockAutoEnterRead lock(mListenerLock);
   167   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   168     CameraControlListener* l = mListeners[i];
   169     l->OnTakePictureComplete(aData, aLength, aMimeType);
   170   }
   171 }
   173 void
   174 CameraControlImpl::OnShutter()
   175 {
   176   // This callback can run on threads other than the Main Thread and
   177   //  the Camera Thread. On Gonk, it is called from the camera driver's
   178   //  preview thread.
   179   RwLockAutoEnterRead lock(mListenerLock);
   181   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   182     CameraControlListener* l = mListeners[i];
   183     l->OnShutter();
   184   }
   185 }
   187 void
   188 CameraControlImpl::OnClosed()
   189 {
   190   // This callback can run on threads other than the Main Thread and
   191   //  the Camera Thread.
   192   RwLockAutoEnterRead lock(mListenerLock);
   194   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   195     CameraControlListener* l = mListeners[i];
   196     l->OnHardwareStateChange(CameraControlListener::kHardwareClosed);
   197   }
   198 }
   200 void
   201 CameraControlImpl::OnRecorderStateChange(CameraControlListener::RecorderState aState,
   202                                          int32_t aStatus, int32_t aTrackNumber)
   203 {
   204   // This callback can run on threads other than the Main Thread and
   205   //  the Camera Thread. On Gonk, it is called from the media encoder
   206   //  thread.
   207   RwLockAutoEnterRead lock(mListenerLock);
   209   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   210     CameraControlListener* l = mListeners[i];
   211     l->OnRecorderStateChange(aState, aStatus, aTrackNumber);
   212   }
   213 }
   215 void
   216 CameraControlImpl::OnPreviewStateChange(CameraControlListener::PreviewState aNewState)
   217 {
   218   // This callback runs on the Main Thread and the Camera Thread, and
   219   //  may run on the local binder thread, should the mediaserver
   220   //  process die.
   221   RwLockAutoEnterRead lock(mListenerLock);
   223   if (aNewState == mPreviewState) {
   224     DOM_CAMERA_LOGI("OnPreviewStateChange: state did not change from %d\n", mPreviewState);
   225     return;
   226   }
   228 #ifdef PR_LOGGING
   229   const char* state[] = { "stopped", "paused", "started" };
   230   MOZ_ASSERT(aNewState >= 0);
   231   if (static_cast<unsigned int>(aNewState) < sizeof(state) / sizeof(state[0])) {
   232     DOM_CAMERA_LOGI("New preview state is '%s'\n", state[aNewState]);
   233   } else {
   234     DOM_CAMERA_LOGE("OnPreviewStateChange: got unknown PreviewState value %d\n", aNewState);
   235   }
   236 #endif
   238   mPreviewState = aNewState;
   240   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   241     CameraControlListener* l = mListeners[i];
   242     l->OnPreviewStateChange(mPreviewState);
   243   }
   244 }
   246 bool
   247 CameraControlImpl::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
   248 {
   249   // This function runs on neither the Main Thread nor the Camera Thread.
   250   //  On Gonk, it is called from the camera driver's preview thread.
   251   RwLockAutoEnterRead lock(mListenerLock);
   253   DOM_CAMERA_LOGI("OnNewPreviewFrame: we have %d preview frame listener(s)\n",
   254     mListeners.Length());
   256   bool consumed = false;
   258   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   259     CameraControlListener* l = mListeners[i];
   260     consumed = l->OnNewPreviewFrame(aImage, aWidth, aHeight) || consumed;
   261   }
   262   return consumed;
   263 }
   265 void
   266 CameraControlImpl::OnError(CameraControlListener::CameraErrorContext aContext,
   267                            CameraControlListener::CameraError aError)
   268 {
   269   // This callback can run on threads other than the Main Thread and
   270   //  the Camera Thread.
   271   RwLockAutoEnterRead lock(mListenerLock);
   273 #ifdef PR_LOGGING
   274   const char* error[] = {
   275     "api-failed",
   276     "init-failed",
   277     "invalid-configuration",
   278     "service-failed",
   279     "set-picture-size-failed",
   280     "set-thumbnail-size-failed",
   281     "unknown"
   282   };
   283   const char* context[] = {
   284     "StartCamera",
   285     "StopCamera",
   286     "AutoFocus",
   287     "StartFaceDetection",
   288     "StopFaceDetection",
   289     "TakePicture",
   290     "StartRecording",
   291     "StopRecording",
   292     "SetConfiguration",
   293     "StartPreview",
   294     "StopPreview",
   295     "ResumeContinuousFocus",
   296     "Unspecified"
   297   };
   298   if (static_cast<unsigned int>(aError) < sizeof(error) / sizeof(error[0]) &&
   299     static_cast<unsigned int>(aContext) < sizeof(context) / sizeof(context[0])) {
   300     DOM_CAMERA_LOGW("CameraControlImpl::OnError : aContext='%s' (%u), aError='%s' (%u)\n",
   301       context[aContext], aContext, error[aError], aError);
   302   } else {
   303     DOM_CAMERA_LOGE("CameraControlImpl::OnError : aContext=%u, aError=%d\n",
   304       aContext, aError);
   305   }
   306 #endif
   308   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
   309     CameraControlListener* l = mListeners[i];
   310     l->OnError(aContext, aError);
   311   }
   312 }
   314 // Camera control asynchronous message; these are dispatched from
   315 //  the Main Thread to the Camera Thread, where they are consumed.
   317 class CameraControlImpl::ControlMessage : public nsRunnable
   318 {
   319 public:
   320   ControlMessage(CameraControlImpl* aCameraControl,
   321                  CameraControlListener::CameraErrorContext aContext)
   322     : mCameraControl(aCameraControl)
   323     , mContext(aContext)
   324   {
   325     MOZ_COUNT_CTOR(CameraControlImpl::ControlMessage);
   326   }
   328   virtual ~ControlMessage()
   329   {
   330     MOZ_COUNT_DTOR(CameraControlImpl::ControlMessage);
   331   }
   333   virtual nsresult RunImpl() = 0;
   335   NS_IMETHOD
   336   Run() MOZ_OVERRIDE
   337   {
   338     MOZ_ASSERT(mCameraControl);
   339     MOZ_ASSERT(NS_GetCurrentThread() == mCameraControl->mCameraThread);
   341     nsresult rv = RunImpl();
   342     if (NS_FAILED(rv)) {
   343       DOM_CAMERA_LOGW("Camera control API failed at %d with 0x%x\n", mContext, rv);
   344       // XXXmikeh - do we want to report a more specific error code?
   345       mCameraControl->OnError(mContext, CameraControlListener::kErrorApiFailed);
   346     }
   348     return NS_OK;
   349   }
   351 protected:
   352   nsRefPtr<CameraControlImpl> mCameraControl;
   353   CameraControlListener::CameraErrorContext mContext;
   354 };
   356 nsresult
   357 CameraControlImpl::Start(const Configuration* aConfig)
   358 {
   359   class Message : public ControlMessage
   360   {
   361   public:
   362     Message(CameraControlImpl* aCameraControl,
   363             CameraControlListener::CameraErrorContext aContext,
   364             const Configuration* aConfig)
   365       : ControlMessage(aCameraControl, aContext)
   366       , mHaveInitialConfig(false)
   367     {
   368       if (aConfig) {
   369         mConfig = *aConfig;
   370         mHaveInitialConfig = true;
   371       }
   372     }
   374     nsresult
   375     RunImpl() MOZ_OVERRIDE
   376     {
   377       if (mHaveInitialConfig) {
   378         return mCameraControl->StartImpl(&mConfig);
   379       }
   380       return mCameraControl->StartImpl();
   381     }
   383   protected:
   384     bool mHaveInitialConfig;
   385     Configuration mConfig;
   386   };
   388   return mCameraThread->Dispatch(
   389     new Message(this, CameraControlListener::kInStartCamera, aConfig), NS_DISPATCH_NORMAL);
   390 }
   392 nsresult
   393 CameraControlImpl::SetConfiguration(const Configuration& aConfig)
   394 {
   395   class Message : public ControlMessage
   396   {
   397   public:
   398     Message(CameraControlImpl* aCameraControl,
   399             CameraControlListener::CameraErrorContext aContext,
   400             const Configuration& aConfig)
   401       : ControlMessage(aCameraControl, aContext)
   402       , mConfig(aConfig)
   403     { }
   405     nsresult
   406     RunImpl() MOZ_OVERRIDE
   407     {
   408       return mCameraControl->SetConfigurationImpl(mConfig);
   409     }
   411   protected:
   412     Configuration mConfig;
   413   };
   415   return mCameraThread->Dispatch(
   416     new Message(this, CameraControlListener::kInSetConfiguration, aConfig), NS_DISPATCH_NORMAL);
   417 }
   419 nsresult
   420 CameraControlImpl::AutoFocus()
   421 {
   422   class Message : public ControlMessage
   423   {
   424   public:
   425     Message(CameraControlImpl* aCameraControl,
   426             CameraControlListener::CameraErrorContext aContext)
   427       : ControlMessage(aCameraControl, aContext)
   428     { }
   430     nsresult
   431     RunImpl() MOZ_OVERRIDE
   432     {
   433       return mCameraControl->AutoFocusImpl();
   434     }
   435   };
   437   return mCameraThread->Dispatch(
   438     new Message(this, CameraControlListener::kInAutoFocus), NS_DISPATCH_NORMAL);
   439 }
   441 nsresult
   442 CameraControlImpl::StartFaceDetection()
   443 {
   444   class Message : public ControlMessage
   445   {
   446   public:
   447     Message(CameraControlImpl* aCameraControl,
   448             CameraControlListener::CameraErrorContext aContext)
   449       : ControlMessage(aCameraControl, aContext)
   450     { }
   452     nsresult
   453     RunImpl() MOZ_OVERRIDE
   454     {
   455       return mCameraControl->StartFaceDetectionImpl();
   456     }
   457   };
   459   return mCameraThread->Dispatch(
   460     new Message(this, CameraControlListener::kInStartFaceDetection), NS_DISPATCH_NORMAL);
   461 }
   463 nsresult
   464 CameraControlImpl::StopFaceDetection()
   465 {
   466   class Message : public ControlMessage
   467   {
   468   public:
   469     Message(CameraControlImpl* aCameraControl,
   470             CameraControlListener::CameraErrorContext aContext)
   471       : ControlMessage(aCameraControl, aContext)
   472     { }
   474     nsresult
   475     RunImpl() MOZ_OVERRIDE
   476     {
   477       return mCameraControl->StopFaceDetectionImpl();
   478     }
   479   };
   481   return mCameraThread->Dispatch(
   482     new Message(this, CameraControlListener::kInStopFaceDetection), NS_DISPATCH_NORMAL);
   483 }
   485 nsresult
   486 CameraControlImpl::TakePicture()
   487 {
   488   class Message : public ControlMessage
   489   {
   490   public:
   491     Message(CameraControlImpl* aCameraControl,
   492             CameraControlListener::CameraErrorContext aContext)
   493       : ControlMessage(aCameraControl, aContext)
   494     { }
   496     nsresult
   497     RunImpl() MOZ_OVERRIDE
   498     {
   499       return mCameraControl->TakePictureImpl();
   500     }
   501   };
   503   return mCameraThread->Dispatch(
   504     new Message(this, CameraControlListener::kInTakePicture), NS_DISPATCH_NORMAL);
   505 }
   507 nsresult
   508 CameraControlImpl::StartRecording(DeviceStorageFileDescriptor* aFileDescriptor,
   509                                   const StartRecordingOptions* aOptions)
   510 {
   511   class Message : public ControlMessage
   512   {
   513   public:
   514     Message(CameraControlImpl* aCameraControl,
   515             CameraControlListener::CameraErrorContext aContext,
   516             const StartRecordingOptions* aOptions,
   517             DeviceStorageFileDescriptor* aFileDescriptor)
   518       : ControlMessage(aCameraControl, aContext)
   519       , mOptionsPassed(false)
   520       , mFileDescriptor(aFileDescriptor)
   521     {
   522       if (aOptions) {
   523         mOptions = *aOptions;
   524         mOptionsPassed = true;
   525       }
   526     }
   528     nsresult
   529     RunImpl() MOZ_OVERRIDE
   530     {
   531       return mCameraControl->StartRecordingImpl(mFileDescriptor,
   532         mOptionsPassed ? &mOptions : nullptr);
   533     }
   535   protected:
   536     StartRecordingOptions mOptions;
   537     bool mOptionsPassed;
   538     nsRefPtr<DeviceStorageFileDescriptor> mFileDescriptor;
   539   };
   542   return mCameraThread->Dispatch(new Message(this, CameraControlListener::kInStartRecording,
   543     aOptions, aFileDescriptor), NS_DISPATCH_NORMAL);
   544 }
   546 nsresult
   547 CameraControlImpl::StopRecording()
   548 {
   549   class Message : public ControlMessage
   550   {
   551   public:
   552     Message(CameraControlImpl* aCameraControl,
   553             CameraControlListener::CameraErrorContext aContext)
   554       : ControlMessage(aCameraControl, aContext)
   555     { }
   557     nsresult
   558     RunImpl() MOZ_OVERRIDE
   559     {
   560       return mCameraControl->StopRecordingImpl();
   561     }
   562   };
   564   return mCameraThread->Dispatch(
   565     new Message(this, CameraControlListener::kInStopRecording), NS_DISPATCH_NORMAL);
   566 }
   568 nsresult
   569 CameraControlImpl::StartPreview()
   570 {
   571   class Message : public ControlMessage
   572   {
   573   public:
   574     Message(CameraControlImpl* aCameraControl,
   575             CameraControlListener::CameraErrorContext aContext)
   576       : ControlMessage(aCameraControl, aContext)
   577     { }
   579     nsresult
   580     RunImpl() MOZ_OVERRIDE
   581     {
   582       return mCameraControl->StartPreviewImpl();
   583     }
   584   };
   586   return mCameraThread->Dispatch(
   587     new Message(this, CameraControlListener::kInStartPreview), NS_DISPATCH_NORMAL);
   588 }
   590 nsresult
   591 CameraControlImpl::StopPreview()
   592 {
   593   class Message : public ControlMessage
   594   {
   595   public:
   596     Message(CameraControlImpl* aCameraControl,
   597             CameraControlListener::CameraErrorContext aContext)
   598       : ControlMessage(aCameraControl, aContext)
   599     { }
   601     nsresult
   602     RunImpl() MOZ_OVERRIDE
   603     {
   604       return mCameraControl->StopPreviewImpl();
   605     }
   606   };
   608   return mCameraThread->Dispatch(
   609     new Message(this, CameraControlListener::kInStopPreview), NS_DISPATCH_NORMAL);
   610 }
   612 nsresult
   613 CameraControlImpl::ResumeContinuousFocus()
   614 {
   615   class Message : public ControlMessage
   616   {
   617   public:
   618     Message(CameraControlImpl* aCameraControl,
   619             CameraControlListener::CameraErrorContext aContext)
   620       : ControlMessage(aCameraControl, aContext)
   621     { }
   623     nsresult
   624     RunImpl() MOZ_OVERRIDE
   625     {
   626       return mCameraControl->ResumeContinuousFocusImpl();
   627     }
   628   };
   630   return mCameraThread->Dispatch(
   631     new Message(this, CameraControlListener::kInResumeContinuousFocus), NS_DISPATCH_NORMAL);
   632 }
   634 nsresult
   635 CameraControlImpl::Stop()
   636 {
   637   class Message : public ControlMessage
   638   {
   639   public:
   640     Message(CameraControlImpl* aCameraControl,
   641             CameraControlListener::CameraErrorContext aContext)
   642       : ControlMessage(aCameraControl, aContext)
   643     { }
   645     nsresult
   646     RunImpl() MOZ_OVERRIDE
   647     {
   648       return mCameraControl->StopImpl();
   649     }
   650   };
   652   return mCameraThread->Dispatch(
   653     new Message(this, CameraControlListener::kInStopCamera), NS_DISPATCH_NORMAL);
   654 }
   656 class CameraControlImpl::ListenerMessage : public CameraControlImpl::ControlMessage
   657 {
   658 public:
   659   ListenerMessage(CameraControlImpl* aCameraControl,
   660                   CameraControlListener* aListener)
   661     : ControlMessage(aCameraControl, CameraControlListener::kInUnspecified)
   662     , mListener(aListener)
   663   { }
   665 protected:
   666   nsRefPtr<CameraControlListener> mListener;
   667 };
   669 void
   670 CameraControlImpl::AddListenerImpl(already_AddRefed<CameraControlListener> aListener)
   671 {
   672   RwLockAutoEnterWrite lock(mListenerLock);
   674   CameraControlListener* l = *mListeners.AppendElement() = aListener;
   675   DOM_CAMERA_LOGI("Added camera control listener %p\n", l);
   677   // Update the newly-added listener's state
   678   l->OnConfigurationChange(mCurrentConfiguration);
   679   l->OnHardwareStateChange(mHardwareState);
   680   l->OnPreviewStateChange(mPreviewState);
   681 }
   683 void
   684 CameraControlImpl::AddListener(CameraControlListener* aListener)
   685  {
   686   class Message : public ListenerMessage
   687   {
   688   public:
   689     Message(CameraControlImpl* aCameraControl,
   690             CameraControlListener* aListener)
   691       : ListenerMessage(aCameraControl, aListener)
   692     { }
   694     nsresult
   695     RunImpl() MOZ_OVERRIDE
   696     {
   697       mCameraControl->AddListenerImpl(mListener.forget());
   698       return NS_OK;
   699     }
   700   };
   702   mCameraThread->Dispatch(new Message(this, aListener), NS_DISPATCH_NORMAL);
   703 }
   705 void
   706 CameraControlImpl::RemoveListenerImpl(CameraControlListener* aListener)
   707 {
   708   RwLockAutoEnterWrite lock(mListenerLock);
   710   nsRefPtr<CameraControlListener> l(aListener);
   711   mListeners.RemoveElement(l);
   712   DOM_CAMERA_LOGI("Removed camera control listener %p\n", l.get());
   713   // XXXmikeh - do we want to notify the listener that it has been removed?
   714 }
   716 void
   717 CameraControlImpl::RemoveListener(CameraControlListener* aListener)
   718  {
   719   class Message : public ListenerMessage
   720   {
   721   public:
   722     Message(CameraControlImpl* aCameraControl, CameraControlListener* aListener)
   723       : ListenerMessage(aCameraControl, aListener)
   724     { }
   726     nsresult
   727     RunImpl() MOZ_OVERRIDE
   728     {
   729       mCameraControl->RemoveListenerImpl(mListener);
   730       return NS_OK;
   731     }
   732   };
   734   mCameraThread->Dispatch(new Message(this, aListener), NS_DISPATCH_NORMAL);
   735 }

mercurial