Bug 1139721 - Fix camera memory leaks for onfacedetected events, failed initializations and capabilities. r=mikeh
authorAndrew Osmond <aosmond@mozilla.com>
Fri, 17 Apr 2015 07:09:54 -0400
changeset 239599 7a458d7e3e4f9e8a91b6c48445c12acd4abebaf4
parent 239598 86970b32c0c826016419cf0bd44222ef98f43daf
child 239600 ade4423fb17de9a31ed359d79079ffd02cbb0b7e
push id12444
push userryanvm@gmail.com
push dateFri, 17 Apr 2015 20:04:42 +0000
treeherderfx-team@560a202db924 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikeh
bugs1139721
milestone40.0a1
Bug 1139721 - Fix camera memory leaks for onfacedetected events, failed initializations and capabilities. r=mikeh
dom/camera/DOMCameraCapabilities.cpp
dom/camera/DOMCameraControl.cpp
--- a/dom/camera/DOMCameraCapabilities.cpp
+++ b/dom/camera/DOMCameraCapabilities.cpp
@@ -318,16 +318,17 @@ CameraCapabilities::HasSupport(JSContext
 }
 
 CameraCapabilities::CameraCapabilities(nsPIDOMWindow* aWindow,
                                        ICameraControl* aCameraControl)
   : mWindow(aWindow)
   , mCameraControl(aCameraControl)
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  MOZ_COUNT_CTOR(CameraCapabilities);
   if (mCameraControl) {
     mListener = new CameraClosedListenerProxy<CameraCapabilities>(this);
     mCameraControl->AddListener(mListener);
   }
 }
 
 CameraCapabilities::~CameraCapabilities()
 {
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -301,17 +301,17 @@ nsDOMCameraControl::nsDOMCameraControl(u
   if (NS_FAILED(rv)) {
     mListener->OnUserError(DOMCameraControlListener::kInStartCamera, rv);
   }
 }
 
 nsDOMCameraControl::~nsDOMCameraControl()
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
-  /*invoke DOMMdediastream destroy*/
+  /*invoke DOMMediaStream destroy*/
   Destroy();
 }
 
 JSObject*
 nsDOMCameraControl::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return CameraControlBinding::Wrap(aCx, this, aGivenProto);
 }
@@ -1368,20 +1368,19 @@ nsDOMCameraControl::OnFacesDetected(cons
 {
   DOM_CAMERA_LOGI("DOM OnFacesDetected %zu face(s)\n", aFaces.Length());
   MOZ_ASSERT(NS_IsMainThread());
 
   Sequence<OwningNonNull<DOMCameraDetectedFace> > faces;
   uint32_t len = aFaces.Length();
 
   if (faces.SetCapacity(len)) {
-    nsRefPtr<DOMCameraDetectedFace> f;
     for (uint32_t i = 0; i < len; ++i) {
-      f = new DOMCameraDetectedFace(static_cast<DOMMediaStream*>(this), aFaces[i]);
-      *faces.AppendElement() = f.forget().take();
+      *faces.AppendElement() =
+        new DOMCameraDetectedFace(static_cast<DOMMediaStream*>(this), aFaces[i]);
     }
   }
 
   CameraFacesDetectedEventInit eventInit;
   eventInit.mFaces.SetValue(faces);
 
   nsRefPtr<CameraFacesDetectedEvent> event =
     CameraFacesDetectedEvent::Constructor(this,
@@ -1422,16 +1421,20 @@ nsDOMCameraControl::OnUserError(CameraCo
     this, aContext, aError);
   MOZ_ASSERT(NS_IsMainThread());
 
   nsRefPtr<Promise> promise;
 
   switch (aContext) {
     case CameraControlListener::kInStartCamera:
       promise = mGetCameraPromise.forget();
+      // If we failed to open the camera, we never actually provided a reference
+      // for the application to release explicitly. Thus we must clear our handle
+      // here to ensure everything is freed.
+      mCameraControl = nullptr;
       break;
 
     case CameraControlListener::kInStopCamera:
       promise = mReleasePromise.forget();
       if (aError == NS_ERROR_NOT_INITIALIZED) {
         // This value indicates that the hardware is already closed; which for
         // kInStopCamera, is not actually an error.
         if (promise) {