Backed out changeset a73dece39b01 (bug 985496) for mochitest-5 orange
authorWes Kocher <wkocher@mozilla.com>
Fri, 25 Apr 2014 16:15:37 -0700
changeset 180845 5d6a3571f1abd8dd38973ee29c2a894acfd8a196
parent 180844 33a615530ab17a6068f45a7ead9ec1f25ef01774
child 180846 d0892b46689463b1f5fd76e4f502b8317895fd73
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
bugs985496
milestone31.0a1
backs outa73dece39b0129e53040f29eed4f377ddf387dee
Backed out changeset a73dece39b01 (bug 985496) for mochitest-5 orange
content/media/webrtc/MediaEngineWebRTC.h
content/media/webrtc/MediaEngineWebRTCVideo.cpp
dom/camera/CameraControlImpl.cpp
dom/camera/CameraControlImpl.h
dom/camera/CameraControlListener.h
dom/camera/CameraRecorderProfiles.h
dom/camera/DOMCameraCapabilities.cpp
dom/camera/DOMCameraCapabilities.h
dom/camera/DOMCameraControl.cpp
dom/camera/DOMCameraControl.h
dom/camera/DOMCameraControlListener.cpp
dom/camera/DOMCameraControlListener.h
dom/camera/FallbackCameraControl.cpp
dom/camera/GonkCameraControl.cpp
dom/camera/GonkCameraControl.h
dom/camera/GonkCameraHwMgr.cpp
dom/camera/GonkCameraHwMgr.h
dom/camera/GonkCameraManager.cpp
dom/camera/GonkCameraParameters.cpp
dom/camera/GonkCameraParameters.h
dom/camera/GonkRecorderProfiles.cpp
dom/camera/GonkRecorderProfiles.h
dom/camera/ICameraControl.h
dom/camera/TestGonkCameraControl.cpp
dom/camera/TestGonkCameraControl.h
dom/camera/TestGonkCameraHardware.cpp
dom/camera/moz.build
dom/camera/test/test_bug975472.html
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -165,17 +165,17 @@ public:
   NS_DECL_THREADSAFE_ISUPPORTS
 #else
   // We are subclassed from CameraControlListener, which implements a
   // threadsafe reference-count for us.
   NS_DECL_ISUPPORTS_INHERITED
 
   void OnHardwareStateChange(HardwareState aState);
   bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
-  void OnUserError(UserContext aContext, nsresult aError);
+  void OnError(CameraErrorContext aContext, CameraError aError);
   void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType);
 
   void AllocImpl();
   void DeallocImpl();
   void StartImpl(webrtc::CaptureCapability aCapability);
   void StopImpl();
   void SnapshotImpl();
   void RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -630,17 +630,17 @@ MediaEngineWebRTCVideoSource::OnHardware
     LOG(("*** Initial orientation: %d (Camera %d Back %d MountAngle: %d)",
          mRotation, mCaptureIndex, mBackCamera, mCameraAngle));
     mState = kStarted;
     mCallbackMonitor.Notify();
   }
 }
 
 void
-MediaEngineWebRTCVideoSource::OnUserError(UserContext aContext, nsresult aError)
+MediaEngineWebRTCVideoSource::OnError(CameraErrorContext aContext, CameraError aError)
 {
   ReentrantMonitorAutoEnter sync(mCallbackMonitor);
   mCallbackMonitor.Notify();
 }
 
 void
 MediaEngineWebRTCVideoSource::OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
 {
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -1,69 +1,64 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CameraControlImpl.h"
 #include "base/basictypes.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/unused.h"
-#include "nsPrintfCString.h"
 #include "nsIWeakReferenceUtils.h"
 #include "CameraRecorderProfiles.h"
 #include "CameraCommon.h"
 #include "nsGlobalWindow.h"
 #include "DeviceStorageFileDescriptor.h"
 #include "CameraControlListener.h"
 
 using namespace mozilla;
 
 nsWeakPtr CameraControlImpl::sCameraThread;
 
 CameraControlImpl::CameraControlImpl(uint32_t aCameraId)
-  : mListenerLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "CameraControlImpl.Listeners.Lock"))
-  , mCameraId(aCameraId)
+  : mCameraId(aCameraId)
   , mPreviewState(CameraControlListener::kPreviewStopped)
   , mHardwareState(CameraControlListener::kHardwareClosed)
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
 
   // reuse the same camera thread to conserve resources
   nsCOMPtr<nsIThread> ct = do_QueryReferent(sCameraThread);
   if (ct) {
     mCameraThread = ct.forget();
   } else {
     nsresult rv = NS_NewNamedThread("CameraThread", getter_AddRefs(mCameraThread));
-    if (NS_FAILED(rv)) {
-      MOZ_CRASH("Failed to create new Camera Thread");
-    }
+    unused << rv; // swallow rv to suppress a compiler warning when the macro
+                  // is #defined to nothing (i.e. in non-DEBUG builds).
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
 
     // keep a weak reference to the new thread
     sCameraThread = do_GetWeakReference(mCameraThread);
   }
 
   // Care must be taken with the mListenerLock read-write lock to prevent
   // deadlocks. Currently this is handled by ensuring that any attempts to
   // acquire the lock for writing (as in Add/RemoveListener()) happen in a
   // runnable dispatched to the Camera Thread--even if the method is being
   // called from that thread. This ensures that if a registered listener
   // (which is invoked with a read-lock) tries to call Add/RemoveListener(),
   // the lock-for-writing attempt won't happen until the listener has
   // completed.
   //
   // Multiple parallel listeners being invoked are not a problem because
   // the read-write lock allows multiple simultaneous read-locks.
-  if (!mListenerLock) {
-    MOZ_CRASH("Out of memory getting new PRRWLock");
-  }
+  mListenerLock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "CameraControlImpl.Listeners.Lock");
 }
 
 CameraControlImpl::~CameraControlImpl()
 {
-  MOZ_ASSERT(mListenerLock, "mListenerLock missing in ~CameraControlImpl()");
   if (mListenerLock) {
     PR_DestroyRWLock(mListenerLock);
     mListenerLock = nullptr;
   }
 }
 
 already_AddRefed<RecorderProfileManager>
 CameraControlImpl::GetRecorderProfileManager()
@@ -263,141 +258,114 @@ CameraControlImpl::OnNewPreviewFrame(lay
   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
     CameraControlListener* l = mListeners[i];
     consumed = l->OnNewPreviewFrame(aImage, aWidth, aHeight) || consumed;
   }
   return consumed;
 }
 
 void
-CameraControlImpl::OnUserError(CameraControlListener::UserContext aContext,
-                               nsresult aError)
+CameraControlImpl::OnError(CameraControlListener::CameraErrorContext aContext,
+                           CameraControlListener::CameraError aError)
 {
   // This callback can run on threads other than the Main Thread and
   //  the Camera Thread.
   RwLockAutoEnterRead lock(mListenerLock);
 
 #ifdef PR_LOGGING
+  const char* error[] = {
+    "api-failed",
+    "init-failed",
+    "invalid-configuration",
+    "service-failed",
+    "set-picture-size-failed",
+    "set-thumbnail-size-failed",
+    "unknown"
+  };
   const char* context[] = {
     "StartCamera",
     "StopCamera",
     "AutoFocus",
     "StartFaceDetection",
     "StopFaceDetection",
     "TakePicture",
     "StartRecording",
     "StopRecording",
     "SetConfiguration",
     "StartPreview",
     "StopPreview",
-    "SetPictureSize",
-    "SetThumbnailSize",
     "ResumeContinuousFocus",
     "Unspecified"
   };
-  if (static_cast<size_t>(aContext) < sizeof(context) / sizeof(context[0])) {
-    DOM_CAMERA_LOGW("CameraControlImpl::OnUserError : aContext='%s' (%d), aError=0x%x\n",
-      context[aContext], aContext, aError);
+  if (static_cast<unsigned int>(aError) < sizeof(error) / sizeof(error[0]) &&
+    static_cast<unsigned int>(aContext) < sizeof(context) / sizeof(context[0])) {
+    DOM_CAMERA_LOGW("CameraControlImpl::OnError : aContext='%s' (%u), aError='%s' (%u)\n",
+      context[aContext], aContext, error[aError], aError);
   } else {
-    DOM_CAMERA_LOGE("CameraControlImpl::OnUserError : aContext=%d, aError=0x%x\n",
+    DOM_CAMERA_LOGE("CameraControlImpl::OnError : aContext=%u, aError=%d\n",
       aContext, aError);
   }
 #endif
 
   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
     CameraControlListener* l = mListeners[i];
-    l->OnUserError(aContext, aError);
-  }
-}
-
-void
-CameraControlImpl::OnSystemError(CameraControlListener::SystemContext aContext,
-                                 nsresult aError)
-{
-  // This callback can run on threads other than the Main Thread and
-  //  the Camera Thread.
-  RwLockAutoEnterRead lock(mListenerLock);
-
-#ifdef PR_LOGGING
-  const char* context[] = {
-    "Camera Service"
-  };
-  if (static_cast<size_t>(aContext) < sizeof(context) / sizeof(context[0])) {
-    DOM_CAMERA_LOGW("CameraControlImpl::OnSystemError : aContext='%s' (%d), aError=0x%x\n",
-      context[aContext], aContext, aError);
-  } else {
-    DOM_CAMERA_LOGE("CameraControlImpl::OnSystemError : aContext=%d, aError=0x%x\n",
-      aContext, aError);
-  }
-#endif
-
-  for (uint32_t i = 0; i < mListeners.Length(); ++i) {
-    CameraControlListener* l = mListeners[i];
-    l->OnSystemError(aContext, aError);
+    l->OnError(aContext, aError);
   }
 }
 
 // Camera control asynchronous message; these are dispatched from
 //  the Main Thread to the Camera Thread, where they are consumed.
 
 class CameraControlImpl::ControlMessage : public nsRunnable
 {
 public:
   ControlMessage(CameraControlImpl* aCameraControl,
-                 CameraControlListener::UserContext aContext)
+                 CameraControlListener::CameraErrorContext aContext)
     : mCameraControl(aCameraControl)
     , mContext(aContext)
-  { }
+  {
+    MOZ_COUNT_CTOR(CameraControlImpl::ControlMessage);
+  }
+
+  virtual ~ControlMessage()
+  {
+    MOZ_COUNT_DTOR(CameraControlImpl::ControlMessage);
+  }
 
   virtual nsresult RunImpl() = 0;
 
   NS_IMETHOD
   Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(mCameraControl);
     MOZ_ASSERT(NS_GetCurrentThread() == mCameraControl->mCameraThread);
 
     nsresult rv = RunImpl();
     if (NS_FAILED(rv)) {
-      nsPrintfCString msg("Camera control API(%d) failed with 0x%x", mContext, rv);
-      NS_WARNING(msg.get());
-      mCameraControl->OnUserError(mContext, rv);
+      DOM_CAMERA_LOGW("Camera control API failed at %d with 0x%x\n", mContext, rv);
+      // XXXmikeh - do we want to report a more specific error code?
+      mCameraControl->OnError(mContext, CameraControlListener::kErrorApiFailed);
     }
 
     return NS_OK;
   }
 
 protected:
-  virtual ~ControlMessage() { }
-
   nsRefPtr<CameraControlImpl> mCameraControl;
-  CameraControlListener::UserContext mContext;
+  CameraControlListener::CameraErrorContext mContext;
 };
 
 nsresult
-CameraControlImpl::Dispatch(ControlMessage* aMessage)
-{
-  nsresult rv = mCameraThread->Dispatch(aMessage, NS_DISPATCH_NORMAL);
-  if (NS_SUCCEEDED(rv)) {
-    return NS_OK;
-  }
-
-  nsPrintfCString msg("Failed to dispatch camera control message (0x%x)", rv);
-  NS_WARNING(msg.get());
-  return NS_ERROR_FAILURE;
-}
-
-nsresult
 CameraControlImpl::Start(const Configuration* aConfig)
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext,
+            CameraControlListener::CameraErrorContext aContext,
             const Configuration* aConfig)
       : ControlMessage(aCameraControl, aContext)
       , mHaveInitialConfig(false)
     {
       if (aConfig) {
         mConfig = *aConfig;
         mHaveInitialConfig = true;
       }
@@ -412,138 +380,144 @@ CameraControlImpl::Start(const Configura
       return mCameraControl->StartImpl();
     }
 
   protected:
     bool mHaveInitialConfig;
     Configuration mConfig;
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInStartCamera, aConfig));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInStartCamera, aConfig), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::SetConfiguration(const Configuration& aConfig)
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext,
+            CameraControlListener::CameraErrorContext aContext,
             const Configuration& aConfig)
       : ControlMessage(aCameraControl, aContext)
       , mConfig(aConfig)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->SetConfigurationImpl(mConfig);
     }
 
   protected:
     Configuration mConfig;
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInSetConfiguration, aConfig));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInSetConfiguration, aConfig), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::AutoFocus()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->AutoFocusImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInAutoFocus));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInAutoFocus), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::StartFaceDetection()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->StartFaceDetectionImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInStartFaceDetection));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInStartFaceDetection), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::StopFaceDetection()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->StopFaceDetectionImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInStopFaceDetection));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInStopFaceDetection), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::TakePicture()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->TakePictureImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInTakePicture));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInTakePicture), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::StartRecording(DeviceStorageFileDescriptor* aFileDescriptor,
                                   const StartRecordingOptions* aOptions)
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext,
+            CameraControlListener::CameraErrorContext aContext,
             const StartRecordingOptions* aOptions,
             DeviceStorageFileDescriptor* aFileDescriptor)
       : ControlMessage(aCameraControl, aContext)
       , mOptionsPassed(false)
       , mFileDescriptor(aFileDescriptor)
     {
       if (aOptions) {
         mOptions = *aOptions;
@@ -559,126 +533,129 @@ CameraControlImpl::StartRecording(Device
     }
 
   protected:
     StartRecordingOptions mOptions;
     bool mOptionsPassed;
     nsRefPtr<DeviceStorageFileDescriptor> mFileDescriptor;
   };
 
-  if (!aFileDescriptor) {
-    return NS_ERROR_INVALID_ARG;
-  }
-  return Dispatch(new Message(this, CameraControlListener::kInStartRecording,
-    aOptions, aFileDescriptor));
+
+  return mCameraThread->Dispatch(new Message(this, CameraControlListener::kInStartRecording,
+    aOptions, aFileDescriptor), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::StopRecording()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->StopRecordingImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInStopRecording));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInStopRecording), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::StartPreview()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->StartPreviewImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInStartPreview));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInStartPreview), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::StopPreview()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->StopPreviewImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInStopPreview));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInStopPreview), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::ResumeContinuousFocus()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->ResumeContinuousFocusImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInResumeContinuousFocus));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInResumeContinuousFocus), NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::Stop()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
-            CameraControlListener::UserContext aContext)
+            CameraControlListener::CameraErrorContext aContext)
       : ControlMessage(aCameraControl, aContext)
     { }
 
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       return mCameraControl->StopImpl();
     }
   };
 
-  return Dispatch(new Message(this, CameraControlListener::kInStopCamera));
+  return mCameraThread->Dispatch(
+    new Message(this, CameraControlListener::kInStopCamera), NS_DISPATCH_NORMAL);
 }
 
 class CameraControlImpl::ListenerMessage : public CameraControlImpl::ControlMessage
 {
 public:
   ListenerMessage(CameraControlImpl* aCameraControl,
                   CameraControlListener* aListener)
     : ControlMessage(aCameraControl, CameraControlListener::kInUnspecified)
@@ -717,19 +694,17 @@ CameraControlImpl::AddListener(CameraCon
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       mCameraControl->AddListenerImpl(mListener.forget());
       return NS_OK;
     }
   };
 
-  if (aListener) {
-    Dispatch(new Message(this, aListener));
-  }
+  mCameraThread->Dispatch(new Message(this, aListener), NS_DISPATCH_NORMAL);
 }
 
 void
 CameraControlImpl::RemoveListenerImpl(CameraControlListener* aListener)
 {
   RwLockAutoEnterWrite lock(mListenerLock);
 
   nsRefPtr<CameraControlListener> l(aListener);
@@ -751,12 +726,10 @@ CameraControlImpl::RemoveListener(Camera
     nsresult
     RunImpl() MOZ_OVERRIDE
     {
       mCameraControl->RemoveListenerImpl(mListener);
       return NS_OK;
     }
   };
 
-  if (aListener) {
-    Dispatch(new Message(this, aListener));
-  }
+  mCameraThread->Dispatch(new Message(this, aListener), NS_DISPATCH_NORMAL);
 }
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -29,19 +29,19 @@ class RecorderProfileManager;
 
 class CameraControlImpl : public ICameraControl
 {
 public:
   CameraControlImpl(uint32_t aCameraId);
   virtual void AddListener(CameraControlListener* aListener) MOZ_OVERRIDE;
   virtual void RemoveListener(CameraControlListener* aListener) MOZ_OVERRIDE;
 
-  // See ICameraControl.h for these methods' return values.
   virtual nsresult Start(const Configuration* aConfig = nullptr) MOZ_OVERRIDE;
   virtual nsresult Stop() MOZ_OVERRIDE;
+
   virtual nsresult SetConfiguration(const Configuration& aConfig) MOZ_OVERRIDE;
   virtual nsresult StartPreview() MOZ_OVERRIDE;
   virtual nsresult StopPreview() MOZ_OVERRIDE;
   virtual nsresult AutoFocus() MOZ_OVERRIDE;
   virtual nsresult StartFaceDetection() MOZ_OVERRIDE;
   virtual nsresult StopFaceDetection() MOZ_OVERRIDE;
   virtual nsresult TakePicture() MOZ_OVERRIDE;
   virtual nsresult StartRecording(DeviceStorageFileDescriptor* aFileDescriptor,
@@ -52,18 +52,18 @@ public:
   already_AddRefed<RecorderProfileManager> GetRecorderProfileManager();
   uint32_t GetCameraId() { return mCameraId; }
 
   virtual void Shutdown() MOZ_OVERRIDE;
 
   // Event handlers called directly from outside this class.
   void OnShutter();
   void OnClosed();
-  void OnUserError(CameraControlListener::UserContext aContext, nsresult aError);
-  void OnSystemError(CameraControlListener::SystemContext aContext, nsresult aError);
+  void OnError(CameraControlListener::CameraErrorContext aContext,
+               CameraControlListener::CameraError aError);
   void OnAutoFocusMoving(bool aIsMoving);
 
 protected:
   // Event handlers.
   void OnAutoFocusComplete(bool aAutoFocusSucceeded);
   void OnFacesDetected(const nsTArray<Face>& aFaces);
   void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType);
 
@@ -91,47 +91,31 @@ protected:
   void AddListenerImpl(already_AddRefed<CameraControlListener> aListener);
   void RemoveListenerImpl(CameraControlListener* aListener);
   nsTArray<nsRefPtr<CameraControlListener> > mListeners;
   PRRWLock* mListenerLock;
 
   class ControlMessage;
   class ListenerMessage;
 
-  nsresult Dispatch(ControlMessage* aMessage);
-
-  // Asynchronous method implementations, invoked on the Camera Thread.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if one or more arguments is invalid;
-  //  - NS_ERROR_NOT_INITIALIZED if the underlying hardware is not initialized,
-  //      failed to initialize (in the case of StartImpl()), or has been stopped;
-  //      for StartRecordingImpl(), this indicates that no recorder has been
-  //      configured (either by calling StartImpl() or SetConfigurationImpl());
-  //  - NS_ERROR_ALREADY_INITIALIZED if the underlying hardware is already
-  //      initialized;
-  //  - NS_ERROR_NOT_IMPLEMENTED if the method is not implemented;
-  //  - NS_ERROR_FAILURE on general failures.
   virtual nsresult StartImpl(const Configuration* aConfig = nullptr) = 0;
   virtual nsresult StopImpl() = 0;
   virtual nsresult SetConfigurationImpl(const Configuration& aConfig) = 0;
   virtual nsresult StartPreviewImpl() = 0;
   virtual nsresult StopPreviewImpl() = 0;
   virtual nsresult AutoFocusImpl() = 0;
   virtual nsresult StartFaceDetectionImpl() = 0;
   virtual nsresult StopFaceDetectionImpl() = 0;
   virtual nsresult TakePictureImpl() = 0;
   virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
                                       const StartRecordingOptions* aOptions) = 0;
   virtual nsresult StopRecordingImpl() = 0;
   virtual nsresult ResumeContinuousFocusImpl() = 0;
   virtual nsresult PushParametersImpl() = 0;
   virtual nsresult PullParametersImpl() = 0;
-
   virtual already_AddRefed<RecorderProfileManager> GetRecorderProfileManagerImpl() = 0;
 
   void OnShutterInternal();
   void OnClosedInternal();
 
   uint32_t mCameraId;
 
   CameraControlListener::CameraListenerConfiguration mCurrentConfiguration;
--- a/dom/camera/CameraControlListener.h
+++ b/dom/camera/CameraControlListener.h
@@ -77,41 +77,40 @@ public:
   };
   virtual void OnConfigurationChange(const CameraListenerConfiguration& aConfiguration) { }
 
   virtual void OnAutoFocusComplete(bool aAutoFocusSucceeded) { }
   virtual void OnAutoFocusMoving(bool aIsMoving) { }
   virtual void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType) { }
   virtual void OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces) { }
 
-  enum UserContext
+  enum CameraErrorContext
   {
     kInStartCamera,
     kInStopCamera,
     kInAutoFocus,
     kInStartFaceDetection,
     kInStopFaceDetection,
     kInTakePicture,
     kInStartRecording,
     kInStopRecording,
     kInSetConfiguration,
     kInStartPreview,
     kInStopPreview,
-    kInSetPictureSize,
-    kInSetThumbnailSize,
     kInResumeContinuousFocus,
     kInUnspecified
   };
-  // Error handler for problems arising due to user-initiated actions.
-  virtual void OnUserError(UserContext aContext, nsresult aError) { }
-
-  enum SystemContext
+  enum CameraError
   {
-    kSystemService
+    kErrorApiFailed,
+    kErrorInitFailed,
+    kErrorInvalidConfiguration,
+    kErrorServiceFailed,
+    kErrorSetPictureSizeFailed,
+    kErrorSetThumbnailSizeFailed,
+    kErrorUnknown
   };
-  // Error handler for problems arising due to system failures, not triggered
-  // by something the CameraControl API user did.
-  virtual void OnSystemError(SystemContext aContext, nsresult aError) { }
+  virtual void OnError(CameraErrorContext aContext, CameraError aError) { }
 };
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_CAMERACONTROLLISTENER_H
--- a/dom/camera/CameraRecorderProfiles.h
+++ b/dom/camera/CameraRecorderProfiles.h
@@ -39,24 +39,16 @@ public:
     switch (mCodec) {
       case H263:    return "h263";
       case H264:    return "h264";
       case MPEG4SP: return "mpeg4sp";
       default:      return nullptr;
     }
   }
 
-  // Get a representation of this video profile that can be returned
-  // to JS, possibly as a child member of another object.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aObject' is null;
-  //  - NS_ERROR_OUT_OF_MEMORY if a new object could not be allocated;
-  //  - NS_ERROR_FAILURE if construction of the JS object fails.
   nsresult GetJsObject(JSContext* aCx, JSObject** aObject);
 
 protected:
   uint32_t mCameraId;
   uint32_t mQualityIndex;
   Codec mCodec;
   int mBitrate;
   int mFramerate;
@@ -76,35 +68,28 @@ public:
 
   enum Codec {
     AMRNB,
     AMRWB,
     AAC,
     UNKNOWN
   };
 
+public:
   Codec GetCodec() const    { return mCodec; }
   const char* GetCodecName() const
   {
     switch (mCodec) {
       case AMRNB: return "amrnb";
       case AMRWB: return "amrwb";
       case AAC:   return "aac";
       default:    return nullptr;
     }
   }
 
-  // Get a representation of this audio profile that can be returned
-  // to JS, possibly as a child member of another object.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aObject' is null;
-  //  - NS_ERROR_OUT_OF_MEMORY if a new object could not be allocated;
-  //  - NS_ERROR_FAILURE if construction of the JS object fails.
   nsresult GetJsObject(JSContext* aCx, JSObject** aObject);
 
 protected:
   uint32_t mCameraId;
   uint32_t mQualityIndex;
   Codec mCodec;
   int mBitrate;
   int mSamplerate;
@@ -140,24 +125,16 @@ public:
   {
     switch (mFileFormat) {
       case THREE_GPP: return VIDEO_3GPP;
       case MPEG4:     return VIDEO_MP4;
       default:        return nullptr;
     }
   }
 
-  // Get a representation of this recorder profile that can be returned
-  // to JS, possibly as a child member of another object.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aObject' is null;
-  //  - NS_ERROR_OUT_OF_MEMORY if a new object could not be allocated;
-  //  - NS_ERROR_FAILURE if construction of the JS object fails.
   virtual nsresult GetJsObject(JSContext* aCx, JSObject** aObject) = 0;
 
 protected:
   virtual ~RecorderProfile();
 
   uint32_t mCameraId;
   uint32_t mQualityIndex;
   const char* mName;
@@ -179,34 +156,24 @@ public:
   virtual ~RecorderProfileBase()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   const RecorderVideoProfile* GetVideoProfile() const { return &mVideo; }
   const RecorderAudioProfile* GetAudioProfile() const { return &mAudio; }
 
-  // Get a representation of this recorder profile that can be returned
-  // to JS, possibly as a child member of another object.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aObject' is null;
-  //  - NS_ERROR_OUT_OF_MEMORY if a new object could not be allocated;
-  //  - NS_ERROR_NOT_AVAILABLE if the profile has no file format name;
-  //  - NS_ERROR_FAILURE if construction of the JS object fails.
-  nsresult
-  GetJsObject(JSContext* aCx, JSObject** aObject)
+  nsresult GetJsObject(JSContext* aCx, JSObject** aObject)
   {
     NS_ENSURE_TRUE(aObject, NS_ERROR_INVALID_ARG);
 
     const char* format = GetFileFormatName();
     if (!format) {
       // the profile must have a file format
-      return NS_ERROR_NOT_AVAILABLE;
+      return NS_ERROR_FAILURE;
     }
 
     JS::Rooted<JSObject*> o(aCx, JS_NewObject(aCx, nullptr, JS::NullPtr(), JS::NullPtr()));
     if (!o) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     JS::Rooted<JSString*> s(aCx, JS_NewStringCopyZ(aCx, format));
@@ -244,26 +211,16 @@ class RecorderProfileManager
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecorderProfileManager)
 
   virtual bool IsSupported(uint32_t aQualityIndex) const { return true; }
   virtual already_AddRefed<RecorderProfile> Get(uint32_t aQualityIndex) const = 0;
 
   uint32_t GetMaxQualityIndex() const { return mMaxQualityIndex; }
-
-  // Get a representation of all supported recorder profiles that can be
-  // returned to JS.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aObject' is null;
-  //  - NS_ERROR_OUT_OF_MEMORY if a new object could not be allocated;
-  //  - NS_ERROR_NOT_AVAILABLE if the profile has no file format name;
-  //  - NS_ERROR_FAILURE if construction of the JS object fails.
   nsresult GetJsObject(JSContext* aCx, JSObject** aObject) const;
 
 protected:
   RecorderProfileManager(uint32_t aCameraId);
   virtual ~RecorderProfileManager();
 
   uint32_t mCameraId;
   uint32_t mMaxQualityIndex;
--- a/dom/camera/DOMCameraCapabilities.cpp
+++ b/dom/camera/DOMCameraCapabilities.cpp
@@ -175,20 +175,21 @@ CameraCapabilities::Populate(ICameraCont
   if (!mRecorderProfileManager) {
     DOM_CAMERA_LOGW("Unable to get recorder profile manager\n");
   } else {
     AutoJSContext js;
 
     JS::Rooted<JSObject*> o(js);
     nsresult rv = mRecorderProfileManager->GetJsObject(js, o.address());
     if (NS_FAILED(rv)) {
-      DOM_CAMERA_LOGE("Failed to JS-objectify profile manager (0x%x)\n", rv);
-    } else {
-      mRecorderProfiles = JS::ObjectValue(*o);
+      DOM_CAMERA_LOGE("Failed to JS-objectify profile manager (%d)\n", rv);
+      return rv;
     }
+
+    mRecorderProfiles = JS::ObjectValue(*o);
   }
 
   // For now, always return success, since the presence or absence of capabilities
   // indicates whether or not they are supported.
   return NS_OK;
 }
 
 void
--- a/dom/camera/DOMCameraCapabilities.h
+++ b/dom/camera/DOMCameraCapabilities.h
@@ -36,23 +36,18 @@ public:
   // Because this header's filename doesn't match its C++ or DOM-facing
   // classname, we can't rely on the [Func="..."] WebIDL tag to implicitly
   // include the right header for us; instead we must explicitly include a
   // HasSupport() method in each header. We can get rid of these with the
   // Great Renaming proposed in bug 983177.
   static bool HasSupport(JSContext* aCx, JSObject* aGlobal);
 
   CameraCapabilities(nsPIDOMWindow* aWindow);
+  ~CameraCapabilities();
 
-  // Populate the camera capabilities interface from the specific
-  // camera control object.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aCameraControl' is null.
   nsresult Populate(ICameraControl* aCameraControl);
 
   nsPIDOMWindow* GetParentObject() const { return mWindow; }
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   void GetPreviewSizes(nsTArray<CameraSize>& aRetVal) const;
   void GetPictureSizes(nsTArray<CameraSize>& aRetVal) const;
@@ -70,18 +65,16 @@ public:
   uint32_t MaxDetectedFaces() const;
   double MinExposureCompensation() const;
   double MaxExposureCompensation() const;
   double ExposureCompensationStep() const;
   JS::Value RecorderProfiles(JSContext* cx) const;
   void GetIsoModes(nsTArray<nsString>& aRetVal) const;
 
 protected:
-  ~CameraCapabilities();
-
   nsresult TranslateToDictionary(ICameraControl* aCameraControl,
                                  uint32_t aKey, nsTArray<CameraSize>& aSizes);
 
   nsTArray<CameraSize> mPreviewSizes;
   nsTArray<CameraSize> mPictureSizes;
   nsTArray<CameraSize> mThumbnailSizes;
   nsTArray<CameraSize> mVideoSizes;
 
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -27,17 +27,16 @@
 #include "CameraCommon.h"
 #include "nsGlobalWindow.h"
 #include "CameraPreviewMediaStream.h"
 #include "mozilla/dom/CameraControlBinding.h"
 #include "mozilla/dom/CameraManagerBinding.h"
 #include "mozilla/dom/CameraCapabilitiesBinding.h"
 #include "DOMCameraDetectedFace.h"
 #include "mozilla/dom/BindingUtils.h"
-#include "nsPrintfCString.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMCameraControl)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMediaStream)
@@ -198,17 +197,18 @@ nsDOMCameraControl::nsDOMCameraControl(u
 
   // Register a listener for camera events.
   mListener = new DOMCameraControlListener(this, mInput);
   mCameraControl->AddListener(mListener);
 
   // Start the camera...
   nsresult rv = mCameraControl->Start(&config);
   if (NS_FAILED(rv)) {
-    mListener->OnUserError(DOMCameraControlListener::kInStartCamera, rv);
+    mListener->OnError(DOMCameraControlListener::kInStartCamera,
+                       DOMCameraControlListener::kErrorApiFailed);
   }
 }
 
 nsDOMCameraControl::~nsDOMCameraControl()
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
 }
 
@@ -733,17 +733,17 @@ nsDOMCameraControl::StartRecording(const
       mAudioChannelAgent->StartPlaying(&canPlay);
     }
   }
 #endif
 
   nsCOMPtr<nsIDOMDOMRequest> request;
   mDSFileDescriptor = new DeviceStorageFileDescriptor();
   aRv = aStorageArea.CreateFileDescriptor(aFilename, mDSFileDescriptor.get(),
-                                          getter_AddRefs(request));
+                                         getter_AddRefs(request));
   if (aRv.Failed()) {
     return;
   }
 
   mOptions = aOptions;
   mStartRecordingOnSuccessCb = &aOnSuccess;
   mStartRecordingOnErrorCb = nullptr;
   if (aOnError.WasPassed()) {
@@ -753,32 +753,29 @@ nsDOMCameraControl::StartRecording(const
   nsCOMPtr<nsIDOMEventListener> listener = new StartRecordingHelper(this);
   request->AddEventListener(NS_LITERAL_STRING("success"), listener, false);
   request->AddEventListener(NS_LITERAL_STRING("error"), listener, false);
 }
 
 void
 nsDOMCameraControl::OnCreatedFileDescriptor(bool aSucceeded)
 {
-  nsresult rv = NS_ERROR_FAILURE;
-
   if (aSucceeded && mDSFileDescriptor->mFileDescriptor.IsValid()) {
     ICameraControl::StartRecordingOptions o;
 
     o.rotation = mOptions.mRotation;
     o.maxFileSizeBytes = mOptions.mMaxFileSizeBytes;
     o.maxVideoLengthMs = mOptions.mMaxVideoLengthMs;
     o.autoEnableLowLightTorch = mOptions.mAutoEnableLowLightTorch;
-    rv = mCameraControl->StartRecording(mDSFileDescriptor.get(), &o);
+    nsresult rv = mCameraControl->StartRecording(mDSFileDescriptor.get(), &o);
     if (NS_SUCCEEDED(rv)) {
       return;
     }
   }
-
-  OnUserError(CameraControlListener::kInStartRecording, rv);
+  OnError(CameraControlListener::kInStartRecording, NS_LITERAL_STRING("FAILURE"));
 
   if (mDSFileDescriptor->mFileDescriptor.IsValid()) {
     // An error occured. We need to manually close the file associated with the
     // FileDescriptor, and we shouldn't do this on the main thread, so we
     // use a little helper.
     nsRefPtr<CloseFileRunnable> closer =
       new CloseFileRunnable(mDSFileDescriptor->mFileDescriptor);
     closer->Dispatch();
@@ -802,58 +799,32 @@ nsDOMCameraControl::StopRecording(ErrorR
 
 void
 nsDOMCameraControl::ResumePreview(ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
   aRv = mCameraControl->StartPreview();
 }
 
-class ImmediateErrorCallback : public nsRunnable
-{
-public:
-  ImmediateErrorCallback(CameraErrorCallback* aCallback, const nsAString& aMessage)
-    : mCallback(aCallback)
-    , mMessage(aMessage)
-  { }
-  
-  NS_IMETHODIMP
-  Run()
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    ErrorResult ignored;
-    mCallback->Call(mMessage, ignored);
-    return NS_OK;
-  }
-
-protected:
-  nsRefPtr<CameraErrorCallback> mCallback;
-  nsString mMessage;
-};
-
 void
 nsDOMCameraControl::SetConfiguration(const CameraConfiguration& aConfiguration,
                                      const Optional<OwningNonNull<CameraSetConfigurationCallback> >& aOnSuccess,
                                      const Optional<OwningNonNull<CameraErrorCallback> >& aOnError,
                                      ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
 
   nsRefPtr<CameraTakePictureCallback> cb = mTakePictureOnSuccessCb;
   if (cb) {
     // We're busy taking a picture, can't change modes right now.
     if (aOnError.WasPassed()) {
-      // There is already a call to TakePicture() in progress, abort this
-      // call and invoke the error callback (if one was passed in).
-      NS_DispatchToMainThread(new ImmediateErrorCallback(&aOnError.Value(),
-                              NS_LITERAL_STRING("TakePictureInProgress")));
-    } else {
-      // Only throw if no error callback was passed in.
-      aRv = NS_ERROR_FAILURE;
+      ErrorResult ignored;
+      aOnError.Value().Call(NS_LITERAL_STRING("Busy"), ignored);
     }
+    aRv = NS_ERROR_FAILURE;
     return;
   }
 
   ICameraControl::Configuration config;
   config.mRecorderProfile = aConfiguration.mRecorderProfile;
   config.mPreviewSize.width = aConfiguration.mPreviewSize.mWidth;
   config.mPreviewSize.height = aConfiguration.mPreviewSize.mHeight;
   config.mMode = ICameraControl::kPictureMode;
@@ -868,34 +839,55 @@ nsDOMCameraControl::SetConfiguration(con
   mSetConfigurationOnErrorCb = nullptr;
   if (aOnError.WasPassed()) {
     mSetConfigurationOnErrorCb = &aOnError.Value();
   }
 
   aRv = mCameraControl->SetConfiguration(config);
 }
 
+class ImmediateErrorCallback : public nsRunnable
+{
+public:
+  ImmediateErrorCallback(CameraErrorCallback* aCallback, const nsAString& aMessage)
+    : mCallback(aCallback)
+    , mMessage(aMessage)
+  { }
+  
+  NS_IMETHODIMP
+  Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    ErrorResult ignored;
+    mCallback->Call(mMessage, ignored);
+    return NS_OK;
+  }
+
+protected:
+  nsRefPtr<CameraErrorCallback> mCallback;
+  nsString mMessage;
+};
+
+
 void
 nsDOMCameraControl::AutoFocus(CameraAutoFocusCallback& aOnSuccess,
                               const Optional<OwningNonNull<CameraErrorCallback> >& aOnError,
                               ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
 
   nsRefPtr<CameraAutoFocusCallback> cb = mAutoFocusOnSuccessCb;
   if (cb) {
     if (aOnError.WasPassed()) {
       // There is already a call to AutoFocus() in progress, abort this new one
       // and invoke the error callback (if one was passed in).
       NS_DispatchToMainThread(new ImmediateErrorCallback(&aOnError.Value(),
                               NS_LITERAL_STRING("AutoFocusAlreadyInProgress")));
-    } else {
-      // Only throw if no error callback was passed in.
-      aRv = NS_ERROR_FAILURE;
     }
+    aRv = NS_ERROR_FAILURE;
     return;
   }
 
   mAutoFocusOnSuccessCb = &aOnSuccess;
   mAutoFocusOnErrorCb = nullptr;
   if (aOnError.WasPassed()) {
     mAutoFocusOnErrorCb = &aOnError.Value();
   }
@@ -927,20 +919,18 @@ nsDOMCameraControl::TakePicture(const Ca
 
   nsRefPtr<CameraTakePictureCallback> cb = mTakePictureOnSuccessCb;
   if (cb) {
     if (aOnError.WasPassed()) {
       // There is already a call to TakePicture() in progress, abort this new
       // one and invoke the error callback (if one was passed in).
       NS_DispatchToMainThread(new ImmediateErrorCallback(&aOnError.Value(),
                               NS_LITERAL_STRING("TakePictureAlreadyInProgress")));
-    } else {
-      // Only throw if no error callback was passed in.
-      aRv = NS_ERROR_FAILURE;
     }
+    aRv = NS_ERROR_FAILURE;
     return;
   }
 
   {
     ICameraControlParameterSetAutoEnter batch(mCameraControl);
 
     // XXXmikeh - remove this: see bug 931155
     ICameraControl::Size s;
@@ -1275,18 +1265,20 @@ nsDOMCameraControl::OnTakePictureComplet
     return;
   }
 
   ErrorResult ignored;
   cb->Call(aPicture, ignored);
 }
 
 void
-nsDOMCameraControl::OnUserError(CameraControlListener::UserContext aContext, nsresult aError)
+nsDOMCameraControl::OnError(CameraControlListener::CameraErrorContext aContext, const nsAString& aError)
 {
+  DOM_CAMERA_LOGI("DOM OnError context=%d, error='%s'\n", aContext,
+    NS_LossyConvertUTF16toASCII(aError).get());
   MOZ_ASSERT(NS_IsMainThread());
 
   nsRefPtr<CameraErrorCallback> errorCb;
 
   switch (aContext) {
     case CameraControlListener::kInStartCamera:
       mGetCameraOnSuccessCb = nullptr;
       errorCb = mGetCameraOnErrorCb.forget();
@@ -1324,84 +1316,41 @@ nsDOMCameraControl::OnUserError(CameraCo
       return;
 
     case CameraControlListener::kInStartPreview:
       // This method doesn't have any callbacks, so all we can do is log the
       // failure. This only happens after the hardware has been released.
       NS_WARNING("Failed to (re)start preview");
       return;
 
-    case CameraControlListener::kInStopPreview:
-      // This method doesn't have any callbacks, so all we can do is log the
-      // failure. This only happens after the hardware has been released.
-      NS_WARNING("Failed to stop preview");
-      return;
-
-    case CameraControlListener::kInSetPictureSize:
-      // This method doesn't have any callbacks, so all we can do is log the
-      // failure. This only happens after the hardware has been released.
-      NS_WARNING("Failed to set picture size");
-      return;
-
-    case CameraControlListener::kInSetThumbnailSize:
-      // This method doesn't have any callbacks, so all we can do is log the
-      // failure. This only happens after the hardware has been released.
-      NS_WARNING("Failed to set thumbnail size");
-      return;
+    case CameraControlListener::kInUnspecified:
+      if (aError.EqualsASCII("ErrorServiceFailed")) {
+        // If the camera service fails, we will get preview-stopped and
+        // hardware-closed events, so nothing to do here.
+        NS_WARNING("Camera service failed");
+        return;
+      }
+      if (aError.EqualsASCII("ErrorSetPictureSizeFailed") ||
+          aError.EqualsASCII("ErrorSetThumbnailSizeFailed")) {
+        // We currently don't handle attribute setter failure. Practically,
+        // this only ever happens if a setter is called after the hardware
+        // has gone away before an asynchronous set gets to happen, so we
+        // swallow these.
+        NS_WARNING("Failed to set either picture or thumbnail size");
+        return;
+      }
+      // fallthrough
 
     default:
-      {
-        nsPrintfCString msg("Unhandled aContext=%u, aError=0x%x\n", aContext, aError);
-        NS_WARNING(msg.get());
-      }
-      MOZ_ASSUME_UNREACHABLE("Unhandled user error");
+      MOZ_ASSUME_UNREACHABLE("Error occurred in unanticipated camera state");
       return;
   }
 
   if (!errorCb) {
-    DOM_CAMERA_LOGW("DOM No error handler for aError=0x%x in aContext=%u\n",
-      aError, aContext);
+    DOM_CAMERA_LOGW("DOM No error handler for error '%s' in context=%d\n",
+      NS_LossyConvertUTF16toASCII(aError).get(), aContext);
     return;
   }
 
-  nsString error;
-  switch (aError) {
-    case NS_ERROR_INVALID_ARG:
-      error = NS_LITERAL_STRING("InvalidArgument");
-      break;
-
-    case NS_ERROR_NOT_AVAILABLE:
-      error = NS_LITERAL_STRING("NotAvailable");
-      break;
-
-    case NS_ERROR_NOT_IMPLEMENTED:
-      error = NS_LITERAL_STRING("NotImplemented");
-      break;
-
-    case NS_ERROR_NOT_INITIALIZED:
-      error = NS_LITERAL_STRING("HardwareClosed");
-      break;
-
-    case NS_ERROR_ALREADY_INITIALIZED:
-      error = NS_LITERAL_STRING("HardwareAlreadyOpen");
-      break;
+  ErrorResult ignored;
+  errorCb->Call(aError, ignored);
+}
 
-    case NS_ERROR_OUT_OF_MEMORY:
-      error = NS_LITERAL_STRING("OutOfMemory");
-      break;
-
-    default:
-      {
-        nsPrintfCString msg("Reporting aError=0x%x as generic\n", aError);
-        NS_WARNING(msg.get());
-      }
-      // fallthrough
-
-    case NS_ERROR_FAILURE:
-      error = NS_LITERAL_STRING("GeneralFailure");
-      break;
-  }
-
-  DOM_CAMERA_LOGI("DOM OnUserError aContext=%u, error='%s'\n", aContext,
-    NS_ConvertUTF16toUTF8(error).get());
-  ErrorResult ignored;
-  errorCb->Call(error, ignored);
-}
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -162,17 +162,17 @@ protected:
   void OnTakePictureComplete(nsIDOMBlob* aPicture);
   void OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces);
 
   void OnHardwareStateChange(DOMCameraControlListener::HardwareState aState);
   void OnPreviewStateChange(DOMCameraControlListener::PreviewState aState);
   void OnRecorderStateChange(CameraControlListener::RecorderState aState, int32_t aStatus, int32_t aTrackNum);
   void OnConfigurationChange(DOMCameraConfiguration* aConfiguration);
   void OnShutter();
-  void OnUserError(CameraControlListener::UserContext aContext, nsresult aError);
+  void OnError(CameraControlListener::CameraErrorContext aContext, const nsAString& mError);
 
   bool IsWindowStillActive();
 
   nsresult NotifyRecordingStatusChange(const nsString& aMsg);
 
   nsRefPtr<ICameraControl> mCameraControl; // non-DOM camera control
 
   // An agent used to join audio channel service.
--- a/dom/camera/DOMCameraControlListener.cpp
+++ b/dom/camera/DOMCameraControlListener.cpp
@@ -349,34 +349,58 @@ DOMCameraControlListener::OnTakePictureC
     uint32_t mLength;
     nsString mMimeType;
   };
 
   NS_DispatchToMainThread(new Callback(mDOMCameraControl, aData, aLength, aMimeType));
 }
 
 void
-DOMCameraControlListener::OnUserError(UserContext aContext, nsresult aError)
+DOMCameraControlListener::OnError(CameraErrorContext aContext, CameraError aError)
 {
   class Callback : public DOMCallback
   {
   public:
     Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
-             UserContext aContext,
-             nsresult aError)
+             CameraErrorContext aContext,
+             CameraError aError)
       : DOMCallback(aDOMCameraControl)
       , mContext(aContext)
       , mError(aError)
     { }
 
     virtual void
     RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
     {
-      aDOMCameraControl->OnUserError(mContext, mError);
+      nsString error;
+
+      switch (mError) {
+        case kErrorServiceFailed:
+          error = NS_LITERAL_STRING("ErrorServiceFailed");
+          break;
+
+        case kErrorSetPictureSizeFailed:
+          error = NS_LITERAL_STRING("ErrorSetPictureSizeFailed");
+          break;
+
+        case kErrorSetThumbnailSizeFailed:
+          error = NS_LITERAL_STRING("ErrorSetThumbnailSizeFailed");
+          break;
+
+        case kErrorApiFailed:
+          // XXXmikeh legacy error placeholder
+          error = NS_LITERAL_STRING("FAILURE");
+          break;
+
+        default:
+          error = NS_LITERAL_STRING("ErrorUnknown");
+          break;
+      }
+      aDOMCameraControl->OnError(mContext, error);
     }
 
   protected:
-    UserContext mContext;
-    nsresult mError;
+    CameraErrorContext mContext;
+    CameraError mError;
   };
 
   NS_DispatchToMainThread(new Callback(mDOMCameraControl, aContext, aError));
 }
--- a/dom/camera/DOMCameraControlListener.h
+++ b/dom/camera/DOMCameraControlListener.h
@@ -24,17 +24,17 @@ public:
   virtual void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType) MOZ_OVERRIDE;
 
   virtual void OnHardwareStateChange(HardwareState aState) MOZ_OVERRIDE;
   virtual void OnPreviewStateChange(PreviewState aState) MOZ_OVERRIDE;
   virtual void OnRecorderStateChange(RecorderState aState, int32_t aStatus, int32_t aTrackNum) MOZ_OVERRIDE;
   virtual void OnConfigurationChange(const CameraListenerConfiguration& aConfiguration) MOZ_OVERRIDE;
   virtual void OnShutter() MOZ_OVERRIDE;
   virtual bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) MOZ_OVERRIDE;
-  virtual void OnUserError(UserContext aContext, nsresult aError) MOZ_OVERRIDE;
+  virtual void OnError(CameraErrorContext aContext, CameraError aError) MOZ_OVERRIDE;
 
 protected:
   virtual ~DOMCameraControlListener();
 
   nsMainThreadPtrHandle<nsDOMCameraControl> mDOMCameraControl;
   CameraPreviewMediaStream* mStream;
 
   class DOMCallback;
--- a/dom/camera/FallbackCameraControl.cpp
+++ b/dom/camera/FallbackCameraControl.cpp
@@ -19,51 +19,61 @@ namespace mozilla {
  * Fallback camera control subclass. Can be used as a template for the
  * definition of new camera support classes.
  */
 class FallbackCameraControl : public CameraControlImpl
 {
 public:
   FallbackCameraControl(uint32_t aCameraId) : CameraControlImpl(aCameraId) { }
 
-  virtual nsresult Set(uint32_t aKey, const nsAString& aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, nsAString& aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Set(uint32_t aKey, double aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, double& aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Set(uint32_t aKey, int32_t aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, int32_t& aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Set(uint32_t aKey, int64_t aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, int64_t& aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Set(uint32_t aKey, const Size& aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, Size& aValue) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Set(uint32_t aKey, const nsTArray<Region>& aRegions) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, nsTArray<Region>& aRegions) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
+  void OnAutoFocusComplete(bool aSuccess);
+  void OnAutoFocusMoving(bool aIsMoving) { }
+  void OnTakePictureComplete(uint8_t* aData, uint32_t aLength) { }
+  void OnTakePictureError() { }
+  void OnNewPreviewFrame(layers::GraphicBufferLocked* aBuffer) { }
+  void OnRecorderEvent(int msg, int ext1, int ext2) { }
+  void OnError(CameraControlListener::CameraErrorContext aWhere,
+               CameraControlListener::CameraError aError) { }
 
-  virtual nsresult SetLocation(const Position& aLocation) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
+  virtual nsresult Set(uint32_t aKey, const nsAString& aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, nsAString& aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Set(uint32_t aKey, double aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, double& aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Set(uint32_t aKey, int32_t aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, int32_t& aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Set(uint32_t aKey, int64_t aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, int64_t& aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Set(uint32_t aKey, const Size& aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, Size& aValue) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Set(uint32_t aKey, const nsTArray<Region>& aRegions) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, nsTArray<Region>& aRegions) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
 
-  virtual nsresult Get(uint32_t aKey, nsTArray<Size>& aSizes) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, nsTArray<nsString>& aValues) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual nsresult Get(uint32_t aKey, nsTArray<double>& aValues) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
+  virtual nsresult SetLocation(const Position& aLocation) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
 
-  nsresult PushParameters() { return NS_ERROR_NOT_INITIALIZED; }
-  nsresult PullParameters() { return NS_ERROR_NOT_INITIALIZED; }
+  virtual nsresult Get(uint32_t aKey, nsTArray<Size>& aSizes) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, nsTArray<nsString>& aValues) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult Get(uint32_t aKey, nsTArray<double>& aValues) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+
+  nsresult PushParameters() { return NS_ERROR_FAILURE; }
+  nsresult PullParameters() { return NS_ERROR_FAILURE; }
 
 protected:
   ~FallbackCameraControl();
 
-  virtual nsresult StartPreviewImpl() { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult StopPreviewImpl() { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult AutoFocusImpl() { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult StartFaceDetectionImpl() { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult StopFaceDetectionImpl() { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult TakePictureImpl() { return NS_ERROR_NOT_INITIALIZED; }
+  virtual nsresult StartPreviewImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult StopPreviewImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult AutoFocusImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult StartFaceDetectionImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult StopFaceDetectionImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult TakePictureImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
   virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
                                       const StartRecordingOptions* aOptions = nullptr) MOZ_OVERRIDE
-                                        { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult StopRecordingImpl() { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult PushParametersImpl() { return NS_ERROR_NOT_INITIALIZED; }
-  virtual nsresult PullParametersImpl() { return NS_ERROR_NOT_INITIALIZED; }
+                                        { return NS_ERROR_FAILURE; }
+  virtual nsresult StopRecordingImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult ResumeContinuousFocusImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult PushParametersImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual nsresult PullParametersImpl() MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
   virtual already_AddRefed<RecorderProfileManager> GetRecorderProfileManagerImpl() MOZ_OVERRIDE { return nullptr; }
 
 private:
   FallbackCameraControl(const FallbackCameraControl&) MOZ_DELETE;
   FallbackCameraControl& operator=(const FallbackCameraControl&) MOZ_DELETE;
 };
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -48,19 +48,18 @@ using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 using namespace mozilla::ipc;
 using namespace android;
 
 #define RETURN_IF_NO_CAMERA_HW()                                          \
   do {                                                                    \
     if (!mCameraHw.get()) {                                               \
-      NS_WARNING("Camera hardware is not initialized");                   \
       DOM_CAMERA_LOGE("%s:%d : mCameraHw is null\n", __func__, __LINE__); \
-      return NS_ERROR_NOT_INITIALIZED;                                    \
+      return NS_ERROR_NOT_AVAILABLE;                                      \
     }                                                                     \
   } while(0)
 
 // Construct nsGonkCameraControl on the main thread.
 nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId)
   : CameraControlImpl(aCameraId)
   , mLastPictureSize({0, 0})
   , mLastThumbnailSize({0, 0})
@@ -103,17 +102,17 @@ nsGonkCameraControl::StartImpl(const Con
    * The intent of the above flow is to let the Main Thread do as much work
    * up-front as possible without waiting for blocking Camera Thread calls
    * to complete.
    */
   MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread);
 
   nsresult rv = Initialize();
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    return NS_ERROR_NOT_INITIALIZED;
+    return rv;
   }
 
   if (aInitialConfig) {
     rv = SetConfigurationInternal(*aInitialConfig);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       // The initial configuration failed, close up the hardware
       StopImpl();
       return rv;
@@ -122,25 +121,20 @@ nsGonkCameraControl::StartImpl(const Con
 
   OnHardwareStateChange(CameraControlListener::kHardwareOpen);
   return StartPreviewImpl();
 }
 
 nsresult
 nsGonkCameraControl::Initialize()
 {
-  if (mCameraHw.get()) {
-    DOM_CAMERA_LOGI("Camera %d already connected (this=%p)\n", mCameraId, this);
-    return NS_ERROR_ALREADY_INITIALIZED;
-  }
-
   mCameraHw = GonkCameraHardware::Connect(this, mCameraId);
   if (!mCameraHw.get()) {
     DOM_CAMERA_LOGE("Failed to connect to camera %d (this=%p)\n", mCameraId, this);
-    return NS_ERROR_NOT_INITIALIZED;
+    return NS_ERROR_FAILURE;
   }
 
   DOM_CAMERA_LOGI("Initializing camera %d (this=%p, mCameraHw=%p)\n", mCameraId, this, mCameraHw.get());
 
   // Initialize our camera configuration database.
   PullParametersImpl();
 
   // Set preferred preview frame format.
@@ -697,17 +691,18 @@ nsGonkCameraControl::SetThumbnailSize(co
     }
     ~SetThumbnailSize() { MOZ_COUNT_DTOR(SetThumbnailSize); }
 
     NS_IMETHODIMP
     Run() MOZ_OVERRIDE
     {
       nsresult rv = mCameraControl->SetThumbnailSizeImpl(mSize);
       if (NS_FAILED(rv)) {
-        mCameraControl->OnUserError(CameraControlListener::kInSetThumbnailSize, rv);
+        mCameraControl->OnError(CameraControlListener::kInUnspecified,
+                                CameraControlListener::kErrorSetThumbnailSizeFailed);
       }
       return NS_OK;
     }
 
   protected:
     nsRefPtr<nsGonkCameraControl> mCameraControl;
     Size mSize;
   };
@@ -832,17 +827,18 @@ nsGonkCameraControl::SetPictureSize(cons
     }
     ~SetPictureSize() { MOZ_COUNT_DTOR(SetPictureSize); }
 
     NS_IMETHODIMP
     Run() MOZ_OVERRIDE
     {
       nsresult rv = mCameraControl->SetPictureSizeImpl(mSize);
       if (NS_FAILED(rv)) {
-        mCameraControl->OnUserError(CameraControlListener::kInSetPictureSize, rv);
+        mCameraControl->OnError(CameraControlListener::kInUnspecified,
+                                CameraControlListener::kErrorSetPictureSizeFailed);
       }
       return NS_OK;
     }
 
   protected:
     nsRefPtr<nsGonkCameraControl> mCameraControl;
     Size mSize;
   };
@@ -950,19 +946,17 @@ nsGonkCameraControl::StartRecordingImpl(
   /**
    * Get the base path from device storage and append the app-specified
    * filename to it.  The filename may include a relative subpath
    * (e.g.) "DCIM/IMG_0001.jpg".
    *
    * The camera app needs to provide the file extension '.3gp' for now.
    * See bug 795202.
    */
-  if (NS_WARN_IF(!aFileDescriptor)) {
-    return NS_ERROR_INVALID_ARG;
-  }
+  NS_ENSURE_TRUE(aFileDescriptor, NS_ERROR_FAILURE);
   nsAutoString fullPath;
   mVideoFile = aFileDescriptor->mDSFile;
   mVideoFile->GetFullPath(fullPath);
   DOM_CAMERA_LOGI("Video filename is '%s'\n",
                   NS_LossyConvertUTF16toASCII(fullPath).get());
 
   if (!mVideoFile->IsSafePath()) {
     DOM_CAMERA_LOGE("Invalid video file name\n");
@@ -1207,18 +1201,18 @@ nsGonkCameraControl::OnTakePictureComple
   }
 
   DOM_CAMERA_LOGI("nsGonkCameraControl::OnTakePictureComplete() done\n");
 }
 
 void
 nsGonkCameraControl::OnTakePictureError()
 {
-  CameraControlImpl::OnUserError(CameraControlListener::kInTakePicture,
-                                 NS_ERROR_FAILURE);
+  CameraControlImpl::OnError(CameraControlListener::kInTakePicture,
+                             CameraControlListener::kErrorApiFailed);
 }
 
 nsresult
 nsGonkCameraControl::SetPreviewSize(const Size& aSize)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread);
 
   nsTArray<Size> previewSizes;
@@ -1643,25 +1637,25 @@ nsGonkCameraControl::OnNewPreviewFrame(l
                           mCurrentConfiguration.mPreviewSize.height);
   videoImage->SetData(data);
 
   OnNewPreviewFrame(frame, mCurrentConfiguration.mPreviewSize.width,
                     mCurrentConfiguration.mPreviewSize.height);
 }
 
 void
-nsGonkCameraControl::OnSystemError(CameraControlListener::SystemContext aWhere,
-                                   nsresult aError)
+nsGonkCameraControl::OnError(CameraControlListener::CameraErrorContext aWhere,
+                             CameraControlListener::CameraError aError)
 {
-  if (aWhere == CameraControlListener::kSystemService) {
+  if (aError == CameraControlListener::kErrorServiceFailed) {
     OnPreviewStateChange(CameraControlListener::kPreviewStopped);
     OnHardwareStateChange(CameraControlListener::kHardwareClosed);
   }
 
-  CameraControlImpl::OnSystemError(aWhere, aError);
+  CameraControlImpl::OnError(aWhere, aError);
 }
 
 // Gonk callback handlers.
 namespace mozilla {
 
 void
 OnTakePictureComplete(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength)
 {
@@ -1706,22 +1700,21 @@ OnShutter(nsGonkCameraControl* gc)
 
 void
 OnClosed(nsGonkCameraControl* gc)
 {
   gc->OnClosed();
 }
 
 void
-OnSystemError(nsGonkCameraControl* gc,
-              CameraControlListener::SystemContext aWhere,
-              int32_t aArg1, int32_t aArg2)
+OnError(nsGonkCameraControl* gc, CameraControlListener::CameraError aError,
+        int32_t aArg1, int32_t aArg2)
 {
 #ifdef PR_LOGGING
-  DOM_CAMERA_LOGE("OnSystemError : aWhere=%d, aArg1=%d, aArg2=%d\n", aWhere, aArg1, aArg2);
+  DOM_CAMERA_LOGE("OnError : aError=%d, aArg1=%d, aArg2=%d\n", aError, aArg1, aArg2);
 #else
   unused << aArg1;
   unused << aArg2;
 #endif
-  gc->OnSystemError(aWhere, NS_ERROR_FAILURE);
+  gc->OnError(CameraControlListener::kInUnspecified, aError);
 }
 
 } // namespace mozilla
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -49,19 +49,19 @@ public:
   nsGonkCameraControl(uint32_t aCameraId);
 
   void OnAutoFocusComplete(bool aSuccess);
   void OnFacesDetected(camera_frame_metadata_t* aMetaData);
   void OnTakePictureComplete(uint8_t* aData, uint32_t aLength);
   void OnTakePictureError();
   void OnNewPreviewFrame(layers::TextureClient* aBuffer);
   void OnRecorderEvent(int msg, int ext1, int ext2);
-  void OnSystemError(CameraControlListener::SystemContext aWhere, nsresult aError);
- 
-  // See ICameraControl.h for getter/setter return values.
+  void OnError(CameraControlListener::CameraErrorContext aWhere,
+               CameraControlListener::CameraError aError);
+
   virtual nsresult Set(uint32_t aKey, const nsAString& aValue) MOZ_OVERRIDE;
   virtual nsresult Get(uint32_t aKey, nsAString& aValue) MOZ_OVERRIDE;
   virtual nsresult Set(uint32_t aKey, double aValue) MOZ_OVERRIDE;
   virtual nsresult Get(uint32_t aKey, double& aValue) MOZ_OVERRIDE;
   virtual nsresult Set(uint32_t aKey, int32_t aValue) MOZ_OVERRIDE;
   virtual nsresult Get(uint32_t aKey, int32_t& aValue) MOZ_OVERRIDE;
   virtual nsresult Set(uint32_t aKey, int64_t aValue) MOZ_OVERRIDE;
   virtual nsresult Get(uint32_t aKey, int64_t& aValue) MOZ_OVERRIDE;
@@ -82,33 +82,32 @@ public:
 protected:
   ~nsGonkCameraControl();
 
   using CameraControlImpl::OnNewPreviewFrame;
   using CameraControlImpl::OnAutoFocusComplete;
   using CameraControlImpl::OnFacesDetected;
   using CameraControlImpl::OnTakePictureComplete;
   using CameraControlImpl::OnConfigurationChange;
-  using CameraControlImpl::OnUserError;
+  using CameraControlImpl::OnError;
 
   virtual void BeginBatchParameterSet() MOZ_OVERRIDE;
   virtual void EndBatchParameterSet() MOZ_OVERRIDE;
 
+  virtual nsresult StartImpl(const Configuration* aInitialConfig = nullptr) MOZ_OVERRIDE;
+  virtual nsresult StopImpl() MOZ_OVERRIDE;
   nsresult Initialize();
 
+  virtual nsresult SetConfigurationImpl(const Configuration& aConfig) MOZ_OVERRIDE;
   nsresult SetConfigurationInternal(const Configuration& aConfig);
   nsresult SetPictureConfiguration(const Configuration& aConfig);
   nsresult SetVideoConfiguration(const Configuration& aConfig);
 
   template<class T> nsresult SetAndPush(uint32_t aKey, const T& aValue);
 
-  // See CameraControlImpl.h for these methods' return values.
-  virtual nsresult StartImpl(const Configuration* aInitialConfig = nullptr) MOZ_OVERRIDE;
-  virtual nsresult SetConfigurationImpl(const Configuration& aConfig) MOZ_OVERRIDE;
-  virtual nsresult StopImpl() MOZ_OVERRIDE;
   virtual nsresult StartPreviewImpl() MOZ_OVERRIDE;
   virtual nsresult StopPreviewImpl() MOZ_OVERRIDE;
   virtual nsresult AutoFocusImpl() MOZ_OVERRIDE;
   virtual nsresult StartFaceDetectionImpl() MOZ_OVERRIDE;
   virtual nsresult StopFaceDetectionImpl() MOZ_OVERRIDE;
   virtual nsresult TakePictureImpl() MOZ_OVERRIDE;
   virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
                                       const StartRecordingOptions* aOptions = nullptr) MOZ_OVERRIDE;
@@ -175,15 +174,14 @@ private:
 void OnTakePictureComplete(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength);
 void OnTakePictureError(nsGonkCameraControl* gc);
 void OnAutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess);
 void OnAutoFocusMoving(nsGonkCameraControl* gc, bool aIsMoving);
 void OnFacesDetected(nsGonkCameraControl* gc, camera_frame_metadata_t* aMetaData);
 void OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer);
 void OnShutter(nsGonkCameraControl* gc);
 void OnClosed(nsGonkCameraControl* gc);
-void OnSystemError(nsGonkCameraControl* gc,
-                   CameraControlListener::SystemContext aWhere,
-                   int32_t aArg1, int32_t aArg2);
+void OnError(nsGonkCameraControl* gc, CameraControlListener::CameraError aError,
+             int32_t aArg1, int32_t aArg2);
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_GONKCAMERACONTROL_H
--- a/dom/camera/GonkCameraHwMgr.cpp
+++ b/dom/camera/GonkCameraHwMgr.cpp
@@ -108,17 +108,17 @@ GonkCameraHardware::notify(int32_t aMsgT
       break;
 #endif
 
     case CAMERA_MSG_SHUTTER:
       OnShutter(mTarget);
       break;
 
     case CAMERA_MSG_ERROR:
-      OnSystemError(mTarget, CameraControlListener::kSystemService, ext1, ext2);
+      OnError(mTarget, CameraControlListener::kErrorServiceFailed, ext1, ext2);
       break;
 
     default:
       DOM_CAMERA_LOGE("Unhandled notify callback event %d\n", aMsgType);
       break;
   }
 }
 
@@ -143,17 +143,17 @@ nsresult
 GonkCameraHardware::Init()
 {
   DOM_CAMERA_LOGT("%s: this=%p\n", __func__, (void* )this);
 
   CameraInfo info;
   int rv = Camera::getCameraInfo(mCameraId, &info);
   if (rv != 0) {
     DOM_CAMERA_LOGE("%s: failed to get CameraInfo mCameraId %d\n", __func__, mCameraId);
-    return NS_ERROR_NOT_INITIALIZED;
+    return NS_ERROR_FAILURE;
    }
 
   mRawSensorOrientation = info.orientation;
   mSensorOrientation = mRawSensorOrientation;
 
   /**
    * Non-V4L2-based camera driver adds extra offset onto picture orientation
    * set by gecko, so we have to adjust it back.
--- a/dom/camera/GonkCameraHwMgr.h
+++ b/dom/camera/GonkCameraHwMgr.h
@@ -38,22 +38,16 @@ namespace mozilla {
 namespace android {
 
 class GonkCameraHardware : public GonkNativeWindowNewFrameCallback
                          , public CameraListener
 {
 protected:
   GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId, const sp<Camera>& aCamera);
   virtual ~GonkCameraHardware();
-
-  // Initialize the AOSP camera interface.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_NOT_INITIALIZED if the interface could not be initialized.
   virtual nsresult Init();
 
 public:
   static sp<GonkCameraHardware> Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId);
   virtual void Close();
 
   // derived from GonkNativeWindowNewFrameCallback
   virtual void OnNewFrame() MOZ_OVERRIDE;
--- a/dom/camera/GonkCameraManager.cpp
+++ b/dom/camera/GonkCameraManager.cpp
@@ -15,18 +15,16 @@
  */
 
 #include "ICameraControl.h"
 
 #include <camera/Camera.h>
 
 #include "CameraCommon.h"
 #include "GonkCameraControl.h"
-#include "mozilla/Preferences.h"
-#include "TestGonkCameraControl.h"
 
 using namespace mozilla;
 
 // From ICameraControl, gonk-specific management functions
 nsresult
 ICameraControl::GetNumberOfCameras(int32_t& aDeviceCount)
 {
   aDeviceCount = android::Camera::getNumberOfCameras();
@@ -37,17 +35,17 @@ nsresult
 ICameraControl::GetCameraName(uint32_t aDeviceNum, nsCString& aDeviceName)
 {
   int32_t count = android::Camera::getNumberOfCameras();
   int32_t deviceNum = static_cast<int32_t>(aDeviceNum);
 
   DOM_CAMERA_LOGI("GetCameraName : getNumberOfCameras() returned %d\n", count);
   if (deviceNum < 0 || deviceNum > count) {
     DOM_CAMERA_LOGE("GetCameraName : invalid device number (%u)\n", aDeviceNum);
-    return NS_ERROR_INVALID_ARG;
+    return NS_ERROR_NOT_AVAILABLE;
   }
 
   android::CameraInfo info;
   int rv = android::Camera::getCameraInfo(deviceNum, &info);
   if (rv != 0) {
     DOM_CAMERA_LOGE("GetCameraName : get_camera_info(%d) failed: %d\n", deviceNum, rv);
     return NS_ERROR_NOT_AVAILABLE;
   }
@@ -70,17 +68,16 @@ ICameraControl::GetCameraName(uint32_t a
 }
 
 nsresult
 ICameraControl::GetListOfCameras(nsTArray<nsString>& aList)
 {
   int32_t count = android::Camera::getNumberOfCameras();
   DOM_CAMERA_LOGI("getListOfCameras : getNumberOfCameras() returned %d\n", count);
   if (count <= 0) {
-    aList.Clear();
     return NS_OK;
   }
 
   // Allocate 2 extra slots to reserve space for 'front' and 'back' cameras
   // at the front of the array--we will collapse any empty slots below.
   aList.SetLength(2);
   uint32_t extraIdx = 2;
   bool gotFront = false;
@@ -112,24 +109,15 @@ ICameraControl::GetListOfCameras(nsTArra
 
   if (!gotBack) {
     aList.RemoveElementAt(0);
   }
 
   return NS_OK;
 }
 
-static const char* sTestModeEnabled = "camera.control.test.enabled";
-
 // implementation-specific camera factory
 already_AddRefed<ICameraControl>
 ICameraControl::Create(uint32_t aCameraId)
 {
-  const nsAdoptingCString& test = Preferences::GetCString(sTestModeEnabled);
-  nsRefPtr<nsGonkCameraControl> control;
-  if (test.EqualsASCII("control")) {
-    NS_WARNING("Using test CameraControl layer");
-    control = new TestGonkCameraControl(aCameraId);
-  } else {
-    control = new nsGonkCameraControl(aCameraId);
-  }
+  nsRefPtr<nsGonkCameraControl> control = new nsGonkCameraControl(aCameraId);
   return control.forget();
 }
--- a/dom/camera/GonkCameraParameters.cpp
+++ b/dom/camera/GonkCameraParameters.cpp
@@ -134,24 +134,23 @@ GonkCameraParameters::Parameters::GetTex
 
 GonkCameraParameters::GonkCameraParameters()
   : mLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraParameters.Lock"))
   , mDirty(false)
   , mInitialized(false)
 {
   MOZ_COUNT_CTOR(GonkCameraParameters);
   if (!mLock) {
-    MOZ_CRASH("Out of memory getting new PRRWLock");
+    MOZ_CRASH("OOM getting new PRRWLock");
   }
 }
 
 GonkCameraParameters::~GonkCameraParameters()
 {
   MOZ_COUNT_DTOR(GonkCameraParameters);
-  MOZ_ASSERT(mLock, "mLock missing in ~GonkCameraParameters()");
   if (mLock) {
     PR_DestroyRWLock(mLock);
     mLock = nullptr;
   }
 }
 
 nsresult
 GonkCameraParameters::MapIsoToGonk(const nsAString& aIso, nsACString& aIsoOut)
@@ -159,17 +158,17 @@ GonkCameraParameters::MapIsoToGonk(const
   if (aIso.EqualsASCII("hjr")) {
     aIsoOut = "ISO_HJR";
   } else if (aIso.EqualsASCII("auto")) {
     aIsoOut = "auto";
   } else {
     nsAutoCString v = NS_LossyConvertUTF16toASCII(aIso);
     unsigned int iso;
     if (sscanf(v.get(), "%u", &iso) != 1) {
-      return NS_ERROR_INVALID_ARG;
+      return NS_ERROR_FAILURE;
     }
     aIsoOut = nsPrintfCString("ISO%u", iso);
   }
 
   return NS_OK;
 }
 
 nsresult
@@ -177,17 +176,17 @@ GonkCameraParameters::MapIsoFromGonk(con
 {
   if (strcmp(aIso, "ISO_HJR") == 0) {
     aIsoOut.AssignASCII("hjr");
   } else if (strcmp(aIso, "auto") == 0) {
     aIsoOut.AssignASCII("auto");
   } else {
     unsigned int iso;
     if (sscanf(aIso, "ISO%u", &iso) != 1) {
-      return NS_ERROR_INVALID_ARG;
+      return NS_ERROR_FAILURE;
     }
     aIsoOut.AppendInt(iso);
   }
 
   return NS_OK;
 }
 
 // Any members that need to be initialized on the first parameter pull
@@ -329,49 +328,39 @@ GonkCameraParameters::GetTranslated(uint
 {
   nsresult rv;
 
   if (aKey == CAMERA_PARAM_THUMBNAILSIZE) {
     int width;
     int height;
 
     rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-    if (width < 0) {
-      return NS_ERROR_NOT_AVAILABLE;
+    if (NS_FAILED(rv) || width < 0) {
+      return NS_ERROR_FAILURE;
     }
     rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-    if (height < 0) {
-      return NS_ERROR_NOT_AVAILABLE;
+    if (NS_FAILED(rv) || height < 0) {
+      return NS_ERROR_FAILURE;
     }
 
     aSize.width = static_cast<uint32_t>(width);
     aSize.height = static_cast<uint32_t>(height);
     return NS_OK;
   }
 
   const char* value;
   rv = GetImpl(aKey, value);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  if (!value || *value == '\0') {
-    DOM_CAMERA_LOGW("Camera parameter aKey=%d not available\n", aKey);
+  if (NS_FAILED(rv) || !value || *value == '\0') {
+    DOM_CAMERA_LOGW("Camera parameter aKey=%d not available (0x%x)\n", aKey, rv);
     return NS_ERROR_NOT_AVAILABLE;
   }
   if (sscanf(value, "%ux%u", &aSize.width, &aSize.height) != 2) {
     DOM_CAMERA_LOGE("Camera parameter aKey=%d size tuple '%s' is invalid\n", aKey, value);
-    return NS_ERROR_NOT_AVAILABLE;
+    return NS_ERROR_FAILURE;
   }
-
   return NS_OK;
 }
 
 // Handle arrays of ICameraControl::Regions
 nsresult
 GonkCameraParameters::SetTranslated(uint32_t aKey, const nsTArray<ICameraControl::Region>& aRegions)
 {
   uint32_t length = aRegions.Length();
@@ -396,22 +385,18 @@ GonkCameraParameters::SetTranslated(uint
 
 nsresult
 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Region>& aRegions)
 {
   aRegions.Clear();
 
   const char* value;
   nsresult rv = GetImpl(aKey, value);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  if (!value || *value == '\0') {
-    DOM_CAMERA_LOGW("Camera parameter aKey=%d not available\n", aKey);
-    return NS_ERROR_NOT_AVAILABLE;
+  if (NS_FAILED(rv) || !value || *value == '\0') {
+    return NS_ERROR_FAILURE;
   }
 
   const char* p = value;
   uint32_t count = 1;
 
   // count the number of regions in the string
   while ((p = strstr(p, "),("))) {
     ++count;
@@ -421,19 +406,19 @@ GonkCameraParameters::GetTranslated(uint
   aRegions.SetCapacity(count);
   ICameraControl::Region* r;
 
   // parse all of the region sets
   uint32_t i;
   for (i = 0, p = value; p && i < count; ++i, p = strchr(p + 1, '(')) {
     r = aRegions.AppendElement();
     if (sscanf(p, "(%d,%d,%d,%d,%u)", &r->top, &r->left, &r->bottom, &r->right, &r->weight) != 5) {
-      DOM_CAMERA_LOGE("Camera parameter aKey=%d region tuple has bad format: '%s'\n", aKey, p);
+      DOM_CAMERA_LOGE("%s:%d : region tuple has bad format: '%s'\n", __func__, __LINE__, p);
       aRegions.Clear();
-      return NS_ERROR_NOT_AVAILABLE;
+      return NS_ERROR_FAILURE;
     }
   }
 
   return NS_OK;
 }
 
 // Handle ICameraControl::Positions
 nsresult
@@ -453,17 +438,16 @@ GonkCameraParameters::SetTranslated(uint
   if (!isnan(aPosition.altitude)) {
     DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aPosition.altitude);
     SetImpl(Parameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get());
   }
   if (!isnan(aPosition.timestamp)) {
     DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aPosition.timestamp);
     SetImpl(Parameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get());
   }
-
   return NS_OK;
 }
 
 // Handle int64_ts
 nsresult
 GonkCameraParameters::SetTranslated(uint32_t aKey, const int64_t& aValue)
 {
   switch (aKey) {
@@ -693,17 +677,17 @@ nsresult
 GonkCameraParameters::GetTranslated(uint32_t aKey, uint32_t& aValue)
 {
   int val;
   nsresult rv = GetImpl(aKey, val);
   if (NS_FAILED(rv)) {
     return rv;
   }
   if (val < 0) {
-    return NS_ERROR_NOT_AVAILABLE;
+    return NS_ERROR_FAILURE;
   }
 
   aValue = val;
   return NS_OK;
 }
 
 // Handle bools
 nsresult
@@ -720,18 +704,18 @@ GonkCameraParameters::GetTranslated(uint
 
 nsresult
 ParseItem(const char* aStart, const char* aEnd, ICameraControl::Size* aItem)
 {
   if (sscanf(aStart, "%ux%u", &aItem->width, &aItem->height) == 2) {
     return NS_OK;
   }
 
-  DOM_CAMERA_LOGE("Size tuple has bad format: '%s'\n", aStart);
-  return NS_ERROR_NOT_AVAILABLE;
+  DOM_CAMERA_LOGE("Size tuple has bad format: '%s'\n", __func__, __LINE__, aStart);
+  return NS_ERROR_FAILURE;
 }
 
 nsresult
 ParseItem(const char* aStart, const char* aEnd, nsAString* aItem)
 {
   if (aEnd) {
     aItem->AssignASCII(aStart, aEnd - aStart);
   } else {
@@ -753,27 +737,27 @@ ParseItem(const char* aStart, const char
 
 nsresult
 ParseItem(const char* aStart, const char* aEnd, double* aItem)
 {
   if (sscanf(aStart, "%lf", aItem) == 1) {
     return NS_OK;
   }
 
-  return NS_ERROR_NOT_AVAILABLE;
+  return NS_ERROR_FAILURE;
 }
 
 nsresult
 ParseItem(const char* aStart, const char* aEnd, int* aItem)
 {
   if (sscanf(aStart, "%d", aItem) == 1) {
     return NS_OK;
   }
 
-  return NS_ERROR_NOT_AVAILABLE;
+  return NS_ERROR_FAILURE;
 }
 
 template<class T> nsresult
 GonkCameraParameters::GetListAsArray(uint32_t aKey, nsTArray<T>& aArray)
 {
   const char* p;
   nsresult rv = GetImpl(aKey, p);
   if (NS_FAILED(rv)) {
@@ -790,18 +774,21 @@ GonkCameraParameters::GetListAsArray(uin
   if (*p == '\0') {
     DOM_CAMERA_LOGI("Camera parameter %d not available (value is empty string)\n", aKey);
     return NS_OK;
   }
 
   const char* comma;
 
   while (p) {
-    // nsTArray::AppendElement() is infallible
     T* v = aArray.AppendElement();
+    if (!v) {
+      aArray.Clear();
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
     comma = strchr(p, ',');
     if (comma != p) {
       rv = ParseItem(p, comma, v);
       if (NS_FAILED(rv)) {
         aArray.Clear();
         return rv;
       }
       p = comma;
--- a/dom/camera/GonkCameraParameters.h
+++ b/dom/camera/GonkCameraParameters.h
@@ -32,19 +32,16 @@ class GonkCameraParameters
 public:
   GonkCameraParameters();
   virtual ~GonkCameraParameters();
 
   // IMPORTANT: This class is read and written by multiple threads --
   // ALL public methods must hold mLock, for either reading or writing,
   // for the life of their operation. Not doing so was the cause of
   // bug 928856, which was -painful- to track down.
-  //
-  // Return values:
-  //  - see return values for GetTranslated() and SetTranslated() below.
   template<class T> nsresult
   Set(uint32_t aKey, const T& aValue)
   {
     RwLockAutoEnterWrite lock(mLock);
     nsresult rv = SetTranslated(aKey, aValue);
     mDirty = mDirty || NS_SUCCEEDED(rv);
     return rv;
   }
@@ -122,35 +119,31 @@ protected:
     static const char* GetTextKey(uint32_t aKey);
   };
 
   Parameters mParams;
 
   // The *Impl() templates handle converting the parameter keys from
   // their enum values to string types, if necessary. These are the
   // bottom layer accessors to mParams.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_NOT_IMPLEMENTED if the numeric 'aKey' value is invalid.
   template<typename T> nsresult
   SetImpl(uint32_t aKey, const T& aValue)
   {
     const char* key = Parameters::GetTextKey(aKey);
-    NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED);
+    NS_ENSURE_TRUE(key, NS_ERROR_NOT_AVAILABLE);
 
     mParams.set(key, aValue);
     return NS_OK;
   }
 
   template<typename T> nsresult
   GetImpl(uint32_t aKey, T& aValue)
   {
     const char* key = Parameters::GetTextKey(aKey);
-    NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED);
+    NS_ENSURE_TRUE(key, NS_ERROR_NOT_AVAILABLE);
 
     mParams.get(key, aValue);
     return NS_OK;
   }
 
   template<class T> nsresult
   SetImpl(const char* aKey, const T& aValue)
   {
@@ -164,25 +157,16 @@ protected:
     mParams.get(aKey, aValue);
     return NS_OK;
   }
 
   // The *Translated() functions allow us to handle special cases;
   // for example, where the thumbnail size setting is exposed as an
   // ICameraControl::Size object, but is handled by the AOSP layer
   // as two separate parameters.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aValue' contains an invalid value;
-  //  - NS_ERROR_NOT_IMPLEMENTED if 'aKey' is invalid;
-  //  - NS_ERROR_NOT_AVAILABLE if the getter fails to retrieve a valid value,
-  //      or if a setter fails because it requires one or more values that
-  //      could not be retrieved;
-  //  - NS_ERROR_FAILURE on unexpected internal failures.
   nsresult SetTranslated(uint32_t aKey, const nsAString& aValue);
   nsresult GetTranslated(uint32_t aKey, nsAString& aValue);
   nsresult SetTranslated(uint32_t aKey, const ICameraControl::Size& aSize);
   nsresult GetTranslated(uint32_t aKey, ICameraControl::Size& aSize);
   nsresult GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Size>& aSizes);
   nsresult SetTranslated(uint32_t aKey, const nsTArray<ICameraControl::Region>& aRegions);
   nsresult GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Region>& aRegions);
   nsresult SetTranslated(uint32_t aKey, const ICameraControl::Position& aPosition);
@@ -194,35 +178,18 @@ protected:
   nsresult GetTranslated(uint32_t aKey, int& aValue);
   nsresult SetTranslated(uint32_t aKey, const uint32_t& aValue);
   nsresult GetTranslated(uint32_t aKey, uint32_t& aValue);
   nsresult SetTranslated(uint32_t aKey, const bool& aValue);
   nsresult GetTranslated(uint32_t aKey, bool& aValue);
   nsresult GetTranslated(uint32_t aKey, nsTArray<nsString>& aValues);
   nsresult GetTranslated(uint32_t aKey, nsTArray<double>& aValues);
 
-  // Converts a string of multiple, comma-separated values into an array
-  // of the appropriate type.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_NOT_IMPLEMENTED if 'aKey' is invalid;
-  //  - NS_ERROR_NOT_AVAILABLE if a valid value could not be returned.
   template<class T> nsresult GetListAsArray(uint32_t aKey, nsTArray<T>& aArray);
-
-  // Converts ISO values (e.g., "auto", "hjr", "100", "200", etc.) to and from
-  // values understood by Gonk (e.g., "auto", "ISO_HJR", "ISO100", "ISO200",
-  // respectively).
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if the 'aIso' argument is not a valid form.
   nsresult MapIsoToGonk(const nsAString& aIso, nsACString& aIsoOut);
   nsresult MapIsoFromGonk(const char* aIso, nsAString& aIsoOut);
 
-  // Call once to initialize local cached values used in translating other
-  // arguments between Gecko and Gonk. Always returns NS_OK.
   nsresult Initialize();
 };
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_GONKCAMERAPARAMETERS_H
--- a/dom/camera/GonkRecorderProfiles.cpp
+++ b/dom/camera/GonkRecorderProfiles.cpp
@@ -88,21 +88,16 @@ GonkRecorderProfile::GonkRecorderProfile
 GonkRecorderProfile::~GonkRecorderProfile()
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
 }
 
 nsresult
 GonkRecorderProfile::ConfigureRecorder(GonkRecorder* aRecorder)
 {
-  if (!aRecorder) {
-    DOM_CAMERA_LOGW("ConfigureRecorder() called with null aRecorder\n");
-    return NS_ERROR_INVALID_ARG;
-  }
-
   static const size_t SIZE = 256;
   char buffer[SIZE];
 
   // set all the params
   CHECK_SETARG(aRecorder->setAudioSource(AUDIO_SOURCE_CAMCORDER));
   CHECK_SETARG(aRecorder->setVideoSource(VIDEO_SOURCE_CAMERA));
   CHECK_SETARG(aRecorder->setOutputFormat(GetOutputFormat()));
   CHECK_SETARG(aRecorder->setVideoFrameRate(mVideo.GetFramerate()));
--- a/dom/camera/GonkRecorderProfiles.h
+++ b/dom/camera/GonkRecorderProfiles.h
@@ -9,17 +9,17 @@
 #include "CameraRecorderProfiles.h"
 #include "ICameraControl.h"
 
 #ifndef CHECK_SETARG
 #define CHECK_SETARG(x)                 \
   do {                                  \
     if (x) {                            \
       DOM_CAMERA_LOGE(#x " failed\n");  \
-      return NS_ERROR_NOT_AVAILABLE;    \
+      return NS_ERROR_INVALID_ARG;      \
     }                                   \
   } while(0)
 #endif
 
 
 namespace android {
 class GonkRecorder;
 };
@@ -61,23 +61,16 @@ class GonkRecorderProfile : public Recor
 {
 public:
   GonkRecorderProfile(uint32_t aCameraId, uint32_t aQualityIndex);
 
   GonkRecorderAudioProfile* GetGonkAudioProfile() { return &mAudio; }
   GonkRecorderVideoProfile* GetGonkVideoProfile() { return &mVideo; }
 
   android::output_format GetOutputFormat() const { return mPlatformOutputFormat; }
-
-  // Configures the specified recorder using this profile.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aRecorder' is null;
-  //  - NS_ERROR_NOT_AVAILABLE if the recorder rejected this profile.
   nsresult ConfigureRecorder(android::GonkRecorder* aRecorder);
 
 protected:
   virtual ~GonkRecorderProfile();
 
   android::output_format mPlatformOutputFormat;
 };
 
@@ -102,16 +95,17 @@ public:
    * SetSupportedResolutions().
    */
   void ClearSupportedResolutions() { mSupportedSizes.Clear(); }
 
   bool IsSupported(uint32_t aQualityIndex) const;
 
   already_AddRefed<RecorderProfile> Get(uint32_t aQualityIndex) const;
   already_AddRefed<GonkRecorderProfile> Get(const char* aProfileName) const;
+  nsresult ConfigureRecorder(android::GonkRecorder* aRecorder);
 
 protected:
   virtual ~GonkRecorderProfileManager();
 
   nsTArray<ICameraControl::Size> mSupportedSizes;
 };
 
 }; // namespace mozilla
--- a/dom/camera/ICameraControl.h
+++ b/dom/camera/ICameraControl.h
@@ -75,38 +75,18 @@ enum {
   CAMERA_PARAM_SUPPORTED_ISOMODES
 };
 
 class ICameraControl
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ICameraControl)
 
-  // Returns the number of cameras supported by the system.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_FAILURE if the camera count cannot be retrieved.
   static nsresult GetNumberOfCameras(int32_t& aDeviceCount);
-
-  // Gets the (possibly-meaningful) name of a particular camera.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aDeviceNum' is not a valid camera number;
-  //  - NS_ERROR_NOT_AVAILABLE if 'aDeviceNum' is valid but the camera name
-  //      could still not be retrieved.
   static nsresult GetCameraName(uint32_t aDeviceNum, nsCString& aDeviceName);
-
-  // Returns a list of names of all cameras supported by the system.
-  //
-  // Return values:
-  //  - NS_OK on success, even if no camera names are returned (in which
-  //      case 'aList' will be empty);
-  //  - NS_ERROR_NOT_AVAILABLE if the list of cameras cannot be retrieved.
   static nsresult GetListOfCameras(nsTArray<nsString>& aList);
 
   enum Mode {
     kUnspecifiedMode,
     kPictureMode,
     kVideoMode,
   };
 
@@ -138,17 +118,18 @@ public:
   };
 
   struct Configuration {
     Mode      mMode;
     Size      mPreviewSize;
     nsString  mRecorderProfile;
   };
 
-  struct Point {
+  struct Point
+  {
     int32_t   x;
     int32_t   y;
   };
 
   struct Face {
     uint32_t  id;
     uint32_t  score;
     Region    bound;
@@ -157,51 +138,35 @@ public:
     bool      hasRightEye;
     Point     rightEye;
     bool      hasMouth;
     Point     mouth;
   };
 
   static already_AddRefed<ICameraControl> Create(uint32_t aCameraId);
 
+  virtual nsresult Start(const Configuration* aInitialConfig = nullptr) = 0;
+  virtual nsresult Stop() = 0;
+
+  virtual nsresult SetConfiguration(const Configuration& aConfig) = 0;
+
   virtual void AddListener(CameraControlListener* aListener) = 0;
   virtual void RemoveListener(CameraControlListener* aListener) = 0;
 
-  // Camera control methods.
-  //
-  // Return values:
-  //  - NS_OK on success (if the method requires an asynchronous process,
-  //      this value indicates that the process has begun successfully);
-  //  - NS_ERROR_INVALID_ARG if one or more arguments is invalid;
-  //  - NS_ERROR_FAILURE if an asynchronous method could not be dispatched.
-  virtual nsresult Start(const Configuration* aInitialConfig = nullptr) = 0;
-  virtual nsresult Stop() = 0;
-  virtual nsresult SetConfiguration(const Configuration& aConfig) = 0;
   virtual nsresult StartPreview() = 0;
   virtual nsresult StopPreview() = 0;
   virtual nsresult AutoFocus() = 0;
   virtual nsresult TakePicture() = 0;
   virtual nsresult StartRecording(DeviceStorageFileDescriptor *aFileDescriptor,
                                   const StartRecordingOptions* aOptions = nullptr) = 0;
   virtual nsresult StopRecording() = 0;
   virtual nsresult StartFaceDetection() = 0;
   virtual nsresult StopFaceDetection() = 0;
   virtual nsresult ResumeContinuousFocus() = 0;
 
-  // Camera parameter getters and setters. 'aKey' must be one of the
-  // CAMERA_PARAM_* values enumerated above.
-  //
-  // Return values:
-  //  - NS_OK on success;
-  //  - NS_ERROR_INVALID_ARG if 'aValue' contains an invalid value;
-  //  - NS_ERROR_NOT_IMPLEMENTED if 'aKey' is invalid;
-  //  - NS_ERROR_NOT_AVAILABLE if the getter fails to retrieve a valid value,
-  //      or if a setter fails because it requires one or more values that
-  //      could not be retrieved;
-  //  - NS_ERROR_FAILURE on unexpected internal failures.
   virtual nsresult Set(uint32_t aKey, const nsAString& aValue) = 0;
   virtual nsresult Get(uint32_t aKey, nsAString& aValue) = 0;
   virtual nsresult Set(uint32_t aKey, double aValue) = 0;
   virtual nsresult Get(uint32_t aKey, double& aValue) = 0;
   virtual nsresult Set(uint32_t aKey, int32_t aValue) = 0;
   virtual nsresult Get(uint32_t aKey, int32_t& aValue) = 0;
   virtual nsresult Set(uint32_t aKey, int64_t aValue) = 0;
   virtual nsresult Get(uint32_t aKey, int64_t& aValue) = 0;
deleted file mode 100644
--- a/dom/camera/TestGonkCameraControl.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "TestGonkCameraControl.h"
-#include "mozilla/Preferences.h"
-
-using namespace mozilla;
-
-static const char* sMethodErrorOverride = "camera.control.test.method.error";
-static const char* sAsyncErrorOverride = "camera.control.test.async.error";
-
-TestGonkCameraControl::TestGonkCameraControl(uint32_t aCameraId)
-  : nsGonkCameraControl(aCameraId)
-{
-  DOM_CAMERA_LOGA("v===== Created TestGonkCameraControl =====v\n");
-  DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
-}
-
-TestGonkCameraControl::~TestGonkCameraControl()
-{
-  DOM_CAMERA_LOGA("^===== Destroyed TestGonkCameraControl =====^\n");
-}
-
-nsresult
-TestGonkCameraControl::ForceMethodFailWithCodeInternal(const char* aFile, int aLine)
-{
-  nsresult rv =
-    static_cast<nsresult>(Preferences::GetInt(sMethodErrorOverride,
-                                              static_cast<int32_t>(NS_OK)));
-  if (NS_FAILED(rv)) {
-    DOM_CAMERA_LOGI("[%s:%d] CameraControl method error override: 0x%x\n",
-      aFile, aLine, rv);
-  }
-  return rv;
-}
-
-nsresult
-TestGonkCameraControl::ForceAsyncFailWithCodeInternal(const char* aFile, int aLine)
-{
-  nsresult rv =
-    static_cast<nsresult>(Preferences::GetInt(sAsyncErrorOverride,
-                                              static_cast<int32_t>(NS_OK)));
-  if (NS_FAILED(rv)) {
-    DOM_CAMERA_LOGI("[%s:%d] CameraControl async error override: 0x%x\n",
-      aFile, aLine, rv);
-  }
-  return rv;
-}
-
-nsresult
-TestGonkCameraControl::Start(const Configuration* aConfig)
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::Start(aConfig);
-}
-
-nsresult
-TestGonkCameraControl::StartImpl(const Configuration* aInitialConfig)
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartImpl(aInitialConfig);
-}
-
-nsresult
-TestGonkCameraControl::Stop()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::Stop();
-}
-
-nsresult
-TestGonkCameraControl::StopImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StopImpl();
-}
-
-nsresult
-TestGonkCameraControl::SetConfiguration(const Configuration& aConfig)
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::SetConfiguration(aConfig);
-}
-
-nsresult
-TestGonkCameraControl::SetConfigurationImpl(const Configuration& aConfig)
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::SetConfigurationImpl(aConfig);
-}
-
-nsresult
-TestGonkCameraControl::StartPreview()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartPreview();
-}
-
-nsresult
-TestGonkCameraControl::StartPreviewImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartImpl();
-}
-
-nsresult
-TestGonkCameraControl::StopPreview()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StopPreview();
-}
-
-nsresult
-TestGonkCameraControl::StopPreviewImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartImpl();
-}
-
-nsresult
-TestGonkCameraControl::AutoFocus()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::AutoFocus();
-}
-
-nsresult
-TestGonkCameraControl::AutoFocusImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::AutoFocusImpl();
-}
-
-nsresult
-TestGonkCameraControl::StartFaceDetection()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartFaceDetection();
-}
-
-nsresult
-TestGonkCameraControl::StartFaceDetectionImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartFaceDetectionImpl();
-}
-
-nsresult
-TestGonkCameraControl::StopFaceDetection()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StopFaceDetection();
-}
-
-nsresult
-TestGonkCameraControl::StopFaceDetectionImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StopFaceDetectionImpl();
-}
-
-nsresult
-TestGonkCameraControl::TakePicture()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::TakePicture();
-}
-
-nsresult
-TestGonkCameraControl::TakePictureImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::TakePictureImpl();
-}
-
-nsresult
-TestGonkCameraControl::StartRecording(DeviceStorageFileDescriptor* aFileDescriptor,
-                                      const StartRecordingOptions* aOptions)
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartRecording(aFileDescriptor, aOptions);
-}
-
-nsresult
-TestGonkCameraControl::StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
-                                          const StartRecordingOptions* aOptions)
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StartRecordingImpl(aFileDescriptor, aOptions);
-}
-
-nsresult
-TestGonkCameraControl::StopRecording()
-{
-  nsresult rv = ForceMethodFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StopRecording();
-}
-
-nsresult
-TestGonkCameraControl::StopRecordingImpl()
-{
-  nsresult rv = ForceAsyncFailWithCode();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return nsGonkCameraControl::StopRecordingImpl();
-}
deleted file mode 100644
--- a/dom/camera/TestGonkCameraControl.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DOM_CAMERA_TESTGONKCAMERACONTROL_H
-#define DOM_CAMERA_TESTGONKCAMERACONTROL_H
-
-#include "GonkCameraControl.h"
-
-namespace mozilla {
-
-class TestGonkCameraControl : public nsGonkCameraControl
-{
-public:
-  TestGonkCameraControl(uint32_t aCameraId);
-
-  virtual nsresult Start(const Configuration* aConfig = nullptr) MOZ_OVERRIDE;
-  virtual nsresult Stop() MOZ_OVERRIDE;
-  virtual nsresult SetConfiguration(const Configuration& aConfig) MOZ_OVERRIDE;
-  virtual nsresult StartPreview() MOZ_OVERRIDE;
-  virtual nsresult StopPreview() MOZ_OVERRIDE;
-  virtual nsresult AutoFocus() MOZ_OVERRIDE;
-  virtual nsresult StartFaceDetection() MOZ_OVERRIDE;
-  virtual nsresult StopFaceDetection() MOZ_OVERRIDE;
-  virtual nsresult TakePicture() MOZ_OVERRIDE;
-  virtual nsresult StartRecording(DeviceStorageFileDescriptor* aFileDescriptor,
-                                  const StartRecordingOptions* aOptions) MOZ_OVERRIDE;
-  virtual nsresult StopRecording() MOZ_OVERRIDE;
-
-protected:
-  virtual ~TestGonkCameraControl();
-
-  virtual nsresult StartImpl(const Configuration* aInitialConfig = nullptr) MOZ_OVERRIDE;
-  virtual nsresult StopImpl() MOZ_OVERRIDE;
-  virtual nsresult SetConfigurationImpl(const Configuration& aConfig) MOZ_OVERRIDE;
-  virtual nsresult StartPreviewImpl() MOZ_OVERRIDE;
-  virtual nsresult StopPreviewImpl() MOZ_OVERRIDE;
-  virtual nsresult AutoFocusImpl() MOZ_OVERRIDE;
-  virtual nsresult StartFaceDetectionImpl() MOZ_OVERRIDE;
-  virtual nsresult StopFaceDetectionImpl() MOZ_OVERRIDE;
-  virtual nsresult TakePictureImpl() MOZ_OVERRIDE;
-  virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
-                                      const StartRecordingOptions* aOptions = nullptr) MOZ_OVERRIDE;
-  virtual nsresult StopRecordingImpl() MOZ_OVERRIDE;
-
-  nsresult ForceMethodFailWithCodeInternal(const char* aFile, int aLine);
-  nsresult ForceAsyncFailWithCodeInternal(const char* aFile, int aLine);
-
-private:
-  TestGonkCameraControl(const TestGonkCameraControl&) MOZ_DELETE;
-  TestGonkCameraControl& operator=(const TestGonkCameraControl&) MOZ_DELETE;
-};
-
-#define ForceMethodFailWithCode() ForceMethodFailWithCodeInternal(__FILE__, __LINE__)
-#define ForceAsyncFailWithCode()  ForceAsyncFailWithCodeInternal(__FILE__, __LINE__)
-
-} // namespace mozilla
-
-#endif // DOM_CAMERA_TESTGONKCAMERACONTROL_H
--- a/dom/camera/TestGonkCameraHardware.cpp
+++ b/dom/camera/TestGonkCameraHardware.cpp
@@ -38,17 +38,17 @@ TestGonkCameraHardware::~TestGonkCameraH
   MOZ_COUNT_DTOR(TestGonkCameraHardware);
   DOM_CAMERA_LOGA("^===== Destroyed TestGonkCameraHardware =====^\n");
 }
 
 nsresult
 TestGonkCameraHardware::Init()
 {
   if (IsTestCase("init-failure")) {
-    return NS_ERROR_NOT_INITIALIZED;
+    return NS_ERROR_FAILURE;
   }
 
   return GonkCameraHardware::Init();
 }
 
 const nsCString
 TestGonkCameraHardware::TestCase()
 {
--- a/dom/camera/moz.build
+++ b/dom/camera/moz.build
@@ -29,17 +29,16 @@ if CONFIG['MOZ_B2G_CAMERA']:
     SOURCES += [
         'GonkCameraControl.cpp',
         'GonkCameraHwMgr.cpp',
         'GonkCameraManager.cpp',
         'GonkCameraParameters.cpp',
         'GonkCameraSource.cpp',
         'GonkRecorder.cpp',
         'GonkRecorderProfiles.cpp',
-        'TestGonkCameraControl.cpp',
         'TestGonkCameraHardware.cpp',
     ]
 else:
     SOURCES += [
         'FallbackCameraControl.cpp',
         'FallbackCameraManager.cpp',
     ]
 
--- a/dom/camera/test/test_bug975472.html
+++ b/dom/camera/test/test_bug975472.html
@@ -1,15 +1,14 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for bug 975472</title>
   <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="camera_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <video id="viewfinder" width="200" height="200" autoplay></video>
 <img src="#" alt="This image is going to load" id="testimage"/>
 <script class="testbody" type="text/javascript;version=1.7">
 
 var whichCamera = navigator.mozCameras.getListOfCameras()[0];
@@ -82,43 +81,43 @@ var tests = [
   },
   {
     key: "auto-focus-after-release",
     func: function testAutoFocus(camera) {
       function onSuccess(success) {
         ok(false, "autoFocus() succeeded incorrectly");
       }
       function onError(error) {
-        ok(error === "hardware-closed", "autoFocus() failed with: " + error);
+        ok(true, "autoFocus() failed correctly with: " + error);
         next();
       }
       camera.autoFocus(onSuccess, onError);
     }
   },
   {
     key: "take-picture-after-release",
     func: function testTakePicture(camera) {
       function onSuccess(picture) {
         ok(false, "takePicture() succeeded incorrectly");
       }
       function onError(error) {
-        ok(error === "hardware-closed", "takePicture() failed with: " + error);
+        ok(true, "takePicture() failed correctly with: " + error);
         next();
       }
       camera.takePicture(null, onSuccess, onError);
     }
   },
   {
     key: "start-recording-after-release",
     func: function testStartRecording(camera) {
       function onSuccess(picture) {
         ok(false, "startRecording() process succeeded incorrectly");
       }
       function onError(error) {
-        ok(error === "hardware-closed", "startRecording() failed with: " + error);
+        ok(true, "startRecording() process failed correctly with: " + error);
         next();
       }
       var recordingOptions = {
         profile: 'cif',
         rotation: 0
       };
       camera.startRecording(recordingOptions,
                             navigator.getDeviceStorage('videos'),
@@ -135,17 +134,17 @@ var tests = [
   },
   {
     key: "set-configuration-after-release",
     func: function testSetConfiguration(camera) {
       function onSuccess(picture) {
         ok(false, "setConfiguration() process succeeded incorrectly");
       }
       function onError(error) {
-        ok(error === "hardware-closed", "setConfiguration() failed with: " + error);
+        ok(true, "setConfiguration() process failed correctly with: " + error);
         next();
       }
       camera.setConfiguration(config, onSuccess, onError);
     }
   },
 ];
 
 var testGenerator = function() {
@@ -163,17 +162,17 @@ var Camera = {
   onCameraReady: function () {
     Camera.nextTest = function() {
       try {
         var t = testGenerator.next();
         info("test: " + t.key);
         t.func(Camera.cameraObj);
       } catch(e) {
         if (e instanceof StopIteration) {
-          CameraTest.end();
+          SimpleTest.finish();
         } else {
           throw e;
         }
       }
     };
     // Release the camera hardware, and call all of the asynchronous methods
     // to make sure they properly handle being in this state.
     Camera.cameraObj.release();