Backed out changeset a73dece39b01 (bug 985496) for mochitest-5 orange
authorWes Kocher <wkocher@mozilla.com>
Fri, 25 Apr 2014 16:15:37 -0700
changeset 198796 5d6a3571f1abd8dd38973ee29c2a894acfd8a196
parent 198795 33a615530ab17a6068f45a7ead9ec1f25ef01774
child 198797 d0892b46689463b1f5fd76e4f502b8317895fd73
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs985496
milestone31.0a1
backs outa73dece39b0129e53040f29eed4f377ddf387dee
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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();