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

add noScriptInfo checkboxes to allow scripts by origin #7272

Merged
merged 1 commit into from
Feb 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app/extensions/brave/locales/en-US/app.properties
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ updateHide=Hide
sessionInfoCommon=This tab uses session {{partitionNumber}}
sessionInfo={{sessionInfoCommon}}
sessionInfoTab.title={{sessionInfoCommon}}
allowScripts=Allow on this site always
allowScriptsTemp=Allow on this site until restart
allowScripts=Allow always
allowScriptsTemp=Allow until restart
allowScriptsOnce=Allow this time
scriptsBlocked={{numberBlocked}} scripts blocked on {{site}}
scriptBlocked={{numberBlocked}} script blocked on {{site}}
scriptsBlocked=Do you want to allow scripts on {{site}} from these sources?
unselectAll=Unselect all
findResults={{activeMatchOrdinal}} of {{numberOfMatches}}
findResultMatches={[plural(numberOfMatches)]}
findResultMatches[one]={{numberOfMatches}} match
Expand Down
2 changes: 2 additions & 0 deletions app/sessionStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ module.exports.cleanAppData = (data, isShutdown) => {
if (typeof noScript === 'number') {
delete data.siteSettings[host].noScript
}
// Don't persist any noScript exceptions
delete data.siteSettings[host].noScriptExceptions
// Don't write runInsecureContent to session
delete data.siteSettings[host].runInsecureContent
// If the site setting is empty, delete it for privacy
Expand Down
12 changes: 12 additions & 0 deletions docs/appActions.md
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,18 @@ Dispatches a message when a tab is being cloned



### noScriptExceptionsAdded(hostPattern, origins)

Dispatches a message when noscript exceptions are added for an origin

**Parameters**

**hostPattern**: `string`, Dispatches a message when noscript exceptions are added for an origin

**origins**: `Object.<string, (boolean|number)>`, Dispatches a message when noscript exceptions are added for an origin



### setObjectId(objectId, objectPath)

Dispatches a message to set objectId for a syncable object.
Expand Down
1 change: 1 addition & 0 deletions docs/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ AppStore
midiSysexPermission: boolean,
notificationsPermission: boolean,
noScript: (number|boolean), // true = block scripts, false = allow, 0 = allow once, 1 = allow until restart
noScriptExceptions: {[hostPattern]: (number|boolean)}, // hosts where scripts are allowed once (0) or until restart (1). false = block
objectId: Array.<number>,
openExternalPermission: boolean,
pointerLockPermission: boolean,
Expand Down
13 changes: 13 additions & 0 deletions js/actions/appActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,19 @@ const appActions = {
})
},

/**
* Dispatches a message when noscript exceptions are added for an origin
* @param {string} hostPattern
* @param {Object.<string, (boolean|number)>} origins
*/
noScriptExceptionsAdded: function (hostPattern, origins) {
AppDispatcher.dispatch({
actionType: appConstants.APP_ADD_NOSCRIPT_EXCEPTIONS,
hostPattern,
origins
})
},

/**
* Dispatches a message to set objectId for a syncable object.
* @param {Array.<number>} objectId
Expand Down
4 changes: 4 additions & 0 deletions js/components/frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ class Frame extends ImmutableComponent {
if (activeSiteSettings.get('noScript') === 0) {
appActions.removeSiteSetting(origin, 'noScript', this.props.isPrivate)
}
const noScriptExceptions = activeSiteSettings.get('noScriptExceptions')
if (noScriptExceptions) {
appActions.noScriptExceptionsAdded(origin, noScriptExceptions.filter((value, host) => value !== 0))
}
}

componentWillUnmount () {
Expand Down
93 changes: 77 additions & 16 deletions js/components/noScriptInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,45 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */

const React = require('react')
const Immutable = require('immutable')
const ImmutableComponent = require('./immutableComponent')
const Dialog = require('./dialog')
const Button = require('./button')
const appActions = require('../actions/appActions')
const siteUtil = require('../state/siteUtil')
const ipc = require('electron').ipcRenderer
const messages = require('../constants/messages')
const urlParse = require('url').parse

class NoScriptCheckbox extends ImmutableComponent {
toggleCheckbox (e) {
this.checkbox.checked = !this.checkbox.checked
e.stopPropagation()
}

get id () {
return `checkbox-for-${this.props.origin}`
}

render () {
return <div className='noScriptCheckbox' id={this.id}>
<input type='checkbox' onClick={(e) => { e.stopPropagation() }}
ref={(node) => { this.checkbox = node }} defaultChecked
origin={this.props.origin} />
<label htmlFor={this.id}
onClick={this.toggleCheckbox.bind(this)}>{this.props.origin}</label>
</div>
}
}

class NoScriptInfo extends ImmutableComponent {
get numberBlocked () {
get blockedOrigins () {
const blocked = this.props.frameProps.getIn(['noScript', 'blocked'])
return blocked ? blocked.size : 0
if (blocked && blocked.size) {
return new Immutable.Set(blocked.map(siteUtil.getOrigin))
} else {
return new Immutable.Set()
}
}

get origin () {
Expand All @@ -25,49 +52,83 @@ class NoScriptInfo extends ImmutableComponent {
return this.props.frameProps.get('isPrivate')
}

unselectAll (e) {
e.stopPropagation()
let checkboxes = this.checkboxes.querySelectorAll('input')
if (!checkboxes) {
return
}
checkboxes.forEach((box) => {
box.checked = false
})
}

reload () {
ipc.emit(messages.SHORTCUT_ACTIVE_FRAME_CLEAN_RELOAD)
}

onAllow (setting) {
onAllow (setting, e) {
if (!this.origin) {
return
}
appActions.changeSiteSetting(this.origin, 'noScript', setting)
this.reload()
if (setting === false) {
appActions.changeSiteSetting(this.origin, 'noScript', setting)
this.reload()
} else {
let checkedOrigins = new Immutable.Map()
this.checkboxes.querySelectorAll('input').forEach((box) => {
const origin = box.getAttribute('origin')
if (origin) {
checkedOrigins = checkedOrigins.set(origin, box.checked ? setting : false)
}
})
if (checkedOrigins.size) {
appActions.noScriptExceptionsAdded(this.origin, checkedOrigins)
this.reload()
}
}
}

get buttons () {
if (!this.props.noScriptGlobalEnabled) {
// NoScript is not turned on globally
return <div><Button l10nId='allow' className='actionButton'
return <div><Button l10nId='allowScripts' className='actionButton'
onClick={this.onAllow.bind(this, false)} /></div>
} else {
return <div>
<Button l10nId='allowScriptsOnce' className='actionButton'
onClick={this.onAllow.bind(this, 0)} />
{this.isPrivate
? null
: <div>
<div><Button l10nId='allowScriptsTemp' className='subtleButton'
onClick={this.onAllow.bind(this, 1)} /></div>
<div><Button l10nId='allow' className='subtleButton'
onClick={this.onAllow.bind(this, false)} /></div>
</div>}
: <span><Button l10nId='allowScriptsTemp' className='subtleButton'
onClick={this.onAllow.bind(this, 1)} /></span>
}
</div>
}
}

render () {
if (!this.origin) {
return null
}
const l10nArgs = {
numberBlocked: this.numberBlocked,
site: this.props.frameProps.get('location') || 'this page'
site: urlParse(this.props.frameProps.get('location')).host
}
return <Dialog onHide={this.props.onHide} className='noScriptInfo' isClickDismiss>
<div className='dialogInner'>
<div className='truncate' data-l10n-args={JSON.stringify(l10nArgs)}
data-l10n-id={this.numberBlocked === 1 ? 'scriptBlocked' : 'scriptsBlocked'} />
{this.buttons}
data-l10n-id={'scriptsBlocked'} />
{this.blockedOrigins.size
? <div>
<div ref={(node) => { this.checkboxes = node }} className='blockedOriginsList'>
{this.blockedOrigins.map((origin) => <NoScriptCheckbox origin={origin} />)}
</div>
<div data-l10n-id={'unselectAll'}
className='clickable'
onClick={this.unselectAll.bind(this)} />
{this.buttons}
</div>
: null}
</div>
</Dialog>
}
Expand Down
3 changes: 2 additions & 1 deletion js/constants/appConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ const appConstants = {
APP_TAB_TOGGLE_DEV_TOOLS: _,
APP_TAB_CLONED: _,
APP_SET_OBJECT_ID: _,
APP_SAVE_SYNC_INIT_DATA: _
APP_SAVE_SYNC_INIT_DATA: _,
APP_ADD_NOSCRIPT_EXCEPTIONS: _
}

module.exports = mapValuesByKeys(appConstants)
22 changes: 22 additions & 0 deletions js/state/contentSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,27 @@ const siteSettingsToContentSettings = (currentSiteSettings, defaultContentSettin
if (['number', 'boolean'].includes(typeof siteSetting.get('noScript'))) {
contentSettings = addContentSettings(contentSettings, 'javascript', primaryPattern, '*', siteSetting.get('noScript') === true ? 'block' : 'allow')
}
const noScriptExceptions = siteSetting.get('noScriptExceptions')
if (noScriptExceptions && typeof noScriptExceptions.get(hostPattern) === 'number') {
// Allow all is needed for inline scripts to run. XXX: this seems like
// a muon bug.
contentSettings = addContentSettings(contentSettings, 'javascript',
primaryPattern, '*', 'allow')
// Re-block the origins that aren't excluded
noScriptExceptions.forEach((value, origin) => {
if (value === false) {
contentSettings = addContentSettings(contentSettings, 'javascript',
primaryPattern, origin, 'block')
}
})
} else if (noScriptExceptions && noScriptExceptions.size) {
noScriptExceptions.forEach((value, origin) => {
if (typeof value === 'number') {
contentSettings = addContentSettings(contentSettings, 'javascript',
primaryPattern, origin, 'allow')
}
})
}
if (typeof siteSetting.get('runInsecureContent') === 'boolean') {
contentSettings = addContentSettings(contentSettings, 'runInsecureContent', primaryPattern, '*',
siteSetting.get('runInsecureContent') ? 'allow' : 'block')
Expand Down Expand Up @@ -279,6 +300,7 @@ const doAction = (action) => {
switch (action.actionType) {
case appConstants.APP_REMOVE_SITE_SETTING:
case appConstants.APP_CHANGE_SITE_SETTING:
case appConstants.APP_ADD_NOSCRIPT_EXCEPTIONS:
AppDispatcher.waitFor([AppStore.dispatchToken], () => {
userPrefsUpdateTrigger(action.temporary)
contentSettingsUpdateTrigger(action.temporary)
Expand Down
12 changes: 12 additions & 0 deletions js/stores/appStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,18 @@ const handleAppAction = (action) => {
appState = appState.set(propertyName, newSiteSettings)
break
}
case appConstants.APP_ADD_NOSCRIPT_EXCEPTIONS:
// Note that this is always cleared on restart or reload, so should not
// be synced or persisted.
let key = 'noScriptExceptions'
if (!action.origins || !action.origins.size) {
// Clear the exceptions
appState = appState.setIn(['siteSettings', action.hostPattern, key], new Immutable.Map())
} else {
const currentExceptions = appState.getIn(['siteSettings', action.hostPattern, key]) || new Immutable.Map()
appState = appState.setIn(['siteSettings', action.hostPattern, key], currentExceptions.merge(action.origins))
}
break
case appConstants.APP_UPDATE_LEDGER_INFO:
appState = appState.set('ledgerInfo', Immutable.fromJS(action.ledgerInfo))
break
Expand Down
23 changes: 21 additions & 2 deletions less/forms.less
Original file line number Diff line number Diff line change
Expand Up @@ -494,14 +494,33 @@ select {
.flyoutDialog;
right: 20px;
width: auto;
max-width: 350px;
text-align: center;
max-width: 400px;
font-size: 15px;
cursor: default;
text-align: center;

.truncate {
margin-bottom: 5px;
}
.noScriptCheckbox {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using aphrodite for new UI but since this isn't new UI and just an extension of an existing one this is cool. Feel free to update at the same time to aphrodite if you want to.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm!

text-align: left;
}
.clickable {
text-align: left;
color: #5B5B5B;
&:hover {
color: #000;
}
text-decoration: underline;
margin-top: 10px;
}
button {
margin: 2px;
margin-top: 10px;
}
label {
margin-left: 2px;
}
}
}

Expand Down
Loading