Skip to content

Commit

Permalink
Merge pull request #11 from brave/fingerprinting_protection
Browse files Browse the repository at this point in the history
Fingerprinting protection
  • Loading branch information
yrliou authored Mar 16, 2018
2 parents a632d49 + d36733f commit 99826ae
Show file tree
Hide file tree
Showing 21 changed files with 308 additions and 36 deletions.
6 changes: 6 additions & 0 deletions app/actions/shieldsPanelActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ export const javascriptToggled: actions.JavascriptToggled = () => {
type: types.JAVASCRIPT_TOGGLED
}
}

export const fingerprintingToggled: actions.FingerprintingToggled = () => {
return {
type: types.FINGERPRINTING_TOGGLED
}
}
23 changes: 20 additions & 3 deletions app/background/api/shieldsAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export const getShieldSettingsForTabData = (tabData?: chrome.tabs.Tab) => {
chrome.contentSettings.plugins.getAsync({ primaryUrl: origin, resourceIdentifier: { id: resourceIdentifiers.RESOURCE_IDENTIFIER_ADS } }),
chrome.contentSettings.plugins.getAsync({ primaryUrl: origin, resourceIdentifier: { id: resourceIdentifiers.RESOURCE_IDENTIFIER_TRACKERS } }),
chrome.contentSettings.plugins.getAsync({ primaryUrl: origin, resourceIdentifier: { id: resourceIdentifiers.RESOURCE_IDENTIFIER_HTTP_UPGRADABLE_RESOURCES } }),
chrome.contentSettings.javascript.getAsync({ primaryUrl: origin })
chrome.contentSettings.javascript.getAsync({ primaryUrl: origin }),
chrome.contentSettings.plugins.getAsync({ primaryUrl: origin, resourceIdentifier: { id: resourceIdentifiers.RESOURCE_IDENTIFIER_FINGERPRINTING } })
]).then((details) => {
return {
url: url.href,
Expand All @@ -36,7 +37,8 @@ export const getShieldSettingsForTabData = (tabData?: chrome.tabs.Tab) => {
ads: details[1].setting,
trackers: details[2].setting,
httpUpgradableResources: details[3].setting,
javascript: details[4].setting
javascript: details[4].setting,
fingerprinting: details[5].setting
}
}).catch(() => {
return {
Expand All @@ -47,7 +49,8 @@ export const getShieldSettingsForTabData = (tabData?: chrome.tabs.Tab) => {
ads: 0,
trackers: 0,
httpUpgradableResources: 0,
javascript: 0
javascript: 0,
fingerprinting: 0
}
})
}
Expand Down Expand Up @@ -140,6 +143,20 @@ export const setAllowJavaScript = (origin: string, setting: string) =>
setting
})

/**
* Changes the fingerprinting at origin to be allowed or blocked.
* The fingerprinting-protection service will come into effect if the fingerprinting is marked as blocked.
* @param {string} origin the origin of the site to change the setting for
* @param {string} setting 'allow' or 'block'
* @return a promise which resolves with the setting is set
*/
export const setAllowFingerprinting = (origin: string, setting: string) =>
chrome.contentSettings.plugins.setAsync({
primaryPattern: origin + '/*',
resourceIdentifier: { id: resourceIdentifiers.RESOURCE_IDENTIFIER_FINGERPRINTING },
setting
})

/**
* Toggles the input value between allow and block
* @return the toggled value
Expand Down
18 changes: 18 additions & 0 deletions app/background/reducers/shieldsPanelReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
setAllowTrackers,
setAllowHTTPUpgradableResources,
setAllowJavaScript,
setAllowFingerprinting,
toggleShieldsValue,
requestShieldPanelData
} from '../api/shieldsAPI'
Expand All @@ -20,6 +21,7 @@ import { reloadTab } from '../api/tabsAPI'
import * as shieldsPanelState from '../../state/shieldsPanelState'
import { State, Tab } from '../../types/state/shieldsPannelState'
import { Actions } from '../../types/actions/index'
import { BlockOptions } from '../../types/other/blockTypes'

const updateBadgeText = (state: State) => {
const tabId: number = shieldsPanelState.getActiveTabId(state)
Expand Down Expand Up @@ -210,6 +212,22 @@ export default function shieldsPanelReducer (state: State = { tabs: {}, windows:
.updateTabShieldsData(state, tabId, { controlsOpen: action.setting })
break
}
case shieldsPanelTypes.FINGERPRINTING_TOGGLED:
{
const tabData: Tab = shieldsPanelState.getActiveTabData(state)
const setting: BlockOptions = tabData.fingerprinting === 'block' ? 'allow' : 'block'
setAllowFingerprinting(tabData.origin, setting)
.then(() => {
requestShieldPanelData(shieldsPanelState.getActiveTabId(state))
reloadTab(tabData.id, true).catch(() => {
console.error('Tab reload was not successful')
})
})
.catch(() => {
console.error('Could not set fingerprinting setting')
})
break
}
}
return state
}
4 changes: 4 additions & 0 deletions app/components/braveShields/braveShields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface Props {
controlsToggled: shieldActions.ControlsToggled
httpsEverywhereToggled: shieldActions.HttpsEverywhereToggled
javascriptToggled: shieldActions.JavascriptToggled
fingerprintingToggled: shieldActions.FingerprintingToggled
}
shieldsPanelTabData: Tab
}
Expand All @@ -42,6 +43,7 @@ export default class BraveShields extends React.Component<Props, object> {
trackersBlocked={shieldsPanelTabData.trackersBlocked}
httpsRedirected={shieldsPanelTabData.httpsRedirected}
javascriptBlocked={shieldsPanelTabData.javascriptBlocked}
fingerprintingBlocked={shieldsPanelTabData.fingerprintingBlocked}
/>
<BraveShieldsControls
braveShields={shieldsPanelTabData.braveShields}
Expand All @@ -54,6 +56,8 @@ export default class BraveShields extends React.Component<Props, object> {
httpsEverywhereToggled={actions.httpsEverywhereToggled}
javascriptToggled={actions.javascriptToggled}
controlsOpen={shieldsPanelTabData.controlsOpen}
fingerprinting={shieldsPanelTabData.fingerprinting}
fingerprintingToggled={actions.fingerprintingToggled}
/>
<BraveShieldsFooter />
</div>
Expand Down
11 changes: 10 additions & 1 deletion app/components/braveShields/braveShieldsControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ export interface Props {
ads: BlockOptions
trackers: BlockOptions
javascript: BlockOptions
fingerprinting: BlockOptions
blockAdsTrackers: shieldActions.BlockAdsTrackers
controlsToggled: shieldActions.ControlsToggled
httpsEverywhereToggled: shieldActions.HttpsEverywhereToggled
javascriptToggled: shieldActions.JavascriptToggled
fingerprintingToggled: shieldActions.FingerprintingToggled
}

export default class BraveShieldsControls extends React.Component<Props, object> {
Expand All @@ -28,6 +30,7 @@ export default class BraveShieldsControls extends React.Component<Props, object>
this.onToggleControls = this.onToggleControls.bind(this)
this.onToggleHTTPSEverywhere = this.onToggleHTTPSEverywhere.bind(this)
this.onToggleJavaScript = this.onToggleJavaScript.bind(this)
this.onToggleFingerprinting = this.onToggleFingerprinting.bind(this)
}

onChangeAdControl (e: HTMLSelectElement) {
Expand All @@ -50,8 +53,12 @@ export default class BraveShieldsControls extends React.Component<Props, object>
this.props.javascriptToggled()
}

onToggleFingerprinting () {
this.props.fingerprintingToggled()
}

render () {
const { braveShields, ads, trackers, controlsOpen, httpUpgradableResources, javascript } = this.props
const { braveShields, ads, trackers, controlsOpen, httpUpgradableResources, javascript, fingerprinting } = this.props
return (
<Grid
id='braveShieldsControls'
Expand Down Expand Up @@ -117,6 +124,8 @@ export default class BraveShieldsControls extends React.Component<Props, object>
id='fingerprintingProtection'
disabled={braveShields === 'block'}
rightText='Fingerprinting Protection'
checked={braveShields !== 'block' && fingerprinting === 'block'}
onChange={this.onToggleFingerprinting}
/>
</Column>
<Column>
Expand Down
7 changes: 6 additions & 1 deletion app/components/braveShields/braveShieldsStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface Props {
trackersBlocked: number
httpsRedirected: number
javascriptBlocked: number
fingerprintingBlocked: number
}

export default class BraveShieldsStats extends React.Component<Props, object> {
Expand All @@ -28,6 +29,10 @@ export default class BraveShieldsStats extends React.Component<Props, object> {
return this.props.javascriptBlocked
}

get fingerprintingBlocked (): number {
return this.props.fingerprintingBlocked
}

render () {
const { braveShields } = this.props
return (
Expand Down Expand Up @@ -77,7 +82,7 @@ export default class BraveShieldsStats extends React.Component<Props, object> {
</Column>

<Column align='flex-end' size={2}>
<BrowserText noSelect={true} text='0' fontSize='26px' color='#ffc000' />
<BrowserText noSelect={true} text={this.fingerprintingBlocked} fontSize='26px' color='#ffc000' />
</Column>
<Column
id='fingerPrintingProtectionStats'
Expand Down
1 change: 1 addition & 0 deletions app/constants/resourceIdentifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export const RESOURCE_IDENTIFIER_ADS = 'ads'
export const RESOURCE_IDENTIFIER_TRACKERS = 'trackers'
export const RESOURCE_IDENTIFIER_HTTP_UPGRADABLE_RESOURCES = 'httpUpgradableResources'
export const RESOURCE_IDENTIFIER_BRAVE_SHIELDS = 'braveShields'
export const RESOURCE_IDENTIFIER_FINGERPRINTING = 'fingerprinting'
1 change: 1 addition & 0 deletions app/constants/shieldsPanelTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export const BLOCK_ADS_TRACKERS = 'BLOCK_ADS_TRACKERS'
export const CONTROLS_TOGGLED = 'CONTROLS_TOGGLED'
export const HTTPS_EVERYWHERE_TOGGLED = 'HTTPS_EVERYWHERE_TOGGLED'
export const JAVASCRIPT_TOGGLED = 'JAVASCRIPT_TOGGLED'
export const FINGERPRINTING_TOGGLED = 'FINGERPRINTING_TOGGLED'
9 changes: 7 additions & 2 deletions app/state/shieldsPanelState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ export const updateTabShieldsData: shieldState.UpdateTabShieldsData = (state, ta
trackersBlocked: 0,
httpsRedirected: 0,
javascriptBlocked: 0,
fingerprintingBlocked: 0,
braveShields: 'allow',
ads: 'allow',
trackers: 'allow',
httpUpgradableResources: 'allow',
javascript: 'allow',
fingerprinting: 'allow',
controlsOpen: true
},
...tabs[tabId],
Expand All @@ -47,7 +49,7 @@ export const updateTabShieldsData: shieldState.UpdateTabShieldsData = (state, ta

export const updateResourceBlocked: shieldState.UpdateResourceBlocked = (state, tabId, blockType) => {
const tabs: shieldState.Tabs = { ...state.tabs }
tabs[tabId] = { ...{ adsBlocked: 0, trackersBlocked: 0, httpsRedirected: 0, javascriptBlocked: 0 }, ...tabs[tabId] }
tabs[tabId] = { ...{ adsBlocked: 0, trackersBlocked: 0, httpsRedirected: 0, javascriptBlocked: 0, fingerprintingBlocked: 0 }, ...tabs[tabId] }
if (blockType === 'ads') {
tabs[tabId].adsBlocked++
} else if (blockType === 'trackers') {
Expand All @@ -56,16 +58,19 @@ export const updateResourceBlocked: shieldState.UpdateResourceBlocked = (state,
tabs[tabId].httpsRedirected++
} else if (blockType === 'javascript') {
tabs[tabId].javascriptBlocked++
} else if (blockType === 'fingerprinting') {
tabs[tabId].fingerprintingBlocked++
}
return { ...state, tabs }
}

export const resetBlockingStats: shieldState.ResetBlockingStats = (state, tabId) => {
const tabs: shieldState.Tabs = { ...state.tabs }
tabs[tabId] = { ...tabs[tabId], ...{ adsBlocked: 0, trackersBlocked: 0, httpsRedirected: 0, javascriptBlocked: 0 } }
tabs[tabId] = { ...tabs[tabId], ...{ adsBlocked: 0, trackersBlocked: 0, httpsRedirected: 0, javascriptBlocked: 0, fingerprintingBlocked: 0 } }
tabs[tabId].adsBlocked = 0
tabs[tabId].trackersBlocked = 0
tabs[tabId].httpsRedirected = 0
tabs[tabId].javascriptBlocked = 0
tabs[tabId].fingerprintingBlocked = 0
return { ...state, tabs }
}
12 changes: 11 additions & 1 deletion app/types/actions/shieldsPanelActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface ShieldDetails {
trackers: BlockOptions
httpUpgradableResources: BlockOptions
javascript: BlockOptions
fingerprinting: BlockOptions
origin: string
hostname: string
}
Expand Down Expand Up @@ -81,11 +82,20 @@ export interface JavascriptToggled {
(): JavascriptToggledReturn
}

interface FingerprintingToggledReturn {
type: types.FINGERPRINTING_TOGGLED
}

export interface FingerprintingToggled {
(): FingerprintingToggledReturn
}

export type shieldPanelActions =
ShieldsPanelDataUpdatedReturn |
ShieldsToggledReturn |
ResourceBlockedReturn |
BlockAdsTrackersReturn |
ControlsToggledReturn |
HttpsEverywhereToggledReturn |
JavascriptToggledReturn
JavascriptToggledReturn |
FingerprintingToggledReturn
1 change: 1 addition & 0 deletions app/types/constants/resourceIdentifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ import * as types from '../../constants/resourceIdentifiers'
export type RESOURCE_IDENTIFIER_ADS = typeof types.RESOURCE_IDENTIFIER_ADS
export type RESOURCE_IDENTIFIER_TRACKERS = typeof types.RESOURCE_IDENTIFIER_TRACKERS
export type RESOURCE_IDENTIFIER_HTTP_UPGRADABLE_RESOURCES = typeof types.RESOURCE_IDENTIFIER_HTTP_UPGRADABLE_RESOURCES
export type RESOURCE_IDENTIFIER_FINGERPRINTING = typeof types.RESOURCE_IDENTIFIER_FINGERPRINTING
1 change: 1 addition & 0 deletions app/types/constants/shieldsPanelTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export type BLOCK_ADS_TRACKERS = typeof types.BLOCK_ADS_TRACKERS
export type CONTROLS_TOGGLED = typeof types.CONTROLS_TOGGLED
export type HTTPS_EVERYWHERE_TOGGLED = typeof types.HTTPS_EVERYWHERE_TOGGLED
export type JAVASCRIPT_TOGGLED = typeof types.JAVASCRIPT_TOGGLED
export type FINGERPRINTING_TOGGLED = typeof types.FINGERPRINTING_TOGGLED
2 changes: 1 addition & 1 deletion app/types/other/blockTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
* 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/. */

export type BlockTypes = 'ads' | 'trackers' | 'httpUpgradableResources' | 'javascript'
export type BlockTypes = 'ads' | 'trackers' | 'httpUpgradableResources' | 'javascript' | 'fingerprinting'
export type BlockOptions = 'allow' | 'block'
2 changes: 2 additions & 0 deletions app/types/state/shieldsPannelState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface Tab {
trackers: BlockOptions
trackersBlocked: number
url: string
fingerprinting: BlockOptions
fingerprintingBlocked: number
}

export interface Tabs {
Expand Down
9 changes: 8 additions & 1 deletion test/app/actions/shieldsPanelActionsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ describe('shieldsPanelActions', () => {
origin: 'https://www.brave.com',
hostname: 'www.brave.com',
id: 1,
javascript: 'allow'
javascript: 'allow',
fingerprinting: 'allow'
}
assert.deepEqual(actions.shieldsPanelDataUpdated(details), {
type: types.SHIELDS_PANEL_DATA_UPDATED,
Expand Down Expand Up @@ -73,4 +74,10 @@ describe('shieldsPanelActions', () => {
setting
})
})

it('fingerprintingToggled action', () => {
assert.deepEqual(actions.fingerprintingToggled(), {
type: types.FINGERPRINTING_TOGGLED
})
})
})
32 changes: 31 additions & 1 deletion test/app/background/api/shieldsAPITest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('Shields API', () => {
httpUpgradableResources: 'block',
javascript: 'block',
braveShields: 'block',
fingerprinting: 'block',
id: 5
})
cb()
Expand Down Expand Up @@ -97,7 +98,8 @@ describe('Shields API', () => {
ads: 'block',
trackers: 'block',
httpUpgradableResources: 'block',
javascript: 'block'
javascript: 'block',
fingerprinting: 'block'
}

this.p
Expand Down Expand Up @@ -227,6 +229,34 @@ describe('Shields API', () => {
})
})

describe('setAllowFingerprinting', function () {
before(function () {
this.spy = sinon.spy(chrome.contentSettings.plugins, 'setAsync')
this.p = shieldsAPI.setAllowFingerprinting('https://www.brave.com', 'block')
})
after(function () {
this.spy.restore()
})
it('calls chrome.contentSettings.plugins with the correct args', function () {
const arg0 = this.spy.getCall(0).args[0]
assert.deepEqual(arg0, {
primaryPattern: 'https://www.brave.com/*',
resourceIdentifier: { id: resourceIdentifiers.RESOURCE_IDENTIFIER_FINGERPRINTING },
setting: 'block'
})
})
it('passes only 1 arg to chrome.contentSettings.plugins', function () {
assert.equal(this.spy.getCall(0).args.length, 1)
})
it('resolves the returned promise', function (cb) {
this.p
.then(cb)
.catch((e: Error) => {
console.error(e.toString())
})
})
})

describe('toggleShieldsValue', function () {
it('toggles \'allow\' to \'block\'', function () {
assert.equal(shieldsAPI.toggleShieldsValue('allow'), 'block')
Expand Down
Loading

0 comments on commit 99826ae

Please sign in to comment.