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

Commit

Permalink
Add fingerprinting to bravery panel
Browse files Browse the repository at this point in the history
Addresses most of #1951

Auditors: @bbondy
  • Loading branch information
diracdeltas committed May 28, 2016
1 parent 5d5e6f5 commit d83b16b
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 12 deletions.
10 changes: 9 additions & 1 deletion app/extensions/brave/brave-default.js
Original file line number Diff line number Diff line change
Expand Up @@ -909,13 +909,14 @@ if (typeof KeyEvent === 'undefined') {
function reportBlock (item) {
var script_url = getOriginatingScriptUrl()
var msg = {
type: item.type,
obj: item.objName,
prop: item.propName,
url: window.location.href,
scriptUrl: stripLineAndColumnNumbers(script_url)
}

// Block the read from occuring; send info to background page instead
console.log('blocking potential canvas fingerprint', msg)
send(msg)
}

Expand All @@ -933,10 +934,12 @@ if (typeof KeyEvent === 'undefined') {
*/
function trapIFrameMethods (frame) {
var items = [{
type: 'Canvas',
objName: 'contentDocument',
propName: 'createElement',
obj: frame.contentDocument
}, {
type: 'Canvas',
objName: 'contentDocument',
propName: 'createElementNS',
obj: frame.contentDocument
Expand All @@ -962,6 +965,7 @@ if (typeof KeyEvent === 'undefined') {
var canvasMethods = ['getImageData', 'getLineDash', 'measureText']
canvasMethods.forEach(function (method) {
var item = {
type: 'Canvas',
objName: 'CanvasRenderingContext2D.prototype',
propName: method,
obj: window.CanvasRenderingContext2D.prototype
Expand All @@ -973,6 +977,7 @@ if (typeof KeyEvent === 'undefined') {
var canvasElementMethods = ['toDataURL', 'toBlob']
canvasElementMethods.forEach(function (method) {
var item = {
type: 'Canvas',
objName: 'HTMLCanvasElement.prototype',
propName: method,
obj: window.HTMLCanvasElement.prototype
Expand All @@ -984,6 +989,7 @@ if (typeof KeyEvent === 'undefined') {
'getShaderPrecisionFormat', 'getExtension']
webglMethods.forEach(function (method) {
var item = {
type: 'WebGL',
objName: 'WebGLRenderingContext.prototype',
propName: method,
obj: window.WebGLRenderingContext.prototype
Expand All @@ -994,6 +1000,7 @@ if (typeof KeyEvent === 'undefined') {
var audioBufferMethods = ['copyFromChannel', 'getChannelData']
audioBufferMethods.forEach(function (method) {
var item = {
type: 'AudioContext',
objName: 'AudioBuffer.prototype',
propName: method,
obj: window.AudioBuffer.prototype
Expand All @@ -1005,6 +1012,7 @@ if (typeof KeyEvent === 'undefined') {
'getFloatTimeDomainData', 'getByteTimeDomainData']
analyserMethods.forEach(function (method) {
var item = {
type: 'AudioContext',
objName: 'AnalyserNode.prototype',
propName: method,
obj: window.AnalyserNode.prototype
Expand Down
2 changes: 2 additions & 0 deletions app/extensions/brave/locales/en-US/bravery.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ httpsEverywhere=HTTPS Everywhere
noScript=Block Scripts
safeBrowsing=Block Phishing / Malware
blockPopups=Block Popups
fingerprintingProtection=Fingerprinting Protection
adControl=Ad Control
cookieControl=Cookie Control
allowAllCookies=Allow all cookies
adBlock=Ad Block
showBraveAds=Show Brave Ads
adsBlocked=Ads and Trackers Blocked
scriptsBlockedNumber=Scripts Blocked
fingerprintingBlocked=Fingerprinting Methods Blocked
httpReroutes=HTTPS Upgrades
4 changes: 3 additions & 1 deletion app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,9 @@ app.on('ready', () => {
})

ipcMain.on(messages.GOT_CANVAS_FINGERPRINTING, (e, details) => {
console.log('got canvas fingerprint block', details)
BrowserWindow.getAllWindows().forEach((win) => {
win.webContents.send(messages.GOT_CANVAS_FINGERPRINTING, details)
})
})

// Setup the crash handling
Expand Down
1 change: 1 addition & 0 deletions app/sessionStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ module.exports.cleanSessionData = (sessionData) => {
delete frame.httpsEverywhere
delete frame.adblock
delete frame.noScript
delete frame.trackingProtection

// Guest instance ID's are not valid after restarting.
// Electron won't know about them.
Expand Down
11 changes: 8 additions & 3 deletions docs/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ AppStore
cookieControl: string, // (block3rdPartyCookie | allowAllCookies)
safeBrowsing: boolean,
noScript: boolean,
httpsEverywhere: boolean
httpsEverywhere: boolean,
fingerprintingProtection: boolean
}
},
temporarySiteSettings: {
Expand Down Expand Up @@ -188,6 +189,9 @@ WindowStore
noScript: {
blocked: Array<string>
},
fingerprintingProtection: {
blocked: Array<string>
}
security: {
isSecure: boolean, // is using https
loginRequiredDetail: {
Expand Down Expand Up @@ -269,8 +273,9 @@ WindowStore
braveryPanelDetail: {
advancedControls: boolean, // If specified, indicates if advanced controls should be shown
expandAdblock: boolean, // If specified, indicates if the tracking protection and adblock section should be expanded
expandHttpse: boolean // If specified, indicates if the httpse section should be expanded
expandNoScript: boolean // Whether noscript section should be expanded
expandHttpse: boolean, // If specified, indicates if the httpse section should be expanded
expandNoScript: boolean, // Whether noscript section should be expanded
expandFp: boolean // Whether fingerprinting protection should be expanded
},
contextMenuDetail: {
left: number, // the left position of the context menu
Expand Down
2 changes: 1 addition & 1 deletion js/actions/windowActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ const windowActions = {
* Dispatches a message to indicate the site info, such as # of blocked ads, should be shown
*
* @param {object} frameProps - The frame to set blocked info on
* @param {string} blockType - either 'adblock' or 'trackingProtection'
* @param {string} blockType - type of the block
* @param {string} location - URL that was blocked
*/
setBlockedBy: function (frameProps, blockType, location) {
Expand Down
41 changes: 39 additions & 2 deletions js/components/braveryPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ class BraveryPanel extends ImmutableComponent {
this.onToggleAdsAndTracking = this.onToggleAdsAndTracking.bind(this)
this.onToggleHttpseList = this.onToggleHttpseList.bind(this)
this.onToggleNoScriptList = this.onToggleNoScriptList.bind(this)
this.onToggleFpList = this.onToggleFpList.bind(this)
this.onToggleAdvanced = this.onToggleAdvanced.bind(this)
this.onToggleShields = this.onToggleSiteSetting.bind(this, 'shieldsUp')
this.onToggleAdControl = this.onToggleSiteSetting.bind(this, 'adControl')
this.onToggleSafeBrowsing = this.onToggleSiteSetting.bind(this, 'safeBrowsing')
this.onToggleNoScript = this.onToggleSiteSetting.bind(this, 'noScript')
this.onToggleCookieControl = this.onToggleSiteSetting.bind(this, 'cookieControl')
this.onToggleHTTPSE = this.onToggleSiteSetting.bind(this, 'httpsEverywhere')
this.onToggleFp = this.onToggleSiteSetting.bind(this, 'fingerprintingProtection')
this.onReload = this.onReload.bind(this)
}
get isBlockingTrackedContent () {
Expand Down Expand Up @@ -58,9 +60,18 @@ class BraveryPanel extends ImmutableComponent {
get isBlockedScriptsShown () {
return this.props.braveryPanelDetail.get('expandNoScript')
}
get isBlockingFingerprinting () {
return this.blockedFingerprinting && this.blockedFingerprinting.size > 0
}
get blockedFingerprinting () {
return this.props.frameProps.getIn(['fingerprintingProtection', 'blocked'])
}
get isHttpseShown () {
return this.props.braveryPanelDetail.get('expandHttpse')
}
get isFpShown () {
return this.props.braveryPanelDetail.get('expandFp')
}
get redirectedResources () {
return this.props.frameProps.get('httpsEverywhere')
}
Expand Down Expand Up @@ -95,6 +106,12 @@ class BraveryPanel extends ImmutableComponent {
})
e.stopPropagation()
}
onToggleFpList (e) {
windowActions.setBraveryPanelDetail({
expandFp: !this.isFpShown
})
e.stopPropagation()
}
onToggleNoScriptList (e) {
windowActions.setBraveryPanelDetail({
expandNoScript: !this.isBlockedScriptsShown
Expand Down Expand Up @@ -140,8 +157,10 @@ class BraveryPanel extends ImmutableComponent {
const noScriptEnabled = this.getSiteSetting('noScript', this.props.braveryDefaults.noScript)
const httpseEnabled = this.getSiteSetting('httpsEverywhere', this.props.braveryDefaults.httpsEverywhere)
const adControl = this.getSiteSetting('adControl', this.props.braveryDefaults.adControl)
const fpEnabled = this.getSiteSetting('fingerprintingProtection', this.props.braveryDefaults.fingerprintingProtection)
const adsBlockedStat = (this.blockedAds ? this.blockedAds.size : 0) + (this.blockedByTrackingList ? this.blockedByTrackingList.size : 0)
const scriptsBlockedStat = this.blockedScripts ? this.blockedScripts.size : 0
const fpBlockedStat = this.blockedFingerprinting ? this.blockedFingerprinting.size : 0
return <Dialog onHide={this.props.onHide} className='braveryPanelContainer' isClickDismiss>
<div className='braveryPanel' onClick={(e) => e.stopPropagation()}>
<div className='braveryPanelHeader'>
Expand Down Expand Up @@ -177,6 +196,13 @@ class BraveryPanel extends ImmutableComponent {
<div className='braveryStat noScriptStat'>{scriptsBlockedStat}</div>
<div data-l10n-id='scriptsBlockedNumber' />
</div>
<div onClick={this.onToggleFpList} className={cx({
statClickable: !!fpBlockedStat,
statDisabled: !shieldsUp || !fpEnabled
})}>
<div className='braveryStat fpStat'>{fpBlockedStat}</div>
<div data-l10n-id='fingerprintingBlocked' />
</div>
</div>
<div className='braveryPanelBody'>
<ul>
Expand Down Expand Up @@ -216,6 +242,16 @@ class BraveryPanel extends ImmutableComponent {
</ul></li>
: null
}
{
this.isBlockingFingerprinting && this.isFpShown
? <li><ul>
{
this.blockedFingerprinting.map((site) =>
<li key={site}>{site}</li>)
}
</ul></li>
: null
}
</ul>
<div className={cx({
braveryAdvancedTitle: true,
Expand Down Expand Up @@ -245,7 +281,7 @@ class BraveryPanel extends ImmutableComponent {
<option data-l10n-id='allowAdsAndTracking' value='allowAdsAndTracking' />
</select>
<SwitchControl onClick={this.onToggleHTTPSE} rightl10nId='httpsEverywhere' checkedOn={httpseEnabled} disabled={!shieldsUp} />
<SwitchControl onClick={this.onToggleSafeBrowsing} rightl10nId='safeBrowsing' checkedOn={this.getSiteSetting('safeBrowsing', this.props.braveryDefaults.safeBrowsing)} disabled={!shieldsUp} />
<SwitchControl onClick={this.onToggleNoScript} rightl10nId='noScript' checkedOn={noScriptEnabled} disabled={!shieldsUp} />
</div>
<div className='braveryControlGroup'>
<div className={cx({
Expand All @@ -256,7 +292,8 @@ class BraveryPanel extends ImmutableComponent {
<option data-l10n-id='block3rdPartyCookie' value='block3rdPartyCookie' />
<option data-l10n-id='allowAllCookies' value='allowAllCookies' />
</select>
<SwitchControl onClick={this.onToggleNoScript} rightl10nId='noScript' checkedOn={noScriptEnabled} disabled={!shieldsUp} />
<SwitchControl onClick={this.onToggleFp} rightl10nId='fingerprintingProtection' checkedOn={fpEnabled} disabled={!shieldsUp} />
<SwitchControl onClick={this.onToggleSafeBrowsing} rightl10nId='safeBrowsing' checkedOn={this.getSiteSetting('safeBrowsing', this.props.braveryDefaults.safeBrowsing)} disabled={!shieldsUp} />
</div>
</div></span>
: null
Expand Down
4 changes: 2 additions & 2 deletions js/components/frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ class Frame extends ImmutableComponent {
ipc.send(messages.CHECK_CERT_ERROR_ACCEPTED, parsedUrl.host, this.props.frame.get('key'))
}
}
if (getSetting(settings.BLOCK_CANVAS_FINGERPRINTING)) {
if (this.props.enableFingerprintingProtection) {
this.webview.send(messages.BLOCK_CANVAS_FINGERPRINTING)
}
windowActions.updateBackForwardState(
Expand Down Expand Up @@ -473,7 +473,7 @@ class Frame extends ImmutableComponent {
})
this.webview.addEventListener('load-start', (e) => {
loadStart(e)
if (getSetting(settings.BLOCK_CANVAS_FINGERPRINTING)) {
if (this.props.enableFingerprintingProtection) {
this.webview.send(messages.BLOCK_CANVAS_FINGERPRINTING)
}
})
Expand Down
28 changes: 28 additions & 0 deletions js/components/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,18 @@ class Main extends ImmutableComponent {
windowActions.setRedirectedBy(frameProps, ruleset, details.url))
})

ipc.on(messages.GOT_CANVAS_FINGERPRINTING, (e, details) => {
if (!details.length) {
return
}
details.forEach((detail) => {
const filteredFrameProps = this.props.windowState.get('frames').filter((frame) => frame.get('location') === detail.url)
const description = [detail.type, detail.scriptUrl || detail.url].join(': ')
filteredFrameProps.forEach((frameProps) =>
windowActions.setBlockedBy(frameProps, 'fingerprintingProtection', description))
})
})

ipc.on(messages.SHOW_NOTIFICATION, (e, text) => {
void new window.Notification(text)
})
Expand Down Expand Up @@ -440,6 +452,20 @@ class Main extends ImmutableComponent {
return enabled
}

get enableFingerprintingProtection () {
if (this.activeSiteSettings) {
if (this.activeSiteSettings.get('shieldsUp') === false) {
return false
}

if (typeof this.activeSiteSettings.get('fingerprintingProtection') === 'boolean') {
return this.activeSiteSettings.get('fingerprintingProtection')
}
}

return getSetting(settings.BLOCK_CANVAS_FINGERPRINTING) || false
}

onCloseFrame (activeFrameProps) {
windowActions.closeFrame(this.props.windowState.get('frames'), activeFrameProps)
}
Expand Down Expand Up @@ -563,6 +589,7 @@ class Main extends ImmutableComponent {
braveryDefaults.adControl = 'blockAds'
}
braveryDefaults.cookieControl = blockCookies ? 'block3rdPartyCookie' : 'allowAllCookies'
braveryDefaults.fingerprintingProtection = getSetting(settings.BLOCK_CANVAS_FINGERPRINTING)
return braveryDefaults
}

Expand Down Expand Up @@ -770,6 +797,7 @@ class Main extends ImmutableComponent {
activeSiteSettings={activeSiteSettings}
enableAds={this.enableAds}
enableNoScript={this.enableNoScript}
enableFingerprintingProtection={this.enableFingerprintingProtection}
isPreview={frame.get('key') === this.props.windowState.get('previewFrameKey')}
isActive={FrameStateUtil.isFrameKeyActive(this.props.windowState, frame.get('key'))}
/>)
Expand Down
6 changes: 4 additions & 2 deletions js/stores/windowStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ const doAction = (action) => {
noScript: {},
themeColor: undefined,
title: '',
trackingProtection: {}
trackingProtection: {},
fingerprintingProtection: {}
})
}
updateNavBarInput(action.location, frameStatePath(key))
Expand Down Expand Up @@ -523,7 +524,8 @@ const doAction = (action) => {
advancedControls: action.braveryPanelDetail.advancedControls,
expandAdblock: action.braveryPanelDetail.expandAdblock,
expandHttpse: action.braveryPanelDetail.expandHttpse,
expandNoScript: action.braveryPanelDetail.expandNoScript
expandNoScript: action.braveryPanelDetail.expandNoScript,
expandFp: action.braveryPanelDetail.expandFp
})
}
break
Expand Down
6 changes: 6 additions & 0 deletions less/forms.less
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,19 @@
&.redirectedResourcesStat {
color: #0796fa;
}
&.fpStat {
color: #faae5a;
}
}
.statDisabled {
opacity: 0.3;
}
.statClickable {
cursor: pointer;
}
&>div {
max-width: 75px;
}
}

.braveryPanelBody {
Expand Down

1 comment on commit d83b16b

@bbondy
Copy link
Member

@bbondy bbondy commented on d83b16b May 29, 2016

Choose a reason for hiding this comment

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

sweet ++

Please sign in to comment.