Skip to content

Commit

Permalink
change logic of noScript interactions
Browse files Browse the repository at this point in the history
-
blocking a script now takes effect immeditately.
scripts blocked now go to the blocked list only after second interaction
address brave/brave-browser#2996
  • Loading branch information
cezaraugusto committed May 23, 2019
1 parent 74f3cfa commit 50aa365
Show file tree
Hide file tree
Showing 20 changed files with 293 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@
"message": "Allow",
"description": "Message for the resources blocked *allow* option"
},
"blockedOnce": {
"message": "Blocked once",
"description": "Message for the resources blocked *blocked once* option"
},
"allowedOnce": {
"message": "Allowed once",
"description": "Message for the resources blocked *allowed once* option"
},
"cancel": {
"message": "Cancel",
"description": "Message for the button inside the static list of resources blocked to cancel the operation"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ export const blockCookies: actions.BlockCookies = (setting) => {
}
}

export const allowScriptOriginsOnce: actions.AllowScriptOriginsOnce = (origins) => {
export const allowScriptOriginsOnce: actions.AllowScriptOriginsOnce = () => {
return {
type: types.ALLOW_SCRIPT_ORIGINS_ONCE,
origins
type: types.ALLOW_SCRIPT_ORIGINS_ONCE
}
}

Expand All @@ -88,3 +87,13 @@ export const changeAllNoScriptSettings: actions.ChangeAllNoScriptSettings = (sho
shouldBlock
}
}

/**
* Set the final state to all resources so they could be stored persistently in
* the blocked/allowed list
*/
export const setFinalScriptsBlockedState: actions.SetFinalScriptsBlockedState = () => {
return {
type: types.SET_FINAL_SCRIPTS_BLOCKED_ONCE_STATE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

// Types
import * as shieldsPanelTypes from '../../constants/shieldsPanelTypes'
import * as windowTypes from '../../constants/windowTypes'
import * as tabTypes from '../../constants/tabTypes'
import * as webNavigationTypes from '../../constants/webNavigationTypes'
import { State, Tab } from '../../types/state/shieldsPannelState'
import { Actions } from '../../types/actions/index'

// State helpers
import * as shieldsPanelState from '../../state/shieldsPanelState'
import * as noScriptState from '../../state/noScriptState'

// APIs
import {
setAllowBraveShields,
setAllowAds,
Expand All @@ -20,10 +29,10 @@ import {
} from '../api/shieldsAPI'
import { setBadgeText, setIcon } from '../api/browserActionAPI'
import { reloadTab } from '../api/tabsAPI'
import * as shieldsPanelState from '../../state/shieldsPanelState'
import { State, Tab } from '../../types/state/shieldsPannelState'
import { Actions } from '../../types/actions/index'

// Helpers
import { getTotalResourcesBlocked } from '../../helpers/shieldsUtils'
import { getAllowedScriptsOrigins } from '../../helpers/noScriptUtils'

const updateShieldsIconBadgeText = (state: State) => {
const tabId: number = shieldsPanelState.getActiveTabId(state)
Expand Down Expand Up @@ -286,7 +295,7 @@ export default function shieldsPanelReducer (state: State = { tabs: {}, windows:
console.error('Active tab not found')
break
}
setAllowScriptOriginsOnce(action.origins, tabData.id)
setAllowScriptOriginsOnce(getAllowedScriptsOrigins(tabData.noScriptInfo), tabData.id)
.then(() => {
requestShieldPanelData(shieldsPanelState.getActiveTabId(state))
reloadTab(tabData.id, true).catch(() => {
Expand All @@ -308,6 +317,9 @@ export default function shieldsPanelReducer (state: State = { tabs: {}, windows:
state = shieldsPanelState.changeAllNoScriptSettings(state, tabId, action.shouldBlock)
break
}
case shieldsPanelTypes.SET_FINAL_SCRIPTS_BLOCKED_ONCE_STATE: {
state = noScriptState.setFinalScriptsBlockedState(state)
}
}
return state
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import {
BlockCookies,
AllowScriptOriginsOnce,
ChangeNoScriptSettings,
ChangeAllNoScriptSettings
ChangeAllNoScriptSettings,
SetFinalScriptsBlockedState
} from '../types/actions/shieldsPanelActions'

interface Props {
Expand All @@ -42,6 +43,7 @@ interface Props {
allowScriptOriginsOnce: AllowScriptOriginsOnce
changeNoScriptSettings: ChangeNoScriptSettings
changeAllNoScriptSettings: ChangeAllNoScriptSettings
setFinalScriptsBlockedState: SetFinalScriptsBlockedState
}
shieldsPanelTabData: Tab
}
Expand Down Expand Up @@ -138,6 +140,7 @@ export default class Shields extends React.PureComponent<Props, State> {
fingerprintingBlocked={shieldsPanelTabData.fingerprintingBlocked}
fingerprintingBlockedResources={shieldsPanelTabData.fingerprintingBlockedResources}
blockFingerprinting={actions.blockFingerprinting}
setFinalScriptsBlockedState={actions.setFinalScriptsBlockedState}
/>
</>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ import {
ChangeNoScriptSettings,
BlockJavaScript,
ChangeAllNoScriptSettings,
AllowScriptOriginsOnce
AllowScriptOriginsOnce,
SetFinalScriptsBlockedState
} from '../../types/actions/shieldsPanelActions'

interface CommonProps {
Expand All @@ -55,6 +56,7 @@ interface JavaScriptProps {
blockJavaScript: BlockJavaScript
changeAllNoScriptSettings: ChangeAllNoScriptSettings
allowScriptOriginsOnce: AllowScriptOriginsOnce
setFinalScriptsBlockedState: SetFinalScriptsBlockedState
}

export type Props = CommonProps & JavaScriptProps
Expand Down Expand Up @@ -122,6 +124,7 @@ export default class ScriptsControls extends React.PureComponent<Props, State> {
allowScriptOriginsOnce,
changeNoScriptSettings,
changeAllNoScriptSettings,
setFinalScriptsBlockedState,
noScriptInfo
} = this.props
const { scriptsBlockedOpen } = this.state
Expand Down Expand Up @@ -158,6 +161,7 @@ export default class ScriptsControls extends React.PureComponent<Props, State> {
allowScriptOriginsOnce={allowScriptOriginsOnce}
changeNoScriptSettings={changeNoScriptSettings}
changeAllNoScriptSettings={changeAllNoScriptSettings}
setFinalScriptsBlockedState={setFinalScriptsBlockedState}
/>
}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ import { NoScriptInfo } from '../../types/other/noScriptInfo'
import {
AllowScriptOriginsOnce,
ChangeNoScriptSettings,
ChangeAllNoScriptSettings
ChangeAllNoScriptSettings,
SetFinalScriptsBlockedState
} from '../../types/actions/shieldsPanelActions'

// Utils
import { getBlockScriptText } from '../../helpers/noScriptUtils'

interface Props {
favicon: string
hostname: string
Expand All @@ -43,6 +47,7 @@ interface Props {
allowScriptOriginsOnce: AllowScriptOriginsOnce
changeNoScriptSettings: ChangeNoScriptSettings
changeAllNoScriptSettings: ChangeAllNoScriptSettings
setFinalScriptsBlockedState: SetFinalScriptsBlockedState
}

export default class DynamicList extends React.PureComponent<Props, {}> {
Expand All @@ -54,17 +59,16 @@ export default class DynamicList extends React.PureComponent<Props, {}> {

onClickBlockOrAllowScript = (event: React.MouseEvent<HTMLButtonElement>) => {
this.props.changeNoScriptSettings(event.currentTarget.id)
this.props.allowScriptOriginsOnce()
}

onClickAllowOrBlockAll (shouldBlock: boolean) {
this.props.changeAllNoScriptSettings(shouldBlock)
this.props.allowScriptOriginsOnce()
}

onClickApplyScriptsOnce = () => {
const { list } = this.props
const allOrigins = Object.keys(list)
const allNonBlockedOrigins = allOrigins.filter(key => list[key].willBlock === false)
this.props.allowScriptOriginsOnce(allNonBlockedOrigins)
onClickConfirmApplyScripts = () => {
this.props.setFinalScriptsBlockedState()
}

getList = (isBlocked: boolean) => {
Expand All @@ -77,7 +81,7 @@ export default class DynamicList extends React.PureComponent<Props, {}> {
<BlockedListItemWithOptions key={index}>
<span title={origin}>{origin}</span>
<LinkAction id={origin} onClick={this.onClickBlockOrAllowScript}>
{list[origin].willBlock ? getLocale('allow') : getLocale('block')}
{getBlockScriptText(list[origin].userInteracted, !isBlocked)}
</LinkAction>
</BlockedListItemWithOptions>
)
Expand Down Expand Up @@ -123,7 +127,7 @@ export default class DynamicList extends React.PureComponent<Props, {}> {
<BlockedListFooterWithOptions>
<LinkAction onClick={onClose}>{getLocale('cancel')}</LinkAction>
<ShieldsButton
onClick={this.onClickApplyScriptsOnce}
onClick={this.onClickConfirmApplyScripts}
level='primary'
type='accent'
text={getLocale('applyOnce')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import {
ChangeAllNoScriptSettings,
AllowScriptOriginsOnce,
BlockCookies,
BlockFingerprinting
BlockFingerprinting,
SetFinalScriptsBlockedState
} from '../types/actions/shieldsPanelActions'
import { BlockCookiesOptions, BlockJSOptions, BlockFPOptions } from '../types/other/blockTypes'
import { NoScriptInfo } from '../types/other/noScriptInfo'
Expand All @@ -36,6 +37,7 @@ interface JavaScriptProps {
blockJavaScript: BlockJavaScript
changeAllNoScriptSettings: ChangeAllNoScriptSettings
allowScriptOriginsOnce: AllowScriptOriginsOnce
setFinalScriptsBlockedState: SetFinalScriptsBlockedState
}

interface CookiesProps {
Expand Down Expand Up @@ -70,6 +72,7 @@ export default class PrivacyControls extends React.PureComponent<Props, {}> {
blockJavaScript={this.props.blockJavaScript}
changeAllNoScriptSettings={this.props.changeAllNoScriptSettings}
allowScriptOriginsOnce={this.props.allowScriptOriginsOnce}
setFinalScriptsBlockedState={this.props.setFinalScriptsBlockedState}
/>
<CookiesControl
isBlockedListOpen={this.props.isBlockedListOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export const BLOCK_COOKIES = 'BLOCK_COOKIES'
export const ALLOW_SCRIPT_ORIGINS_ONCE = 'ALLOW_SCRIPT_ORIGINS_ONCE'
export const CHANGE_NO_SCRIPT_SETTINGS = 'CHANGE_NO_SCRIPT_SETTINGS'
export const CHANGE_ALL_NO_SCRIPT_SETTINGS = 'CHANGE_ALL_NO_SCRIPT_SETTINGS'
export const SET_FINAL_SCRIPTS_BLOCKED_ONCE_STATE = 'SET_FINAL_SCRIPTS_BLOCKED_ONCE_STATE'
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

// Types
import { NoScriptInfo } from '../types/other/noScriptInfo'

// Locale
import { getLocale } from '../background/api/localeAPI'

/**
* Check if all scripts in NoScriptInfo are either allowed or blocked by the user
* @param {NoScriptInfo} noScriptInfo - The modifiedNoScriptInfo state
* @param {boolean} isBlocked - Whether or not all scripts are blocked
* @returns {boolean} - Whether or not the new generated NoScriptInfo data is either blocked or allowed
*/
export const checkEveryItemIsBlockedOrAllowedByUser = (
modifiedNoScriptInfo: NoScriptInfo,
isBlocked: boolean
): boolean => {
return Object.entries(modifiedNoScriptInfo)
.filter(script => script[1].willBlock === isBlocked)
.every(script => script[1].userInteracted)
}

/**
* Get script "block all"/"allow all" text
* Scripts are divided between blocked/allowed and we have an option to block/allow all.
* If all scripts in a list are set to blocked/allowed, state should change
* to "allowed once" or "blocked once"
* @param {NoScriptInfo} noScriptInfo - The NoScriptInfo state
* @param {boolean} isBlocked - Whether or not all scripts are blocked
* @returns {string} - The string to be used by the string
*/
export const getBlockAllText = (
noScriptInfo: NoScriptInfo,
isBlocked: boolean
): string => {
const allInteracted = checkEveryItemIsBlockedOrAllowedByUser(noScriptInfo, isBlocked)

if (isBlocked) {
if (allInteracted) {
return getLocale('allowedOnce')
}
return getLocale('allowAll')
} else {
if (allInteracted) {
return getLocale('blockedOnce')
}
return getLocale('blockAll')
}
}

/**
* Get script "block" text
* Scripts can be set as allow/block when there is no interaction
* and allowed once/blocked once when interaction have happened
* @param {boolean} haveUserInteracted - Whether or not user have interacted with the script
* @param {boolean} isBlocked - Whether or not the current script is blocked
* @returns {string} - The string to be used by the allowed/blocked group
*/
export const getBlockScriptText = (haveUserInteracted: boolean, isBlocked: boolean): string => {
if (!haveUserInteracted) {
return isBlocked ? getLocale('allow') : getLocale('block')
}
return isBlocked ? getLocale('allowedOnce') : getLocale('blockedOnce')
}

/**
* Get script origins allowed by the user
* @param {NoScriptInfo} noScriptInfo - The modifiedNoScriptInfo state
* @param {boolean} isBlocked - Whether or not all scripts are blocked
* @returns {Array<string>} - An array with all origins that user decided to allow
*/
export const getAllowedScriptsOrigins = (modifiedNoScriptInfo: NoScriptInfo): Array<string> => {
const getAllowedOrigins = Object.entries(modifiedNoScriptInfo)
.filter(url => url[1].actuallyBlocked === false)
return getAllowedOrigins.map(url => url[0])
}
Loading

0 comments on commit 50aa365

Please sign in to comment.