diff --git a/js/controller.js b/js/controller.js index 0e22a6d23..cbcca4b37 100644 --- a/js/controller.js +++ b/js/controller.js @@ -291,7 +291,7 @@ OO.plugin("Html5Skin", function (OO, _, $, W) { this.cleanUpEventListeners() this.mb = null; }, - + cleanUpEventListeners : function() { this.accessibilityControls.cleanUp() }, @@ -345,11 +345,9 @@ OO.plugin("Html5Skin", function (OO, _, $, W) { onAttributesFetched: function (event, attributes) { this.state.attributes = attributes; - //anamorphic videos - var isAnamorphic = Utils.getPropertyValue(this.state.attributes, 'provider.ots_stretch_to_output'); - if (isAnamorphic == true || isAnamorphic == "true") { - this.state.mainVideoInnerWrapper.addClass('oo-anamorphic'); - } + // This is the first point at which we know whether the video is anamorphic or not, + // apply fix if necessary + this.trySetAnamorphicFixState(true); }, onThumbnailsFetched: function (event, thumbnails) { @@ -678,12 +676,16 @@ OO.plugin("Html5Skin", function (OO, _, $, W) { this.state.isPlayingAd = false; this.state.pluginsElement.removeClass("oo-showing"); this.state.pluginsClickElement.removeClass("oo-showing"); + // Restore anamorphic videos fix after ad playback if necessary + this.trySetAnamorphicFixState(true); this.renderSkin(); }, onWillPlayAds: function(event) { OO.log("onWillPlayAds is called from event = " + event); this.state.isPlayingAd = true; + // Anamorphic videos fix should not be active during ad playback + this.trySetAnamorphicFixState(false); this.state.pluginsElement.addClass("oo-showing"); this.state.pluginsElement.css({ height: "", @@ -1472,6 +1474,32 @@ OO.plugin("Html5Skin", function (OO, _, $, W) { this.mb.publish(OO.EVENTS.SAVE_PLAYER_SETTINGS, this.state.persistentSettings); }, + /** + * Used to enable or disable the CSS workaround that prevents anamorphic videos from + * being distorted on Firefox. The fix will only be enabled if ots_stretch_to_output + * is set to true in the player attributes. + * Note that currently the oo-anamorphic class has effect only on Firefox. + * @param {boolen} enabled A value that determines whether to enable or disable the anamorphic videos CSS fix. + */ + trySetAnamorphicFixState: function(enabled) { + if (!this.state || !this.state.mainVideoInnerWrapper) { + return; + } + + if (enabled) { + var isAnamorphic = Utils.getPropertyValue(this.state.attributes, 'provider.ots_stretch_to_output'); + + // Only enable anamorphic videos fix if video actually requires it + if (isAnamorphic === true || isAnamorphic === 'true') { + this.state.mainVideoInnerWrapper.addClass('oo-anamorphic'); + OO.log('Anamorphic video fix: ON'); + } + } else { + this.state.mainVideoInnerWrapper.removeClass('oo-anamorphic'); + OO.log('Anamorphic video fix: OFF'); + } + }, + toggleClosedCaptionEnabled: function() { this.state.closedCaptionOptions.enabled = !this.state.closedCaptionOptions.enabled; this.state.persistentSettings.closedCaptionOptions['enabled'] = !!this.state.closedCaptionOptions.enabled; diff --git a/package.json b/package.json index 9a0d50735..8f9d17320 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "react-addons-test-utils": "0.14.7", "react-tools": "*", "reactify": "1.1.1", + "sinon": "^2.1.0", "underscore": "1.3.3", "vinyl-buffer": "^1.0.0", "vinyl-source-stream": "^1.0.0", diff --git a/tests/controller-test.js b/tests/controller-test.js index 849a29301..6bd06477b 100644 --- a/tests/controller-test.js +++ b/tests/controller-test.js @@ -8,6 +8,7 @@ jest.dontMock('underscore'); jest.dontMock('jquery'); var CONSTANTS = require('../js/constants/constants'); +var sinon = require('sinon'); /** * Mock OO @@ -197,6 +198,7 @@ OO = { displayMoreOptionsScreen: function(a) {}, closeMoreOptionsScreen: function() {}, pausedCallback: function() {}, + trySetAnamorphicFixState: function() {}, renderSkin: function() {window.isSkinRendered = true;}, cancelTimer: function() {window.isTimerCanceled = true;}, startHideControlBarTimer: function() {}, @@ -577,6 +579,57 @@ OO = { }); }); + describe('Controller testing Anamorphic videos fix', function() { + var addClassSpy = null; + var removeClassSpy = null; + var attributesParam = null; + var attributesState = JSON.parse(JSON.stringify(controllerMock.state.attributes)); + + beforeEach(function() { + attributesParam = { + provider: { + 'ots_stretch_to_output': true + } + }; + addClassSpy = sinon.spy(controllerMock.state.mainVideoInnerWrapper, 'addClass'); + removeClassSpy = sinon.spy(controllerMock.state.mainVideoInnerWrapper, 'removeClass'); + }); + + afterEach(function() { + controllerMock.state.mainVideoInnerWrapper.addClass.restore(); + controllerMock.state.mainVideoInnerWrapper.removeClass.restore(); + controllerMock.state.attributes = attributesState; + }); + + it('should apply anamorphic CSS fix when ots_stretch_to_output is true', function() { + Html5Skin.onAttributesFetched.call(controllerMock, 'customerUi', attributesParam); + Html5Skin.trySetAnamorphicFixState.call(controllerMock, true); + expect(addClassSpy.callCount).toBe(1); + expect(removeClassSpy.callCount).toBe(0); + }); + + it('should not apply anamorphic CSS fix when ots_stretch_to_output isn\'t true', function() { + attributesParam.provider = {}; + Html5Skin.onAttributesFetched.call(controllerMock, 'customerUi', attributesParam); + Html5Skin.trySetAnamorphicFixState.call(controllerMock, true); + attributesParam.provider = { 'ots_stretch_to_output': false }; + Html5Skin.onAttributesFetched.call(controllerMock, 'customerUi', attributesParam); + Html5Skin.trySetAnamorphicFixState.call(controllerMock, true); + expect(addClassSpy.callCount).toBe(0); + expect(removeClassSpy.callCount).toBe(0); + }); + + it('should disable anamorphic CSS fix when passing false', function() { + Html5Skin.onAttributesFetched.call(controllerMock, 'customerUi', attributesParam); + Html5Skin.trySetAnamorphicFixState.call(controllerMock, true); + expect(addClassSpy.callCount).toBe(1); + Html5Skin.onWillPlayAds.call(controllerMock, 'customerUi'); + Html5Skin.trySetAnamorphicFixState.call(controllerMock, false); + expect(addClassSpy.callCount).toBe(1); + expect(removeClassSpy.callCount).toBe(1); + }); + }); + //test destroy functions last Html5Skin.onEmbedCodeChanged.call(controllerMock, 'customerUi', 'RmZW4zcDo6KqkTIhn1LnowEZyUYn5Tb2', {}); Html5Skin.onAssetChanged.call(controllerMock, 'customerUi', {content: {streams: [{is_live_stream: true}], title: 'Title', posterImages: [{url:'www.ooyala.com'}]}});