From 5a7a5da1fd70fdcb99aad1f368309075c5910250 Mon Sep 17 00:00:00 2001 From: Brian Clifton Date: Mon, 31 Jul 2017 15:31:12 -0700 Subject: [PATCH] Merge pull request #10178 from brave/autoplay_refactor Autoplay refactoring --- app/browser/reducers/autoplayReducer.js | 74 ++- app/renderer/components/frame/frame.js | 1 + js/actions/appActions.js | 11 + js/constants/appConstants.js | 1 + js/state/contentSettings.js | 3 +- .../bravery-components/notificationBarTest.js | 568 ++++++++++++------ test/fixtures/auto-click-play.html | 29 + .../browser/reducers/autoplayReducerTest.js | 292 +++++++++ 8 files changed, 752 insertions(+), 227 deletions(-) create mode 100644 test/fixtures/auto-click-play.html create mode 100644 test/unit/app/browser/reducers/autoplayReducerTest.js diff --git a/app/browser/reducers/autoplayReducer.js b/app/browser/reducers/autoplayReducer.js index d18c14f06c0..21f856d342b 100644 --- a/app/browser/reducers/autoplayReducer.js +++ b/app/browser/reducers/autoplayReducer.js @@ -7,31 +7,26 @@ const appConstants = require('../../../js/constants/appConstants') const {makeImmutable} = require('../../common/state/immutableUtil') const {ipcMain, webContents} = require('electron') -const AppStore = require('../../../js/stores/appStore') const siteSettings = require('../../../js/state/siteSettings') -const settings = require('../../../js/constants/settings') const appActions = require('../../../js/actions/appActions') const {getOrigin} = require('../../../js/state/siteUtil') const locale = require('../../locale') const messages = require('../../../js/constants/messages') -const getSetting = require('../../../js/settings').getSetting -const {autoplayOption} = require('../../common/constants/settingsEnums') -const showAutoplayMessageBox = (tabId) => { +let notificationCallbacks = [] + +const showAutoplayMessageBox = (state, tabId) => { const tab = webContents.fromTabID(tabId) if (!tab || tab.isDestroyed()) { return } const location = tab.getURL() const origin = getOrigin(location) - if (getSetting(settings.AUTOPLAY_MEDIA) === autoplayOption.ALWAYS_ALLOW) { - appActions.changeSiteSetting(origin, 'autoplay', true) - return - } - const originSettings = siteSettings.getSiteSettingsForURL(AppStore.getState().get('siteSettings'), origin) + const originSettings = siteSettings.getSiteSettingsForURL(state.get('siteSettings'), origin) if (originSettings && originSettings.get('autoplay') === false) { return } + const message = locale.translation('allowAutoplay', {origin}) appActions.showNotification({ @@ -46,33 +41,60 @@ const showAutoplayMessageBox = (tabId) => { } }) - ipcMain.once(messages.NOTIFICATION_RESPONSE, (e, msg, buttonIndex, persist) => { - if (msg === message) { - appActions.hideNotification(message) - if (buttonIndex === 0) { - appActions.changeSiteSetting(origin, 'autoplay', true) - if (tab && !tab.isDestroyed()) { - tab.reload() - tab.on('destroyed', function temporaryAllow (e) { - if (!persist) { - appActions.removeSiteSetting(origin, 'autoplay') + if (!notificationCallbacks[tabId]) { + notificationCallbacks[tabId] = (e, msg, buttonIndex, persist) => { + if (msg === message) { + appActions.hideNotification(message) + if (buttonIndex === 0) { + appActions.changeSiteSetting(origin, 'autoplay', true) + if (tab && !tab.isDestroyed()) { + tab.reload() + const temporaryAllow = (e) => { + tab.removeListener('media-started-playing', temporaryAllow) + if (!persist) { + appActions.removeSiteSetting(origin, 'autoplay') + } } - }) + tab.on('media-started-playing', temporaryAllow) + } + } else { + if (persist) { + appActions.changeSiteSetting(origin, 'autoplay', false) + } } - } else { - if (persist) { - appActions.changeSiteSetting(origin, 'autoplay', false) + if (notificationCallbacks[tabId]) { + ipcMain.removeListener(messages.NOTIFICATION_RESPONSE, notificationCallbacks[tabId]) + delete notificationCallbacks[tabId] } } } - }) + ipcMain.on(messages.NOTIFICATION_RESPONSE, notificationCallbacks[tabId]) + } +} + +const hideAutoplayMessageBox = (tabId) => { + const tab = webContents.fromTabID(tabId) + if (!tab || tab.isDestroyed()) { + return + } + const location = tab.getURL() + const origin = getOrigin(location) + const message = locale.translation('allowAutoplay', {origin}) + appActions.hideNotification(message) + if (notificationCallbacks[tabId]) { + ipcMain.removeListener(messages.NOTIFICATION_RESPONSE, notificationCallbacks[tabId]) + delete notificationCallbacks[tabId] + } } const autoplayReducer = (state, action, immutableAction) => { action = immutableAction || makeImmutable(action) switch (action.get('actionType')) { case appConstants.APP_AUTOPLAY_BLOCKED: - showAutoplayMessageBox(action.get('tabId')) + showAutoplayMessageBox(state, action.get('tabId')) + break + case appConstants.APP_AUTOPLAY_DISMISSED: + hideAutoplayMessageBox(action.get('tabId')) break } return state diff --git a/app/renderer/components/frame/frame.js b/app/renderer/components/frame/frame.js index 13feeebe783..0fc01ada6c4 100644 --- a/app/renderer/components/frame/frame.js +++ b/app/renderer/components/frame/frame.js @@ -762,6 +762,7 @@ class Frame extends React.Component { if (this.frame.isEmpty()) { return } + appActions.autoplayDismissed(this.props.tabId) windowActions.setAudioPlaybackActive(this.frame, true) }) this.webview.addEventListener('media-paused', ({title}) => { diff --git a/js/actions/appActions.js b/js/actions/appActions.js index 20dbdb9fb07..95c27754577 100644 --- a/js/actions/appActions.js +++ b/js/actions/appActions.js @@ -1316,6 +1316,17 @@ const appActions = { }) }, + /** + * Notifies autoplay notification can be dismissed + * @param {number} tabId - Tab id of current frame + */ + autoplayDismissed: function (tabId) { + dispatch({ + actionType: appConstants.APP_AUTOPLAY_DISMISSED, + tabId + }) + }, + /** * Handle 'save-password' event from muon */ diff --git a/js/constants/appConstants.js b/js/constants/appConstants.js index a5da269c4d0..7544de85485 100644 --- a/js/constants/appConstants.js +++ b/js/constants/appConstants.js @@ -128,6 +128,7 @@ const appConstants = { APP_ON_GO_BACK_LONG: _, APP_ON_GO_FORWARD_LONG: _, APP_AUTOPLAY_BLOCKED: _, + APP_AUTOPLAY_DISMISSED: _, APP_SAVE_PASSWORD: _, APP_UPDATE_PASSWORD: _, APP_ADD_PASSWORD: _, /** @param {Object} passwordDetail */ diff --git a/js/state/contentSettings.js b/js/state/contentSettings.js index 2cb680b41ee..e1869b696af 100644 --- a/js/state/contentSettings.js +++ b/js/state/contentSettings.js @@ -16,6 +16,7 @@ const urlParse = require('../../app/common/urlParse') const siteSettings = require('./siteSettings') const {registerUserPrefs} = require('./userPrefs') const {getSetting} = require('../settings') +const {autoplayOption} = require('../../app/common/constants/settingsEnums') const {getFlashResourceId} = require('../flash') const net = require('net') @@ -69,7 +70,7 @@ const getDefaultUserPrefContentSettings = (braveryDefaults, appSettings, appConf braveryDefaults = makeImmutable(braveryDefaults) return Immutable.fromJS({ autoplay: [{ - setting: 'block', + setting: getSetting(settings.AUTOPLAY_MEDIA) === autoplayOption.ALWAYS_ALLOW ? 'allow' : 'block', primaryPattern: '*' }], cookies: getDefault3rdPartyStorageSettings(braveryDefaults, appSettings, appConfig), diff --git a/test/bravery-components/notificationBarTest.js b/test/bravery-components/notificationBarTest.js index bec2f63cd20..9a4f93125bc 100644 --- a/test/bravery-components/notificationBarTest.js +++ b/test/bravery-components/notificationBarTest.js @@ -336,211 +336,379 @@ describe('Autoplay test', function () { yield setup(this.app.client) }) - it('default always ask and block', function * () { - const url = Brave.server.url('autoplay.html') - yield this.app.client - .tabByIndex(0) - .loadUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === '' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .waitForExist(notificationBar) - .waitUntil(function () { - return this.getText(notificationBar).then((val) => val.includes('autoplay media')) - }) - }) + describe('autoplay', function () { + it('default always ask and block', function * () { + const url = Brave.server.url('autoplay.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + }) - it('always allow', function * () { - const url = Brave.server.url('autoplay.html') - yield this.app.client - .changeSetting('security.autoplay.media', autoplayOption.ALWAYS_ALLOW) - .tabByIndex(0) - .loadUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - }) + it('always allow', function * () { + const url = Brave.server.url('autoplay.html') + yield this.app.client + .changeSetting('security.autoplay.media', autoplayOption.ALWAYS_ALLOW) + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + }) - it('allow autoplay until tab closed', function * () { - const url = Brave.server.url('autoplay.html') - yield this.app.client - .tabByIndex(0) - .loadUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === '' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .waitForExist(notificationBar) - .waitUntil(function () { - return this.getText(notificationBar).then((val) => val.includes('autoplay media')) - }) - .click('button=Yes') - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .activateURLMode() - .click(reloadButton) - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .newTab({ url }) - .waitForTabCount(2) - .waitForUrl(url) - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .closeTabByIndex(0) - .activateURLMode() - .click(reloadButton) - .waitForExist(notificationBar) - .waitUntil(function () { - return this.getText(notificationBar).then((val) => val.includes('autoplay media')) - }) - }) + it('allow autoplay once', function * () { + const url = Brave.server.url('autoplay.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('button=Yes') + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .activateURLMode() + .click(reloadButton) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + }) - it('allow autoplay and remember', function * () { - const url = Brave.server.url('autoplay.html') - yield this.app.client - .tabByIndex(0) - .loadUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === '' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .waitForExist(notificationBar) - .waitUntil(function () { - return this.getText(notificationBar).then((val) => val.includes('autoplay media')) - }) - .click('[data-l10n-id=rememberDecision]') - .click('button=Yes') - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .activateURLMode() - .click(reloadButton) - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .newTab({ url }) - .waitForTabCount(2) - .waitForUrl(url) - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .closeTabByIndex(0) - .activateURLMode() - .click(reloadButton) - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === 'Autoplay playing' - }) - }) - }) + it('allow autoplay and remember', function * () { + const url = Brave.server.url('autoplay.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('[data-l10n-id=rememberDecision]') + .click('button=Yes') + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .activateURLMode() + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .newTab({ url }) + .waitForTabCount(2) + .waitForUrl(url) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .closeTabByIndex(0) + .activateURLMode() + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + }) - it('keep blocking autoplay', function * () { - const url = Brave.server.url('autoplay.html') - yield this.app.client - .tabByIndex(0) - .loadUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === '' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .waitForExist(notificationBar) - .waitUntil(function () { - return this.getText(notificationBar).then((val) => val.includes('autoplay media')) - }) - .click('button=No') - .windowByUrl(Brave.browserWindowUrl) - .activateURLMode() - .click(reloadButton) - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === '' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .waitForExist(notificationBar) + it('keep blocking autoplay', function * () { + const url = Brave.server.url('autoplay.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('button=No') + .windowByUrl(Brave.browserWindowUrl) + .activateURLMode() + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + }) + + it('keep blocking autoplay and remember', function * () { + const url = Brave.server.url('autoplay.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('[data-l10n-id=rememberDecision]') + .click('button=No') + .windowByUrl(Brave.browserWindowUrl) + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForElementCount('.notificationItem', 0) + }) }) - it('keep blocking autoplay and remember', function * () { - const url = Brave.server.url('autoplay.html') - yield this.app.client - .tabByIndex(0) - .loadUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === '' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .waitForExist(notificationBar) - .waitUntil(function () { - return this.getText(notificationBar).then((val) => val.includes('autoplay media')) - }) - .click('[data-l10n-id=rememberDecision]') - .click('button=No') - .windowByUrl(Brave.browserWindowUrl) - .click(reloadButton) - .tabByUrl(url) - .waitUntil(function () { - return this.getText('div[id="status"]') - .then((status) => { - return status === '' - }) - }) - .windowByUrl(Brave.browserWindowUrl) - .waitForElementCount('.notificationItem', 0) + describe('auto-click-play', function () { + it('default always ask and block', function * () { + const url = Brave.server.url('auto-click-play.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + }) + + it('always allow', function * () { + const url = Brave.server.url('auto-click-play.html') + yield this.app.client + .changeSetting('security.autoplay.media', autoplayOption.ALWAYS_ALLOW) + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + }) + + it('allow autoplay once', function * () { + const url = Brave.server.url('auto-click-play.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('button=Yes') + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .activateURLMode() + .click(reloadButton) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + }) + + it('allow autoplay and remember', function * () { + const url = Brave.server.url('auto-click-play.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('[data-l10n-id=rememberDecision]') + .click('button=Yes') + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .activateURLMode() + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .newTab({ url }) + .waitForTabCount(2) + .waitForUrl(url) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .closeTabByIndex(0) + .activateURLMode() + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === 'Autoplay playing' + }) + }) + }) + + it('keep blocking autoplay', function * () { + const url = Brave.server.url('auto-click-play.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('button=No') + .windowByUrl(Brave.browserWindowUrl) + .activateURLMode() + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + }) + + it('keep blocking autoplay and remember', function * () { + const url = Brave.server.url('auto-click-play.html') + yield this.app.client + .tabByIndex(0) + .loadUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForExist(notificationBar) + .waitUntil(function () { + return this.getText(notificationBar).then((val) => val.includes('autoplay media')) + }) + .click('[data-l10n-id=rememberDecision]') + .click('button=No') + .windowByUrl(Brave.browserWindowUrl) + .click(reloadButton) + .tabByUrl(url) + .waitUntil(function () { + return this.getText('div[id="status"]') + .then((status) => { + return status === '' + }) + }) + .windowByUrl(Brave.browserWindowUrl) + .waitForElementCount('.notificationItem', 0) + }) }) }) diff --git a/test/fixtures/auto-click-play.html b/test/fixtures/auto-click-play.html new file mode 100644 index 00000000000..55581055530 --- /dev/null +++ b/test/fixtures/auto-click-play.html @@ -0,0 +1,29 @@ + + + + + Autoplay + + + + + +
+ + + + + + diff --git a/test/unit/app/browser/reducers/autoplayReducerTest.js b/test/unit/app/browser/reducers/autoplayReducerTest.js new file mode 100644 index 00000000000..b69d6194926 --- /dev/null +++ b/test/unit/app/browser/reducers/autoplayReducerTest.js @@ -0,0 +1,292 @@ +/* global describe, it, before, after */ +const mockery = require('mockery') +const sinon = require('sinon') +const Immutable = require('immutable') +const assert = require('assert') +const fakeElectron = require('../../../lib/fakeElectron') + +const appConstants = require('../../../../../js/constants/appConstants') +const messages = require('../../../../../js/constants/messages') +require('../../../braveUnit') + +describe('autoplayReducer unit tests', function () { + let autoplayReducer + let fakeWebContents, fakeAppActions, fakeLocale + let showNotificationSpy, hideNotificationSpy, translationSpy, + removeListenerSpy, changeSiteSettingSpy, removeSiteSettingSpy + const tabId = 123 + const url = 'https://www.brave.com/niceplay' + const origin = 'https://www.brave.com' + const message = `Allow ${origin} to autoplay media?` + const showNotificationArg = { + buttons: [ + {text: 'Yes'}, + {text: 'No'} + ], + message, + frameOrigin: origin, + options: { + persist: true + } + } + + before(function () { + mockery.enable({ + warnOnReplace: false, + warnOnUnregistered: false, + useCleanCache: true + }) + + fakeWebContents = { + isDestroyed: () => false, + reload: () => {}, + on: (e, cb) => { cb(e) }, + removeListener: (e, cb) => {}, + getURL: () => { + return url + } + } + + fakeAppActions = { + showNotification: (arg) => {}, + hideNotification: (msg) => {}, + changeSiteSetting: (hostPattern, key, value) => {}, + removeSiteSetting: (hostPattern, key) => {} + } + + fakeLocale = { + translation: (msg, arg) => { + let retMsg = '' + switch (msg) { + case 'yes': + retMsg += 'Yes' + break + case 'no': + retMsg += 'No' + break + case 'allowAutoplay': + retMsg += `Allow ${arg.origin} to autoplay media?` + break + } + return retMsg + } + } + + fakeElectron.webContents = { + fromTabID: (tabId) => { + return fakeWebContents + } + } + + showNotificationSpy = sinon.spy(fakeAppActions, 'showNotification') + hideNotificationSpy = sinon.spy(fakeAppActions, 'hideNotification') + translationSpy = sinon.spy(fakeLocale, 'translation') + removeListenerSpy = sinon.spy(fakeElectron.ipcMain, 'removeListener') + changeSiteSettingSpy = sinon.spy(fakeAppActions, 'changeSiteSetting') + removeSiteSettingSpy = sinon.spy(fakeAppActions, 'removeSiteSetting') + + mockery.registerMock('electron', fakeElectron) + mockery.registerMock('../../../js/actions/appActions', fakeAppActions) + mockery.registerMock('../../locale', fakeLocale) + + autoplayReducer = require('../../../../../app/browser/reducers/autoplayReducer') + }) + + after(function () { + showNotificationSpy.restore() + hideNotificationSpy.restore() + translationSpy.restore() + removeListenerSpy.restore() + changeSiteSettingSpy.restore() + removeSiteSettingSpy.restore() + mockery.deregisterAll() + mockery.disable() + }) + + describe('Allow autoplay once', function () { + before(function () { + autoplayReducer(Immutable.fromJS({ + siteSettings: {} + }), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_BLOCKED, + tabId: tabId + })) + fakeElectron.ipcMain.send(messages.NOTIFICATION_RESPONSE, {}, message, 0, false) + }) + + it('calls local.translation', function () { + assert(translationSpy.withArgs('allowAutoplay', {origin}).called) + assert(translationSpy.withArgs('yes').called) + assert(translationSpy.withArgs('no').called) + }) + + it('calls appActions.showNotification', function () { + assert(showNotificationSpy.withArgs(showNotificationArg).called) + }) + + it('calls appActions.hideNotification', function () { + assert(hideNotificationSpy.withArgs(message).called) + }) + + it('calls appActions.changeSiteSetting', function () { + assert(changeSiteSettingSpy.withArgs(origin, 'autoplay', true).called) + }) + + it('calls appActions.removeSiteSetting', function () { + assert(removeSiteSettingSpy.withArgs(origin, 'autoplay').called) + }) + + it('calls ipcMain.removeListener', function () { + assert(removeListenerSpy.called) + }) + }) + + describe('Allow autoplay and remember', function () { + before(function () { + autoplayReducer(Immutable.fromJS({ + siteSettings: {} + }), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_BLOCKED, + tabId: tabId + })) + fakeElectron.ipcMain.send(messages.NOTIFICATION_RESPONSE, {}, message, 0, true) + }) + + it('calls local.translation', function () { + assert(translationSpy.withArgs('allowAutoplay', {origin}).called) + assert(translationSpy.withArgs('yes').called) + assert(translationSpy.withArgs('no').called) + }) + + it('calls appActions.showNotification', function () { + assert(showNotificationSpy.withArgs(showNotificationArg).called) + }) + + it('calls appActions.hideNotification', function () { + assert(hideNotificationSpy.withArgs(message).called) + }) + + it('calls appActions.changeSiteSetting', function () { + assert(changeSiteSettingSpy.withArgs(origin, 'autoplay', true).called) + }) + + it('calls ipcMain.removeListener', function () { + assert(removeListenerSpy.called) + }) + }) + + describe('Deny autoplay once', function () { + before(function () { + autoplayReducer(Immutable.fromJS({ + siteSettings: {} + }), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_BLOCKED, + tabId: tabId + })) + fakeElectron.ipcMain.send(messages.NOTIFICATION_RESPONSE, {}, message, 1, false) + }) + + it('calls local.translation', function () { + assert(translationSpy.withArgs('allowAutoplay', {origin}).called) + assert(translationSpy.withArgs('yes').called) + assert(translationSpy.withArgs('no').called) + }) + + it('calls appActions.showNotification', function () { + assert(showNotificationSpy.withArgs(showNotificationArg).called) + }) + + it('calls appActions.hideNotification', function () { + assert(hideNotificationSpy.withArgs(message).called) + }) + + it('calls ipcMain.removeListener', function () { + assert(removeListenerSpy.called) + }) + }) + + describe('Deny autoplay and remember', function () { + before(function () { + autoplayReducer(Immutable.fromJS({ + siteSettings: {} + }), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_BLOCKED, + tabId: tabId + })) + fakeElectron.ipcMain.send(messages.NOTIFICATION_RESPONSE, {}, message, 1, true) + }) + + it('calls local.translation', function () { + assert(translationSpy.withArgs('allowAutoplay', {origin}).called) + assert(translationSpy.withArgs('yes').called) + assert(translationSpy.withArgs('no').called) + }) + + it('calls appActions.showNotification', function () { + assert(showNotificationSpy.withArgs(showNotificationArg).called) + }) + + it('calls appActions.hideNotification', function () { + assert(hideNotificationSpy.withArgs(message).called) + }) + + it('calls appActions.changeSiteSetting', function () { + assert(changeSiteSettingSpy.withArgs(origin, 'autoplay', false).called) + }) + + it('calls ipcMain.removeListener', function () { + assert(removeListenerSpy.called) + }) + }) + + describe('Calling with exsting deny rules', function () { + before(function () { + showNotificationSpy.reset() + autoplayReducer(Immutable.fromJS({ + siteSettings: { + 'https://www.brave.com': { + autoplay: false + } + } + }), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_BLOCKED, + tabId: tabId + })) + autoplayReducer(Immutable.Map(), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_DISMISSED, + tabId: tabId + })) + + it('never calls appActions.showNotification', function () { + assert(showNotificationSpy.neverCalledWith(showNotificationArg)) + }) + }) + }) + + describe('APP_AUTOPLAY_DISMISSED', function () { + before(function () { + autoplayReducer(Immutable.fromJS({ + siteSettings: {} + }), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_BLOCKED, + tabId: tabId + })) + autoplayReducer(Immutable.Map(), Immutable.fromJS({ + actionType: appConstants.APP_AUTOPLAY_DISMISSED, + tabId: tabId + })) + }) + + it('calls local.translation', function () { + assert(translationSpy.withArgs('allowAutoplay', {origin}).called) + }) + + it('calls appActions.hideNotification', function () { + assert(hideNotificationSpy.withArgs(message).called) + }) + + it('calls ipcMain.removeListener', function () { + assert(removeListenerSpy.called) + }) + }) +})