From 49e2dcf4070e027ce6f3c759175d972bf4f93165 Mon Sep 17 00:00:00 2001 From: Andrew Osmond Date: Tue, 17 Mar 2015 13:01:24 -0400 Subject: [PATCH] Bug 1144211 - Improve code coverage of camera mochitests. r=mikeh --- dom/camera/CameraTestHardware.js | 12 +- dom/camera/DOMCameraControl.cpp | 4 +- dom/camera/FallbackCameraPlatform.h | 4 + dom/camera/GonkCameraControl.cpp | 12 +- dom/camera/TestGonkCameraHardware.cpp | 26 + dom/camera/TestGonkCameraHardware.h | 1 + dom/camera/test/camera_common.js | 28 +- dom/camera/test/mochitest.ini | 19 +- dom/camera/test/test_bug1022766.html | 63 -- dom/camera/test/test_bug1037322.html | 69 --- dom/camera/test/test_bug1099390.html | 55 -- ...lures.html => test_camera_auto_focus.html} | 125 +++- .../test/test_camera_bad_initial_config.html | 44 -- .../test/test_camera_configuration.html | 545 ++++++++++++++++++ ...n.html => test_camera_face_detection.html} | 127 +++- .../test/test_camera_fake_parameters.html | 146 ++++- ..._camera_hardware_auto_focus_moving_cb.html | 73 --- dom/camera/test/test_camera_record.html | 75 +++ ...ug975472.html => test_camera_release.html} | 60 ++ dom/camera/test/test_camera_take_picture.html | 165 ++++++ 20 files changed, 1286 insertions(+), 367 deletions(-) delete mode 100644 dom/camera/test/test_bug1022766.html delete mode 100644 dom/camera/test/test_bug1037322.html delete mode 100644 dom/camera/test/test_bug1099390.html rename dom/camera/test/{test_camera_hardware_failures.html => test_camera_auto_focus.html} (62%) delete mode 100644 dom/camera/test/test_camera_bad_initial_config.html create mode 100644 dom/camera/test/test_camera_configuration.html rename dom/camera/test/{test_camera_hardware_face_detection.html => test_camera_face_detection.html} (67%) delete mode 100644 dom/camera/test/test_camera_hardware_auto_focus_moving_cb.html create mode 100644 dom/camera/test/test_camera_record.html rename dom/camera/test/{test_bug975472.html => test_camera_release.html} (75%) create mode 100644 dom/camera/test/test_camera_take_picture.html diff --git a/dom/camera/CameraTestHardware.js b/dom/camera/CameraTestHardware.js index e077271108f..8c5a9108590 100644 --- a/dom/camera/CameraTestHardware.js +++ b/dom/camera/CameraTestHardware.js @@ -74,9 +74,15 @@ MozCameraTestHardware.prototype = { }, dispatchEvent: function(evt) { - if (this._handler) { - this._handler.handleEvent(evt); - } + var self = this; + /* We should not dispatch the event in the current thread + context because it may be directly from a driver call + and we could hit a deadlock situation. */ + this._window.setTimeout(function() { + if (self._handler) { + self._handler.handleEvent(evt); + } + }, 0); }, reset: function(aWindow) { diff --git a/dom/camera/DOMCameraControl.cpp b/dom/camera/DOMCameraControl.cpp index 94571f74555..da829b6d07e 100755 --- a/dom/camera/DOMCameraControl.cpp +++ b/dom/camera/DOMCameraControl.cpp @@ -958,8 +958,10 @@ nsDOMCameraControl::TakePicture(const CameraPictureOptions& aOptions, if (s.width && s.height) { mCameraControl->Set(CAMERA_PARAM_PICTURE_SIZE, s); } + if (!aOptions.mFileFormat.IsEmpty()) { + mCameraControl->Set(CAMERA_PARAM_PICTURE_FILEFORMAT, aOptions.mFileFormat); + } mCameraControl->Set(CAMERA_PARAM_PICTURE_ROTATION, aOptions.mRotation); - mCameraControl->Set(CAMERA_PARAM_PICTURE_FILEFORMAT, aOptions.mFileFormat); mCameraControl->Set(CAMERA_PARAM_PICTURE_DATETIME, aOptions.mDateTime); mCameraControl->SetLocation(p); } diff --git a/dom/camera/FallbackCameraPlatform.h b/dom/camera/FallbackCameraPlatform.h index 53c4da752f5..0e5b10dc009 100644 --- a/dom/camera/FallbackCameraPlatform.h +++ b/dom/camera/FallbackCameraPlatform.h @@ -269,6 +269,8 @@ namespace android { return 320; } else if (strcmp(aParameter, "vid.height") == 0) { return 240; + } else if (strcmp(aParameter, "vid.fps") == 0) { + return 30; } return 0; case CAMCORDER_QUALITY_HIGH: @@ -277,6 +279,8 @@ namespace android { return 640; } else if (strcmp(aParameter, "vid.height") == 0) { return 480; + } else if (strcmp(aParameter, "vid.fps") == 0) { + return 30; } return 0; default: diff --git a/dom/camera/GonkCameraControl.cpp b/dom/camera/GonkCameraControl.cpp index 85f8ec9e193..3e1eee782cc 100644 --- a/dom/camera/GonkCameraControl.cpp +++ b/dom/camera/GonkCameraControl.cpp @@ -1255,7 +1255,7 @@ nsGonkCameraControl::StopRecordingImpl() class RecordingComplete : public nsRunnable { public: - RecordingComplete(DeviceStorageFile* aFile) + RecordingComplete(already_AddRefed aFile) : mFile(aFile) { } @@ -1285,6 +1285,11 @@ nsGonkCameraControl::StopRecordingImpl() mRecorder->stop(); mRecorder = nullptr; +#else + if (!mVideoFile) { + return NS_OK; + } +#endif OnRecorderStateChange(CameraControlListener::kRecorderStopped); { @@ -1299,10 +1304,7 @@ nsGonkCameraControl::StopRecordingImpl() } // notify DeviceStorage that the new video file is closed and ready - return NS_DispatchToMainThread(new RecordingComplete(mVideoFile)); -#else - return NS_OK; -#endif + return NS_DispatchToMainThread(new RecordingComplete(mVideoFile.forget())); } nsresult diff --git a/dom/camera/TestGonkCameraHardware.cpp b/dom/camera/TestGonkCameraHardware.cpp index 9932fd5c561..34bac5f9675 100644 --- a/dom/camera/TestGonkCameraHardware.cpp +++ b/dom/camera/TestGonkCameraHardware.cpp @@ -412,6 +412,32 @@ TestGonkCameraHardware::AutoFocus() return OK; } +int +TestGonkCameraHardware::CancelAutoFocus() +{ + class Delegate : public ControlMessage + { + public: + Delegate(TestGonkCameraHardware* aTestHw) + : ControlMessage(aTestHw) + { } + + protected: + NS_IMETHOD + RunImpl() override + { + return mJSTestWrapper->CancelAutoFocus(); + } + }; + + DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__); + nsresult rv = WaitWhileRunningOnMainThread(new Delegate(this)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return UNKNOWN_ERROR; + } + return OK; +} + int TestGonkCameraHardware::StartFaceDetection() { diff --git a/dom/camera/TestGonkCameraHardware.h b/dom/camera/TestGonkCameraHardware.h index ef15265dd02..0782c7f8c80 100644 --- a/dom/camera/TestGonkCameraHardware.h +++ b/dom/camera/TestGonkCameraHardware.h @@ -33,6 +33,7 @@ class TestGonkCameraHardware : public android::GonkCameraHardware public: virtual nsresult Init() override; virtual int AutoFocus() override; + virtual int CancelAutoFocus() override; virtual int StartFaceDetection() override; virtual int StopFaceDetection() override; virtual int TakePicture() override; diff --git a/dom/camera/test/camera_common.js b/dom/camera/test/camera_common.js index 110e8c5948e..89ee2c5a633 100644 --- a/dom/camera/test/camera_common.js +++ b/dom/camera/test/camera_common.js @@ -103,6 +103,14 @@ CameraTestSuite.prototype = { _lowMemSet: false, _reloading: false, + _setupPermission: function(permission) { + if (!SpecialPowers.hasPermission(permission, document)) { + info("requesting " + permission + " permission"); + SpecialPowers.addPermission(permission, true, document); + this._reloading = true; + } + }, + /* Returns a promise which is resolved when the test suite is ready to be executing individual test cases. One may provide the expected hardware type here if desired; the default is to use the JS test @@ -111,24 +119,28 @@ CameraTestSuite.prototype = { /* Depending on how we run the mochitest, we may not have the necessary permissions yet. If we do need to request them, then we have to reload the window to ensure the reconfiguration propogated properly. */ - if (!SpecialPowers.hasPermission("camera", document)) { - info("requesting camera permission"); - this._reloading = true; - SpecialPowers.addPermission("camera", true, document); + this._setupPermission("camera"); + this._setupPermission("device-storage:videos"); + this._setupPermission("device-storage:videos-create"); + this._setupPermission("device-storage:videos-write"); + + if (this._reloading) { window.location.reload(); return Promise.reject(); } - info("has camera permission"); + info("has necessary permissions"); if (!isDefined(hwType)) { hwType = 'hardware'; } this._hwType = hwType; return new Promise(function(resolve, reject) { - SpecialPowers.pushPrefEnv({'set': [['camera.control.test.permission', true]]}, function() { - SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() { - resolve(); + SpecialPowers.pushPrefEnv({'set': [['device.storage.prompt.testing', true]]}, function() { + SpecialPowers.pushPrefEnv({'set': [['camera.control.test.permission', true]]}, function() { + SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() { + resolve(); + }); }); }); }); diff --git a/dom/camera/test/mochitest.ini b/dom/camera/test/mochitest.ini index e08690af471..a255a4117df 100644 --- a/dom/camera/test/mochitest.ini +++ b/dom/camera/test/mochitest.ini @@ -1,21 +1,20 @@ [DEFAULT] support-files = camera_common.js +[test_camera_configuration.html] +[test_camera_release.html] +[test_camera_auto_focus.html] +[test_camera_take_picture.html] +[test_camera_record.html] +skip-if = toolkit == 'gonk' +[test_camera_face_detection.html] +[test_camera_fake_parameters.html] +[test_camera_hardware_init_failure.html] [test_camera.html] skip-if = toolkit != 'gonk' [test_camera_2.html] skip-if = toolkit != 'gonk' [test_camera_3.html] skip-if = toolkit != 'gonk' -[test_camera_hardware_init_failure.html] -[test_camera_hardware_failures.html] -[test_bug975472.html] -[test_camera_fake_parameters.html] -[test_camera_hardware_face_detection.html] -[test_camera_hardware_auto_focus_moving_cb.html] -[test_bug1022766.html] -[test_bug1037322.html] -[test_bug1099390.html] [test_bug1104913.html] skip-if = toolkit != 'gonk' -[test_camera_bad_initial_config.html] diff --git a/dom/camera/test/test_bug1022766.html b/dom/camera/test/test_bug1022766.html deleted file mode 100644 index 924edd03531..00000000000 --- a/dom/camera/test/test_bug1022766.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - Test for bug 1022766 - - - - - - - -This image is going to load - - - - diff --git a/dom/camera/test/test_bug1037322.html b/dom/camera/test/test_bug1037322.html deleted file mode 100644 index e304fa60607..00000000000 --- a/dom/camera/test/test_bug1037322.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - Test for bug 1037322 - - - - - - - -This image is going to load - - - - diff --git a/dom/camera/test/test_bug1099390.html b/dom/camera/test/test_bug1099390.html deleted file mode 100644 index 56646cb709b..00000000000 --- a/dom/camera/test/test_bug1099390.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - Test for bug 1099390 - - - - - - - -This image is going to load - - - - diff --git a/dom/camera/test/test_camera_hardware_failures.html b/dom/camera/test/test_camera_auto_focus.html similarity index 62% rename from dom/camera/test/test_camera_hardware_failures.html rename to dom/camera/test/test_camera_auto_focus.html index e554d04b49f..b252b0a2d1d 100644 --- a/dom/camera/test/test_camera_hardware_failures.html +++ b/dom/camera/test/test_camera_auto_focus.html @@ -1,20 +1,15 @@ - - Bug 940424 - Test camera hardware API failure handling + Test for auto focus - Mozilla Bug 940424 - - This image is going to load - + +This image is going to load - - - - - - -This image is going to load - - - - diff --git a/dom/camera/test/test_camera_configuration.html b/dom/camera/test/test_camera_configuration.html new file mode 100644 index 00000000000..9135bf34134 --- /dev/null +++ b/dom/camera/test/test_camera_configuration.html @@ -0,0 +1,545 @@ + + + + Test for camera configuration + + + + + + + +This image is going to load + + + + diff --git a/dom/camera/test/test_camera_hardware_face_detection.html b/dom/camera/test/test_camera_face_detection.html similarity index 67% rename from dom/camera/test/test_camera_hardware_face_detection.html rename to dom/camera/test/test_camera_face_detection.html index fa2e7ec9c78..d2e4c6c59ce 100644 --- a/dom/camera/test/test_camera_hardware_face_detection.html +++ b/dom/camera/test/test_camera_face_detection.html @@ -92,8 +92,93 @@ function compareFace(aFace, expected) var suite = new CameraTestSuite(); +suite.test('face-detection-op', function() { + function start(p) { + return new Promise(function(resolve, reject) { + suite.hw.attach({ + startFaceDetection: function() { + ok(true, "startFaceDetection() requested"); + resolve(); + } + }); + try { + suite.camera.startFaceDetection(); + ok(true, "startFaceDetection() succeeded"); + } catch(e) { + ok(false, "startFaceDetection() failed with: " + e.name); + resolve(); + } + }); + } + + function stop(p) { + return new Promise(function(resolve, reject) { + suite.hw.attach({ + stopFaceDetection: function() { + ok(true, "stopFaceDetection() requested"); + resolve(); + } + }); + try { + suite.camera.stopFaceDetection(); + ok(true, "stopFaceDetection() succeeded"); + } catch(e) { + ok(false, "stopFaceDetection() failed with: " + e.name); + resolve(); + } + }); + } + + function startFailure(p) { + return new Promise(function(resolve, reject) { + suite.hw.attach({ + startFaceDetection: function() { + ok(true, "startFaceDetection() requested and failed"); + resolve(); + throw SpecialPowers.Cr.NS_ERROR_FAILURE; + } + }); + try { + suite.camera.startFaceDetection(); + ok(true, "startFaceDetection() succeeded and error swallowed"); + } catch(e) { + ok(false, "startFaceDetection() failed with: " + e.name); + resolve(); + } + }); + } + + function stopFailure(p) { + return new Promise(function(resolve, reject) { + suite.hw.attach({ + stopFaceDetection: function() { + ok(true, "stopFaceDetection() requested and failed"); + resolve(); + throw SpecialPowers.Cr.NS_ERROR_FAILURE; + } + }); + try { + suite.camera.stopFaceDetection(); + ok(true, "stopFaceDetection() succeeded and error swallowed"); + } catch(e) { + ok(false, "stopFaceDetection() failed with: " + e.name); + resolve(); + } + }); + } + + return suite.getCamera() + .then(start, suite.rejectGetCamera) + .then(stop) + .then(startFailure) + .then(stopFailure); +}); + suite.test('face-detection', function() { - function detectFace(msg, expected) { + function detectFace(msg, given, expected) { + if (expected === undefined) { + expected = given; + } var sync = new Promise(function(resolve, reject) { function onEvent(evt) { try { @@ -108,7 +193,7 @@ suite.test('face-detection', function() { suite.camera.addEventListener('facesdetected', onEvent); }); - suite.hw.fireFacesDetected(expected); + suite.hw.fireFacesDetected(given); return sync; } @@ -220,11 +305,47 @@ suite.test('face-detection', function() { ); } + function detectOneFaceExcessScore() { + return detectFace('one-face-excess-score', + { + faces: [ { + id: 1, + score: 120, + bounds: { + left: 3, + top: 4, + right: 5, + bottom: 6 + }, + leftEye: null, + rightEye: null, + mouth: null + } ] + }, + { + faces: [ { + id: 1, + score: 100, + bounds: { + left: 3, + top: 4, + right: 5, + bottom: 6 + }, + leftEye: null, + rightEye: null, + mouth: null + } ] + } + ); + } + return suite.getCamera() .then(detectOneFace, suite.rejectGetCamera) .then(detectTwoFaces) .then(detectOneFaceNoFeatures) - .then(detectNoFaces); + .then(detectNoFaces) + .then(detectOneFaceExcessScore); }); suite.setup() diff --git a/dom/camera/test/test_camera_fake_parameters.html b/dom/camera/test/test_camera_fake_parameters.html index a2b7b22a401..da45ce7b013 100644 --- a/dom/camera/test/test_camera_fake_parameters.html +++ b/dom/camera/test/test_camera_fake_parameters.html @@ -132,6 +132,133 @@ suite.test('fake-low-memory-platform', function() { .then(resolve, suite.rejectGetCamera); }); +suite.test('fake-effects', function() { + var supportedValues = ['none', 'mono', 'negative', 'solarize', 'sepia', 'posterize', 'whiteboard', 'blackboard', 'aqua']; + suite.hw.params['effect'] = 'none'; + suite.hw.params['effect-values'] = supportedValues.join(','); + + function resolve(p) { + var cap = suite.camera.capabilities; + ok(cap.effects.length == supportedValues.length, "Effects length = " + cap.effects.length); + + // make sure expected values are present + supportedValues.forEach(function(val) { + ok(cap.effects.indexOf(val) != -1, "Effect '" + val + "' is present"); + }); + } + + return suite.getCamera() + .then(resolve, suite.rejectGetCamera); +}); + +suite.test('fake-flash-modes', function() { + var supportedValues = ['off', 'auto', 'on', 'red-eye', 'torch']; + suite.hw.params['flash-mode'] = 'auto'; + suite.hw.params['flash-mode-values'] = supportedValues.join(','); + + function resolve(p) { + var cam = suite.camera; + var cap = cam.capabilities; + ok(cap.flashModes.length == supportedValues.length, "Flash modes length = " + cap.flashModes.length); + + // make sure expected values are present + supportedValues.forEach(function(val) { + ok(cap.flashModes.indexOf(val) != -1, "Flash mode '" + val + "' is present"); + }); + + // test setters/getters + cap.flashModes.forEach(function(val, index) { + cam.flashMode = val; + ok(cam.flashMode === val, + "Flash Mode [" + index + "] = " + val + ", cam.flashMode = " + cam.flashMode); + }); + } + + return suite.getCamera() + .then(resolve, suite.rejectGetCamera); +}); + +suite.test('fake-focus-modes', function() { + var supportedValues = ['auto', 'infinity', 'macro', 'fixed', 'edof', 'continuous-video']; + suite.hw.params['focus-mode'] = 'auto'; + suite.hw.params['focus-mode-values'] = supportedValues.join(','); + + function resolve(p) { + var cam = suite.camera; + var cap = cam.capabilities; + ok(cap.focusModes.length == supportedValues.length, "Focus modes length = " + cap.focusModes.length); + + // make sure expected values are present + supportedValues.forEach(function(val) { + ok(cap.focusModes.indexOf(val) != -1, "Focus mode '" + val + "' is present"); + }); + + // test setters/getters + cap.focusModes.forEach(function(val, index) { + cam.focusMode = val; + ok(cam.focusMode === val, + "Focus Mode [" + index + "] = " + val + ", cam.focusMode = " + cam.focusMode); + }); + } + + return suite.getCamera() + .then(resolve, suite.rejectGetCamera); +}); + +suite.test('fake-white-balance-modes', function() { + var supportedValues = ['auto', 'incandescent', 'fluorescent', 'warm-fluorescent', 'daylight', 'cloudy-daylight', 'twilight', 'shade']; + suite.hw.params['whitebalance'] = 'auto'; + suite.hw.params['whitebalance-values'] = supportedValues.join(','); + + function resolve(p) { + var cam = suite.camera; + var cap = cam.capabilities; + ok(cap.whiteBalanceModes.length == supportedValues.length, "White balance modes length = " + cap.whiteBalanceModes.length); + + // make sure expected values are present + supportedValues.forEach(function(val) { + ok(cap.whiteBalanceModes.indexOf(val) != -1, "White balance mode '" + val + "' is present"); + }); + + // test setters/getters + cap.whiteBalanceModes.forEach(function(val, index) { + cam.whiteBalanceMode = val; + ok(cam.whiteBalanceMode === val, + "White balance mode [" + index + "] = " + val + ", cam.whiteBalanceMode = " + cam.whiteBalanceMode); + }); + } + + return suite.getCamera() + .then(resolve, suite.rejectGetCamera); +}); + +suite.test('fake-video-sizes', function() { + var supportedValues = ['auto', 'incandescent', 'fluorescent', 'warm-fluorescent', 'daylight', 'cloudy-daylight', 'twilight', 'shade']; + suite.hw.params['whitebalance'] = 'auto'; + suite.hw.params['whitebalance-values'] = supportedValues.join(','); + + function resolve(p) { + var cam = suite.camera; + var cap = cam.capabilities; + ok(cap.whiteBalanceModes.length == supportedValues.length, "White balance modes length = " + cap.whiteBalanceModes.length); + + // make sure expected values are present + supportedValues.forEach(function(val) { + ok(cap.whiteBalanceModes.indexOf(val) != -1, "White balance mode '" + val + "' is present"); + }); + + // test setters/getters + cap.whiteBalanceModes.forEach(function(val, index) { + cam.whiteBalanceMode = val; + ok(cam.whiteBalanceMode === val, + "White balance mode [" + index + "] = " + val + ", cam.whiteBalanceMode = " + cam.whiteBalanceMode); + }); + } + + return suite.getCamera() + .then(resolve, suite.rejectGetCamera); +}); + suite.test('fake-iso', function() { suite.hw.params['iso'] = 'auto'; suite.hw.params['iso-values'] = 'auto,ISO_HJR,ISO100,foo,ISObar,ISO150moz,ISO200,400,ISO800,1600'; @@ -158,9 +285,9 @@ suite.test('fake-iso', function() { // test setters/getters for individual ISO modes cap.isoModes.forEach(function(iso, index) { - cam.iso = iso; - ok(cam.iso === iso, - "ISO[" + index + "] = " + iso + ", cam.iso = " + cam.iso); + cam.isoMode = iso; + ok(cam.isoMode === iso, + "ISO[" + index + "] = " + iso + ", cam.iso = " + cam.isoMode); }); } @@ -168,6 +295,19 @@ suite.test('fake-iso', function() { .then(resolve, suite.rejectGetCamera); }); +suite.test('fake-faces-detected', function() { + suite.hw.params['max-num-detected-faces-hw'] = '5'; + + function resolve(p) { + var cap = suite.camera.capabilities; + + ok(cap.maxDetectedFaces == 5, "maxDetectedFaces = " + cap.maxDetectedFaces); + } + + return suite.getCamera() + .then(resolve, suite.rejectGetCamera); +}); + suite.test('fake-metering-areas', function() { suite.hw.params['max-num-metering-areas'] = '1'; diff --git a/dom/camera/test/test_camera_hardware_auto_focus_moving_cb.html b/dom/camera/test/test_camera_hardware_auto_focus_moving_cb.html deleted file mode 100644 index b977cfdba21..00000000000 --- a/dom/camera/test/test_camera_hardware_auto_focus_moving_cb.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - Bug 965421 - Test camera hardware API for Auto focus moving Callback - - - - - - - Mozilla Bug 965421 - - This image is going to load - - - - - diff --git a/dom/camera/test/test_camera_record.html b/dom/camera/test/test_camera_record.html new file mode 100644 index 00000000000..d9d43bf2263 --- /dev/null +++ b/dom/camera/test/test_camera_record.html @@ -0,0 +1,75 @@ + + + + Test Camera Recording + + + + + + + + This image is going to load + + + + + diff --git a/dom/camera/test/test_bug975472.html b/dom/camera/test/test_camera_release.html similarity index 75% rename from dom/camera/test/test_bug975472.html rename to dom/camera/test/test_camera_release.html index 0a2121fdc7e..9edaf05a037 100644 --- a/dom/camera/test/test_bug975472.html +++ b/dom/camera/test/test_camera_release.html @@ -18,6 +18,39 @@ function cameraRelease(p) { return suite.camera.release(); } +suite.test('release-close-event', function() { + // bug 1099390 + function release(p) { + return new Promise(function(resolve, reject) { + var gotCloseEvent = false; + var gotReleasePromise = false; + + var onClosed = function(e) { + suite.camera.removeEventListener('close', onClosed); + ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent); + ok(e.reason === "HardwareReleased", "'close' event reason is: " + e.reason); + gotCloseEvent = true; + if (gotReleasePromise) { + resolve(); + } + }; + + suite.camera.addEventListener('close', onClosed); + + suite.camera.release().then(function(p) { + ok(true, "released camera"); + gotReleasePromise = true; + if (gotCloseEvent) { + resolve(); + } + }).catch(reject); + }); + } + + return suite.getCamera() + .then(release, suite.rejectGetCamera); +}); + suite.test('release-after-release', function() { return suite.getCamera() .then(cameraRelease, suite.rejectGetCamera) @@ -157,6 +190,33 @@ suite.test('stop-recording-after-release', function() { .then(stopRecording, suite.rejectRelease); }); +suite.test('face-detection-after-release', function() { + function startFaceDetection(p) { + try { + suite.camera.startFaceDetection(); + ok(false, "startFaceDetection() should have failed"); + } catch(e) { + ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE, + "startFaceDetection() failed with: " + e.name); + } + } + + function stopFaceDetection(p) { + try { + suite.camera.stopFaceDetection(); + ok(false, "stopFaceDetection() should have failed"); + } catch(e) { + ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE, + "stopFaceDetection() failed with: " + e.name); + } + } + + return suite.getCamera() + .then(cameraRelease, suite.rejectGetCamera) + .then(startFaceDetection, suite.rejectRelease) + .then(stopFaceDetection); +}); + suite.test('set-configuration-after-release', function() { function configure(p) { return suite.camera.setConfiguration(null); diff --git a/dom/camera/test/test_camera_take_picture.html b/dom/camera/test/test_camera_take_picture.html new file mode 100644 index 00000000000..e302a202fb2 --- /dev/null +++ b/dom/camera/test/test_camera_take_picture.html @@ -0,0 +1,165 @@ + + + + + Bug 940424 - Test camera hardware API failure handling + + + + + + + Mozilla Bug 940424 + + This image is going to load + + + + +