Skip to content
This repository was archived by the owner on Dec 11, 2019. It is now read-only.

Commit e9158b5

Browse files
committed
Notify users when autoplay has been blocked and provide option to allow it
Display "Block autoplay" in bravey shield Fix #8738 Fix #8739 Auditors: @bbondy, @bsclifton, @jonathansampson Test Plan: Covered by automatic test
1 parent 1f536b0 commit e9158b5

File tree

15 files changed

+200
-20
lines changed

15 files changed

+200
-20
lines changed
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
'use strict'
6+
7+
const appConstants = require('../../../js/constants/appConstants')
8+
const {makeImmutable} = require('../../common/state/immutableUtil')
9+
const {ipcMain, webContents} = require('electron')
10+
const AppStore = require('../../../js/stores/appStore')
11+
const siteSettings = require('../../../js/state/siteSettings')
12+
const appActions = require('../../../js/actions/appActions')
13+
const {getOrigin} = require('../../../js/state/siteUtil')
14+
const locale = require('../../locale')
15+
const messages = require('../../../js/constants/messages')
16+
const urlParse = require('../../common/urlParse')
17+
18+
const showAutoplayMessageBox = (location, tabId) => {
19+
const origin = getOrigin(location)
20+
const originSettings = siteSettings.getSiteSettingsForURL(AppStore.getState().get('siteSettings'), origin)
21+
if (originSettings && originSettings.get('noAutoplay') === true) {
22+
return
23+
}
24+
const message = locale.translation('autoplayBlocked', {origin})
25+
26+
appActions.showNotification({
27+
buttons: [
28+
{text: locale.translation('yes')},
29+
{text: locale.translation('no')}
30+
],
31+
message,
32+
frameOrigin: origin,
33+
options: {
34+
persist: true
35+
}
36+
})
37+
38+
ipcMain.once(messages.NOTIFICATION_RESPONSE, (e, msg, buttonIndex, persist) => {
39+
if (msg === message) {
40+
appActions.hideNotification(message)
41+
let ruleKey = origin
42+
const parsedUrl = urlParse(location)
43+
if ((parsedUrl.protocol === 'https:' || parsedUrl.protocol === 'http:')) {
44+
ruleKey = `https?://${parsedUrl.host}`
45+
}
46+
if (buttonIndex === 0) {
47+
appActions.changeSiteSetting(ruleKey, 'noAutoplay', false)
48+
49+
if (tabId) {
50+
const tab = webContents.fromTabID(tabId)
51+
if (tab && !tab.isDestroyed()) {
52+
return tab.reload()
53+
}
54+
}
55+
} else {
56+
if (persist) {
57+
appActions.changeSiteSetting(ruleKey, 'noAutoplay', true)
58+
}
59+
}
60+
}
61+
})
62+
}
63+
64+
const autoplayReducer = (state, action, immutableAction) => {
65+
action = immutableAction || makeImmutable(action)
66+
switch (action.get('actionType')) {
67+
case appConstants.APP_AUTOPLAY_BLOCKED:
68+
showAutoplayMessageBox(action.get('location'), action.get('tabId'))
69+
break
70+
}
71+
return state
72+
}
73+
74+
module.exports = autoplayReducer

app/extensions/brave/locales/en-US/app.properties

+1
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,4 @@ copied=Copied!
260260
connectionError=Server connection failed. Please make sure you are connected to the Internet.
261261
unknownError=Oops, something went wrong.
262262
browserActionButton.title={{name}}
263+
autoplayBlocked=Media autoplay on {{origin}} has been blocked. Do you want to allow it?

app/extensions/brave/locales/en-US/bravery.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ httpReroutes={[plural(httpsUpgradeCount)]}
2626
httpReroutes[one]=HTTPS Upgrade
2727
httpReroutes[other]=HTTPS Upgrades
2828
editBraveryGlobalSettings=Edit default shield settings…
29-
allowAutoplay=Allow Autoplay Media
29+
noAutoplay=Block Autoplay

app/locale.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@ var rendererIdentifiers = function () {
251251
'closeFirefoxWarningOk',
252252
'importSuccessOk',
253253
'connectionError',
254-
'unknownError'
254+
'unknownError',
255+
'autoplayBlocked'
255256
]
256257
}
257258

docs/appActions.md

+12
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,18 @@ because ESC was pressed.
10361036

10371037

10381038

1039+
### autoplayBlocked(location, tabId)
1040+
1041+
Notifies autoplay has been blocked
1042+
1043+
**Parameters**
1044+
1045+
**location**: `string`, Location of current frame
1046+
1047+
**tabId**: `number`, Tab id of current frame
1048+
1049+
1050+
10391051

10401052
* * *
10411053

js/about/preferences.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const adInsertion = appConfig.resourceNames.AD_INSERTION
4949
const trackingProtection = appConfig.resourceNames.TRACKING_PROTECTION
5050
const httpsEverywhere = appConfig.resourceNames.HTTPS_EVERYWHERE
5151
const safeBrowsing = appConfig.resourceNames.SAFE_BROWSING
52-
const autoplay = appConfig.resourceNames.AUTOPLAY
52+
const noAutoplay = appConfig.resourceNames.NOAUTOPLAY
5353
const noScript = appConfig.resourceNames.NOSCRIPT
5454
const flash = appConfig.resourceNames.FLASH
5555

@@ -88,7 +88,8 @@ const braveryPermissionNames = {
8888
'safeBrowsing': ['boolean'],
8989
'httpsEverywhere': ['boolean'],
9090
'fingerprintingProtection': ['boolean'],
91-
'noScript': ['boolean', 'number']
91+
'noScript': ['boolean', 'number'],
92+
'noAutoplay': ['boolean']
9293
}
9394

9495
class GeneralTab extends ImmutableComponent {
@@ -497,7 +498,7 @@ class ShieldsTab extends ImmutableComponent {
497498
this.onChangeAdControl = this.onChangeAdControl.bind(this)
498499
this.onToggleHTTPSE = this.onToggleSetting.bind(this, httpsEverywhere)
499500
this.onToggleSafeBrowsing = this.onToggleSetting.bind(this, safeBrowsing)
500-
this.onToggleAutoplay = this.onToggleSetting.bind(this, autoplay)
501+
this.onToggleNoAutoplay = this.onToggleSetting.bind(this, noAutoplay)
501502
this.onToggleNoScript = this.onToggleSetting.bind(this, noScript)
502503
}
503504
onChangeAdControl (e) {
@@ -548,7 +549,7 @@ class ShieldsTab extends ImmutableComponent {
548549
<SettingCheckbox checked={this.props.braveryDefaults.get('safeBrowsing')} dataL10nId='safeBrowsing' onChange={this.onToggleSafeBrowsing} />
549550
<SettingCheckbox checked={this.props.braveryDefaults.get('noScript')} dataL10nId='noScriptPref' onChange={this.onToggleNoScript} />
550551
<SettingCheckbox dataL10nId='blockCanvasFingerprinting' prefKey={settings.BLOCK_CANVAS_FINGERPRINTING} settings={this.props.settings} onChangeSetting={this.props.onChangeSetting} />
551-
<SettingCheckbox checked={this.props.braveryDefaults.get('autoplay')} dataL10nId='allowAutoplay' onChange={this.onToggleAutoplay} />
552+
<SettingCheckbox checked={this.props.braveryDefaults.get('noAutoplay')} dataL10nId='noAutoplay' onChange={this.onToggleNoAutoplay} />
552553
<Button l10nId='manageAdblockSettings' className='primaryButton manageAdblockSettings'
553554
onClick={aboutActions.createTabRequested.bind(null, {
554555
url: 'about:adblock'

js/actions/appActions.js

+13
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,19 @@ const appActions = {
12921292
AppDispatcher.dispatch({
12931293
actionType: appConstants.APP_DRAG_CANCELLED
12941294
})
1295+
},
1296+
1297+
/**
1298+
* Notifies autoplay has been blocked
1299+
* @param {string} location - Location of current frame
1300+
* @param {number} tabId - Tab id of current frame
1301+
*/
1302+
autoplayBlocked: function (location, tabId) {
1303+
AppDispatcher.dispatch({
1304+
actionType: appConstants.APP_AUTOPLAY_BLOCKED,
1305+
location,
1306+
tabId
1307+
})
12951308
}
12961309
}
12971310

js/components/braveryPanel.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class BraveryPanel extends ImmutableComponent {
3131
this.onToggleCookieControl = this.onToggleSiteSetting.bind(this, 'cookieControl')
3232
this.onToggleHTTPSE = this.onToggleSiteSetting.bind(this, 'httpsEverywhere')
3333
this.onToggleFp = this.onToggleSiteSetting.bind(this, 'fingerprintingProtection')
34-
this.onToggleAutoplay = this.onToggleSiteSetting.bind(this, 'autoplay')
34+
this.onToggleNoAutoplay = this.onToggleSiteSetting.bind(this, 'noAutoplay')
3535
this.onReload = this.onReload.bind(this)
3636
this.onEditGlobal = this.onEditGlobal.bind(this)
3737
this.onInfoClick = this.onInfoClick.bind(this)
@@ -151,6 +151,7 @@ class BraveryPanel extends ImmutableComponent {
151151
if (setting !== 'noScript' && (parsedUrl.protocol === 'https:' || parsedUrl.protocol === 'http:')) {
152152
ruleKey = `https?://${parsedUrl.host}`
153153
}
154+
console.log(e.target.value)
154155
appActions.changeSiteSetting(ruleKey, setting, e.target.value, this.isPrivate)
155156
this.onReload()
156157
}
@@ -165,7 +166,7 @@ class BraveryPanel extends ImmutableComponent {
165166
const shieldsUp = this.props.braverySettings.shieldsUp
166167
const noScriptEnabled = this.props.braverySettings.noScript
167168
const httpseEnabled = this.props.braverySettings.httpsEverywhere
168-
const autoplayEnabled = this.props.braverySettings.autoplay
169+
const noAutoplayEnabled = this.props.braverySettings.noAutoplay
169170
const adControl = this.props.braverySettings.adControl
170171
const fpEnabled = this.props.braverySettings.fingerprintingProtection
171172
const adsBlockedStat = (this.blockedAds ? this.blockedAds.size : 0) + (this.blockedByTrackingList ? this.blockedByTrackingList.size : 0)
@@ -299,7 +300,7 @@ class BraveryPanel extends ImmutableComponent {
299300
</FormDropdown>
300301
<SwitchControl onClick={this.onToggleHTTPSE} rightl10nId='httpsEverywhere' checkedOn={httpseEnabled} disabled={!shieldsUp} className='httpsEverywhereSwitch' />
301302
<SwitchControl onClick={this.onToggleNoScript} rightl10nId='noScript' checkedOn={noScriptEnabled} disabled={!shieldsUp} className='noScriptSwitch' />
302-
<SwitchControl onClick={this.onToggleAutoplay} rightl10nId='allowAutoplay' checkedOn={autoplayEnabled} disabled={!shieldsUp} className='allowAutoplay' />
303+
<SwitchControl onClick={this.onToggleNoAutoplay} rightl10nId='noAutoplay' checkedOn={noAutoplayEnabled} disabled={!shieldsUp} className='noAutoplaySwitch' />
303304
</div>
304305
<div className='braveryControlGroup'>
305306
<div className={cx({

js/components/frame.js

+3
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,9 @@ class Frame extends React.Component {
528528
if (e.details[0] === 'javascript' && e.details[1]) {
529529
windowActions.setBlockedBy(this.frame, 'noScript', e.details[1])
530530
}
531+
if (e.details[0] === 'autoplay') {
532+
appActions.autoplayBlocked(this.frame.get('location'), this.frame.get('tabId'))
533+
}
531534
})
532535
this.webview.addEventListener('did-block-run-insecure-content', (e) => {
533536
if (this.frame.isEmpty()) {

js/constants/appConfig.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = {
1919
quitTimeout: 10 * 1000,
2020
resourceNames: {
2121
ADBLOCK: 'adblock',
22-
AUTOPLAY: 'autoplay',
22+
NOAUTOPLAY: 'noAutoplay',
2323
SAFE_BROWSING: 'safeBrowsing',
2424
HTTPS_EVERYWHERE: 'httpsEverywhere',
2525
TRACKING_PROTECTION: 'trackingProtection',
@@ -36,8 +36,8 @@ module.exports = {
3636
cookieblock: {
3737
enabled: true
3838
},
39-
autoplay: {
40-
enabled: false
39+
noAutoplay: {
40+
enabled: true
4141
},
4242
cookieblockAll: {
4343
enabled: false

js/constants/appConstants.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ const appConstants = {
123123
APP_ON_GO_FORWARD: _,
124124
APP_ON_GO_TO_INDEX: _,
125125
APP_ON_GO_BACK_LONG: _,
126-
APP_ON_GO_FORWARD_LONG: _
126+
APP_ON_GO_FORWARD_LONG: _,
127+
APP_AUTOPLAY_BLOCKED: _
127128
}
128129

129130
module.exports = mapValuesByKeys(appConstants)

js/state/contentSettings.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const getDefaultUserPrefContentSettings = (braveryDefaults, appSettings, appConf
6464
braveryDefaults = makeImmutable(braveryDefaults)
6565
return Immutable.fromJS({
6666
autoplay: [{
67-
setting: braveryDefaults.get('autoplay') ? 'allow' : 'block',
67+
setting: braveryDefaults.get('noAutoplay') ? 'block' : 'allow',
6868
primaryPattern: '*'
6969
}],
7070
cookies: getDefault3rdPartyStorageSettings(braveryDefaults, appSettings, appConfig),
@@ -281,8 +281,8 @@ const siteSettingsToContentSettings = (currentSiteSettings, defaultContentSettin
281281
if (typeof siteSetting.get('widevine') === 'number' && braveryDefaults.get('widevine')) {
282282
contentSettings = addContentSettings(contentSettings, 'plugins', primaryPattern, '*', 'allow', appConfig.widevine.resourceId)
283283
}
284-
if (typeof siteSetting.get('autoplay') === 'boolean') {
285-
contentSettings = addContentSettings(contentSettings, 'autoplay', primaryPattern, '*', siteSetting.get('autoplay') ? 'allow' : 'block')
284+
if (typeof siteSetting.get('noAutoplay') === 'boolean') {
285+
contentSettings = addContentSettings(contentSettings, 'autoplay', primaryPattern, '*', siteSetting.get('noAutoplay') ? 'block' : 'allow')
286286
}
287287
})
288288
// On the second pass we consider only shieldsUp === false settings since we want those to take precedence.

js/stores/appStore.js

+1
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ const handleAppAction = (action) => {
375375
reducers = [
376376
require('../../app/browser/reducers/downloadsReducer'),
377377
require('../../app/browser/reducers/flashReducer'),
378+
require('../../app/browser/reducers/autoplayReducer'),
378379
// tabs, sites and windows reducers need to stay in that order
379380
// until we have a better way to manage dependencies.
380381
// tabsReducer must be above dragDropReducer.

test/bravery-components/braveryPanelTest.js

+75-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* global describe, it, beforeEach */
22

33
const Brave = require('../lib/brave')
4-
const {cookieControl, allowAllCookiesOption, blockAllCookiesOption, urlInput, braveMenu, braveMenuDisabled, adsBlockedStat, adsBlockedControl, showAdsOption, blockAdsOption, braveryPanel, httpsEverywhereStat, noScriptStat, noScriptSwitch, fpSwitch, autoplaySwitch, fpStat, noScriptNavButton, customFiltersInput} = require('../lib/selectors')
4+
const {cookieControl, allowAllCookiesOption, blockAllCookiesOption, urlInput, braveMenu, braveMenuDisabled, adsBlockedStat, adsBlockedControl, showAdsOption, blockAdsOption, braveryPanel, httpsEverywhereStat, noScriptStat, noScriptSwitch, fpSwitch, noAutoplaySwitch, fpStat, noScriptNavButton, customFiltersInput, notificationBar, reloadButton} = require('../lib/selectors')
55
const {getTargetAboutUrl} = require('../../js/lib/appUrlUtil')
66

77
describe('Bravery Panel', function () {
@@ -518,6 +518,11 @@ describe('Bravery Panel', function () {
518518
return status === ''
519519
})
520520
})
521+
.windowByUrl(Brave.browserWindowUrl)
522+
.waitForExist(notificationBar)
523+
.waitUntil(function () {
524+
return this.getText(notificationBar).then((val) => val.includes('Media autoplay'))
525+
})
521526
})
522527

523528
it('allow autoplay in regular tab', function * () {
@@ -531,8 +536,13 @@ describe('Bravery Panel', function () {
531536
return status === ''
532537
})
533538
})
539+
.windowByUrl(Brave.browserWindowUrl)
540+
.waitForExist(notificationBar)
541+
.waitUntil(function () {
542+
return this.getText(notificationBar).then((val) => val.includes('Media autoplay'))
543+
})
534544
.openBraveMenu(braveMenu, braveryPanel)
535-
.click(autoplaySwitch)
545+
.click(noAutoplaySwitch)
536546
.keys(Brave.keys.ESCAPE)
537547
.tabByUrl(url)
538548
.waitUntil(function () {
@@ -554,8 +564,13 @@ describe('Bravery Panel', function () {
554564
return status === ''
555565
})
556566
})
567+
.windowByUrl(Brave.browserWindowUrl)
568+
.waitForExist(notificationBar)
569+
.waitUntil(function () {
570+
return this.getText(notificationBar).then((val) => val.includes('Media autoplay'))
571+
})
557572
.openBraveMenu(braveMenu, braveryPanel)
558-
.click(autoplaySwitch)
573+
.click(noAutoplaySwitch)
559574
.keys(Brave.keys.ESCAPE)
560575
.tabByUrl(url)
561576
.waitUntil(function () {
@@ -565,5 +580,62 @@ describe('Bravery Panel', function () {
565580
})
566581
})
567582
})
583+
584+
it('allow autoplay in notification bar', function * () {
585+
const url = Brave.server.url('autoplay.html')
586+
yield this.app.client
587+
.tabByIndex(0)
588+
.loadUrl(url)
589+
.waitUntil(function () {
590+
return this.getText('div[id="status"]')
591+
.then((status) => {
592+
return status === ''
593+
})
594+
})
595+
.windowByUrl(Brave.browserWindowUrl)
596+
.waitForExist(notificationBar)
597+
.waitUntil(function () {
598+
return this.getText(notificationBar).then((val) => val.includes('Media autoplay'))
599+
})
600+
.click('button=Yes')
601+
.tabByUrl(url)
602+
.waitUntil(function () {
603+
return this.getText('div[id="status"]')
604+
.then((status) => {
605+
return status === 'Autoplay playing'
606+
})
607+
})
608+
})
609+
610+
it('Remember block autoplay in notification bar', function * () {
611+
const url = Brave.server.url('autoplay.html')
612+
yield this.app.client
613+
.tabByIndex(0)
614+
.loadUrl(url)
615+
.waitUntil(function () {
616+
return this.getText('div[id="status"]')
617+
.then((status) => {
618+
return status === ''
619+
})
620+
})
621+
.windowByUrl(Brave.browserWindowUrl)
622+
.waitForExist(notificationBar)
623+
.waitUntil(function () {
624+
return this.getText(notificationBar).then((val) => val.includes('Media autoplay'))
625+
})
626+
.click('[data-l10n-id=rememberDecision]')
627+
.click('button=No')
628+
.windowByUrl(Brave.browserWindowUrl)
629+
.click(reloadButton)
630+
.tabByUrl(url)
631+
.waitUntil(function () {
632+
return this.getText('div[id="status"]')
633+
.then((status) => {
634+
return status === ''
635+
})
636+
})
637+
.windowByUrl(Brave.browserWindowUrl)
638+
.waitForElementCount('.notificationItem', 0)
639+
})
568640
})
569641
})

test/lib/selectors.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ module.exports = {
5858
noScriptAllowOnceButton: '[data-l10n-id="allowScriptsOnce"]',
5959
noScriptAllowButton: '[data-l10n-id="allowScripts"]',
6060
safeBrowsingSwitch: '.safeBrowsingSwitch .switchMiddle',
61-
autoplaySwitch: '.allowAutoplay .switchMiddle',
61+
noAutoplaySwitch: '.noAutoplaySwitch .switchMiddle',
6262
backButton: '.backforward .backButton',
6363
forwardButton: '.backforward .forwardButton',
6464
reloadButton: '.reloadButton',

0 commit comments

Comments
 (0)