From aa6e1fa38251b15f22b4bec6c72deee2e782d806 Mon Sep 17 00:00:00 2001 From: Wilson Page Date: Thu, 18 Sep 2014 17:32:16 -0700 Subject: [PATCH] Bug 1069200 - [Camera]Rapidly click take button and switch picture/video mode will cause video recording and picture mode in the same time --- apps/camera/js/config/config.js | 4 +- apps/camera/js/lib/camera/camera.js | 14 +++++- .../test/unit/lib/camera/camera_test.js | 47 +++++++++++++------ 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/apps/camera/js/config/config.js b/apps/camera/js/config/config.js index 2cd73b2cfe6b..2682157addf4 100644 --- a/apps/camera/js/config/config.js +++ b/apps/camera/js/config/config.js @@ -118,8 +118,8 @@ module.exports = { }, loadingScreen: { - takingPicture: 1500, - requestingCamera: 600, + takingPicture: 1650, + requestingCamera: 750, loadingVideo: 100 }, diff --git a/apps/camera/js/lib/camera/camera.js b/apps/camera/js/lib/camera/camera.js index dcd51f25d7dd..a256dcce3f4e 100644 --- a/apps/camera/js/lib/camera/camera.js +++ b/apps/camera/js/lib/camera/camera.js @@ -388,6 +388,11 @@ Camera.prototype.configure = function() { return; } + // In some extreme cases the mode can + // get changed and configured whilst + // video recording is in progress. + this.stopRecording(); + // Indicate 'busy' this.busy(); @@ -1407,6 +1412,7 @@ Camera.prototype.busy = function(type) { debug('busy %s', type || ''); this.isBusy = true; this.emit('busy', type); + clearTimeout(this.readyTimeout); }; /** @@ -1416,9 +1422,13 @@ Camera.prototype.busy = function(type) { * @private */ Camera.prototype.ready = function() { - debug('ready'); + var self = this; this.isBusy = false; - this.emit('ready'); + clearTimeout(this.readyTimeout); + this.readyTimeout = setTimeout(function() { + debug('ready'); + self.emit('ready'); + }, 150); }; }); diff --git a/apps/camera/test/unit/lib/camera/camera_test.js b/apps/camera/test/unit/lib/camera/camera_test.js index c58373b5a7e1..3bbcb4f656c5 100644 --- a/apps/camera/test/unit/lib/camera/camera_test.js +++ b/apps/camera/test/unit/lib/camera/camera_test.js @@ -60,6 +60,7 @@ suite('lib/camera/camera', function() { this.storage = this.options.storage; this.camera = new this.Camera(this.options); this.sandbox.spy(this.camera, 'ready'); + this.sandbox.spy(this.camera, 'busy'); this.sandbox.spy(this.camera, 'emit'); this.sandbox.spy(this.camera, 'once'); }); @@ -616,11 +617,10 @@ suite('lib/camera/camera', function() { suite('Camera#onPreviewStateChange()', function() { setup(function() { - this.camera = new this.Camera(); - sinon.stub(this.camera, 'emit'); + }); - test('Should fire \'busy\' event if \'stopped\' or \'paused\'', function() { + test('It fires \'busy\' event if \'stopped\' or \'paused\'', function() { this.camera.onPreviewStateChange('stopped'); assert.ok(this.camera.emit.calledWith('busy')); this.camera.emit.reset(); @@ -629,13 +629,13 @@ suite('lib/camera/camera', function() { assert.ok(this.camera.emit.calledWith('busy')); }); - test('Should not fire \'ready\' event for all other states', function() { + test('It fires \'ready\' event for all other states', function() { this.camera.onPreviewStateChange('something else'); - assert.ok(this.camera.emit.calledWith('ready')); - this.camera.emit.reset(); + sinon.assert.called(this.camera.ready); + this.camera.ready.reset(); this.camera.onPreviewStateChange('other'); - assert.ok(this.camera.emit.calledWith('ready')); + sinon.assert.called(this.camera.ready); }); }); @@ -737,11 +737,10 @@ suite('lib/camera/camera', function() { this.camera.selectedCamera = 'back'; }); - test('Should emit a \'busy\', then \'ready\' event', function(done) { - navigator.mozCameras.getCamera.callsArgWithAsync(2, this.mozCamera); + test('Should emit a \'busy\', then \'ready\' event', function() { + navigator.mozCameras.getCamera.callsArgWith(2, this.mozCamera); this.camera.requestCamera(); - sinon.assert.calledWith(this.camera.emit, 'busy'); - this.camera.on('ready', done); + assert.isTrue(this.camera.busy.calledBefore(this.camera.ready)); }); test('Should call `navigator.mozCameras.getCamera()` with currently selected camera', function() { @@ -873,7 +872,7 @@ suite('lib/camera/camera', function() { sinon.assert.notCalled(this.mozCamera.setConfiguration); this.camera.ready(); - this.clock.tick(1); + this.clock.tick(151); sinon.assert.called(this.mozCamera.setConfiguration); sinon.assert.calledWith(this.camera.emit, 'configured'); @@ -893,7 +892,6 @@ suite('lib/camera/camera', function() { }); test('Should flag as busy, then ready', function() { - var self = this; // Use async for this case this.mozCamera.setConfiguration = sinon.stub(); @@ -910,8 +908,8 @@ suite('lib/camera/camera', function() { // Manually call the callback onSuccess(); - assert.isFalse(self.camera.isBusy); - sinon.assert.calledWith(self.camera.emit, 'ready'); + assert.isFalse(this.camera.isBusy); + sinon.assert.called(this.camera.ready); }); test('Should abort if `mozCamera` has since been released', function() { @@ -930,6 +928,13 @@ suite('lib/camera/camera', function() { assert.isFalse(this.camera.emit.calledWith('configured')); }); + + test('It stops any recording that make be in progress', function() { + sinon.stub(this.camera, 'stopRecording'); + this.camera.configure(); + this.clock.tick(1); + sinon.assert.called(this.camera.stopRecording); + }); }); suite('Camera#release()', function() { @@ -1204,4 +1209,16 @@ suite('lib/camera/camera', function() { sinon.assert.called(this.camera.setThumbnailSize); }); }); + + suite('Camera#busy()', function() { + setup(function() { + this.camera.readyTimeout = ''; + this.sandbox.stub(window, 'clearTimeout'); + }); + + test('It clears the ready timeout', function() { + this.camera.busy(); + sinon.assert.calledWith(window.clearTimeout, ''); + }); + }); });