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

Fingerprinting protection #11

Merged
merged 1 commit into from
Mar 16, 2018
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
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