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

Commit

Permalink
add a cookie manager
Browse files Browse the repository at this point in the history
this allows users to view all the cookies, sort them, and delete individual ones or in bulk.

fix #1991

todo: add ability to edit cookies and add to global whitelist/blacklist
  • Loading branch information
diracdeltas committed Oct 12, 2017
1 parent afe7114 commit 492e7fd
Show file tree
Hide file tree
Showing 21 changed files with 396 additions and 4 deletions.
9 changes: 9 additions & 0 deletions app/browser/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,15 @@ const createHistorySubmenu = () => {
click: function (item, focusedWindow) {
CommonMenu.sendToFocusedWindow(focusedWindow, [messages.SHORTCUT_OPEN_CLEAR_BROWSING_DATA_PANEL])
}
},
{
label: locale.translation('manageCookies'),
click: function (item, focusedWindow) {
appActions.createTabRequested({
url: 'about:cookies',
windowId: focusedWindow.id
})
}
}
]
const recentlyClosedItems = menuUtil.createRecentlyClosedTemplateItems(closedFrames)
Expand Down
7 changes: 7 additions & 0 deletions app/browser/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const historyState = require('../common/state/historyState')
const bookmarkOrderCache = require('../common/cache/bookmarkOrderCache')
const ledgerState = require('../common/state/ledgerState')
const {getWindow} = require('./windows')
const filtering = require('../filtering')

let currentPartitionNumber = 0
const incrementPartitionNumber = () => ++currentPartitionNumber
Expand Down Expand Up @@ -291,6 +292,12 @@ const updateAboutDetails = (tab, tabValue) => {
}
} else if (location === 'about:brave') {
tab.send(messages.VERSION_INFORMATION_UPDATED, versionInformation.toJS())
} else if (location === 'about:cookies') {
filtering.cookies.getAll((cookies) => {
if (!tab.isDestroyed()) {
tab.send(messages.COOKIES_UPDATED, cookies)
}
})
}
// send state to about pages
if (aboutUrls.get(location) && aboutDetails) {
Expand Down
21 changes: 21 additions & 0 deletions app/extensions/brave/about-cookies.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<!-- 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/. -->
<html>
<head>
<meta charset="utf-8">
<meta name="availableLanguages" content="">
<meta name="defaultLanguage" content="en-US">
<meta name='theme-color' content='#ff5000'>
<meta name="referrer" content="no-referrer">
<link rel="shortcut icon"type="image/x-icon" href="img/favicon.ico">
<title data-l10n-id="cookiesTitle"></title>
<script src="ext/l20n.min.js"></script>
<script src="gen/aboutPages.entry.js" async></script>
<link rel="localization" href="locales/{locale}/cookies.properties">
</head>
<body>
<div id="appContainer"/>
</body>
</html>
3 changes: 3 additions & 0 deletions app/extensions/brave/locales/en-US/cookies.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
noCookiesSaved=No cookies saved
cookiesTitle=Manage Cookies
clearCookies=Delete all cookies
7 changes: 6 additions & 1 deletion app/extensions/brave/locales/en-US/menu.properties
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ cleanReload=Clean Reload
clearBrowsingData=Clear Browsing Data…
clearCache=Clear Cache…
clearHistory=Clear History…
manageCookies=Manage Cookies…
clearSiteData=Clear All Cookies and Site Data…
clone=Clone
closeOtherTabs=Close other Tabs
closeTab=Close
closeTabPage=Close tab page
closeWindow=Close Window
copy=Copy
copyToClipboard=Copy to clipboard
copyEmailAddress=Copy Email Address
copyImage=Copy Image
copyImageAddress=Copy Image Address
Expand All @@ -46,6 +48,8 @@ cut=Cut
delete=Delete
deleteBookmark=Delete Bookmark
deleteBookmarks=Delete Selected Bookmarks
deleteCookie=Delete Cookie
deleteCookies=Delete Selected Cookies
deleteFolder=Delete Folder
deleteHistoryEntries=Delete Selected History Entries
deleteHistoryEntry=Delete History Entry
Expand All @@ -68,6 +72,7 @@ downloadsManager=Downloads…
downloadToolbarHide=Hide downloads bar
edit=Edit
editBookmark=Edit Bookmark…
editCookie=Edit cookie…
editFolder=Edit Folder…
emailPageLink=Email Page Link…
exportBookmarks=Export Bookmarks…
Expand Down Expand Up @@ -172,4 +177,4 @@ window=Window
zoom=Zoom
zoom=Zoom
zoomIn=Zoom In
zoomOut=Zoom Out
zoomOut=Zoom Out
1 change: 1 addition & 0 deletions app/extensions/brave/locales/en-US/preferences.properties
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ loveToHear=We'd love to hear from you.
manageAdblockSettings=Manage Adblock Settings…
manageAutofillData=Manage Autofill Data…
managePasswords=Manage passwords…
manageCookies=Manage cookies…
mediaPermission=Camera and microphone access
midiSysexPermission=Use web MIDI
minimumPageTimeHigh=1 minute
Expand Down
28 changes: 28 additions & 0 deletions app/filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,34 @@ module.exports.isResourceEnabled = (resourceName, url, isPrivate) => {
return false
}

/**
* Cookie methods
*/
module.exports.cookies = {
getAll: (cb) => {
const cookiesMap = {}
for (let partition in registeredSessions) {
const ses = registeredSessions[partition]
ses.cookies.get({}, (error, cookies) => {
if (error) { console.error(error) }
cookiesMap[partition] = cookies
if (Object.keys(cookiesMap).length ===
Object.keys(registeredSessions).length) {
cb(cookiesMap)
}
})
}
},
remove: (url, name, partition, cb) => {
const ses = registeredSessions[partition]
if (ses) {
ses.cookies.remove(url, name, cb || function () {})
} else {
console.error('No session to remove cookies for: ' + partition)
}
}
}

/**
* Clears all storage data.
* This includes: appcache, cookies, filesystem, indexdb, local storage,
Expand Down
4 changes: 4 additions & 0 deletions app/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ var rendererIdentifiers = function () {
'deleteFolder',
'deleteBookmark',
'deleteBookmarks',
'deleteCookie',
'deleteCookies',
'deleteHistoryEntry',
'deleteHistoryEntries',
'deleteLedgerEntry',
Expand All @@ -66,6 +68,7 @@ var rendererIdentifiers = function () {
'ledgerBackupText3',
'ledgerBackupText4',
'ledgerBackupText5',
'editCookie', // not yet implemented
'editFolder',
'editBookmark',
'unmuteTabs',
Expand Down Expand Up @@ -130,6 +133,7 @@ var rendererIdentifiers = function () {
'clearHistory',
'clearSiteData',
'clearBrowsingData',
'manageCookies',
'recentlyClosed',
'recentlyVisited',
'bookmarks',
Expand Down
18 changes: 17 additions & 1 deletion app/renderer/components/common/sortableTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
const React = require('react')
const Immutable = require('immutable')
const tableSort = require('tablesort')
const KeyCodes = require('../../../common/constants/keyCodes')

const {StyleSheet, css} = require('aphrodite/no-important')
const globalStyles = require('../styles/global')
Expand All @@ -26,6 +27,7 @@ class SortableTable extends React.Component {
super(props)
this.onClick = this.onClick.bind(this)
this.onContextMenu = this.onContextMenu.bind(this)
this.onKeyDown = this.onKeyDown.bind(this)
this.onTableDragStart = this.onTableDragStart.bind(this)
this.state = {
selection: Immutable.Set()
Expand All @@ -41,6 +43,7 @@ class SortableTable extends React.Component {
if (this.props.rows &&
(!prevProps.rows ||
prevProps.rows.length !== this.props.rows.length)) {
this.clearSelection()
this.sortTable.refresh()
}
}
Expand Down Expand Up @@ -228,7 +231,17 @@ class SortableTable extends React.Component {
} else {
this.props.onContextMenu(handlerInputs, this.props.contextMenuName, e)
}
this.clearSelection()
}
}
/**
* Handle keydown
*/
onKeyDown (e) {
if (e.keyCode === KeyCodes.BACKSPACE && this.props.onDelete) {
const handlerInputs = this.getSelectedRowObjects()
if (handlerInputs) {
this.props.onDelete(handlerInputs)
}
}
}
/**
Expand Down Expand Up @@ -300,6 +313,8 @@ class SortableTable extends React.Component {
tableAttributes.draggable = true
}
}
tableAttributes.tabIndex = 0
tableAttributes.onKeyDown = this.onKeyDown
return tableAttributes
}
getRowAttributes (row, index, bodyIndex) {
Expand Down Expand Up @@ -508,6 +523,7 @@ const styles = StyleSheet.create({
// It can be specified by setting css to tableClassNames.
// See 'styles.devices__devicesList' on syncTab.js for example.
table: {
outline: 'none',
boxSizing: 'border-box',
cursor: 'default',
borderSpacing: 0,
Expand Down
7 changes: 7 additions & 0 deletions js/about/aboutActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ const aboutActions = {
})
},

removeCookies: function (cookies) {
aboutActions.dispatchAction({
actionType: appConstants.APP_REMOVE_COOKIES,
cookies
})
},

setResourceEnabled: function (resourceName, enabled) {
aboutActions.dispatchAction({
actionType: appConstants.APP_SET_RESOURCE_ENABLED,
Expand Down
139 changes: 139 additions & 0 deletions js/about/cookies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/* 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/. */

const React = require('react')
const SortableTable = require('../../app/renderer/components/common/sortableTable')
const aboutActions = require('./aboutActions')
const messages = require('../constants/messages')
const moment = require('moment')

const {StyleSheet, css} = require('aphrodite/no-important')

require('../../less/about/common.less')
require('../../node_modules/font-awesome/css/font-awesome.css')

const ipc = window.chrome.ipcRenderer

const COOKIE_FIELDS = ['domain', 'name', 'value', 'path', 'expirationDate', 'secure', 'httpOnly', 'session', 'hostOnly', 'partition'] // TODO: add the sameSite field
const INFO_URL = 'https://developer.chrome.com/extensions/cookies#type-Cookie'

class AboutCookies extends React.Component {
constructor (props) {
super(props)
this.state = {
cookies: []
}
ipc.on(messages.COOKIES_UPDATED, (e, cookies) => {
const allCookies = []
for (let partition in cookies) {
cookies[partition].forEach((cookie) => {
cookie.partition = partition
allCookies.push(cookie)
})
}
this.setState({
cookies: allCookies
})
})
}

get isCookiesEmpty () {
return this.state.cookies.length === 0
}

get cookiesTable () {
return <SortableTable
fillAvailable
className={css(styles.cookieTable)}
headings={COOKIE_FIELDS}
defaultHeading='domain'
addHoverClass
multiSelect
contextMenuName='cookies'
onContextMenu={aboutActions.contextMenu}
onDelete={aboutActions.removeCookies}
rowObjects={this.state.cookies}
rows={this.state.cookies.map((cookie) => {
return COOKIE_FIELDS.map((fieldName) => {
const value = cookie[fieldName]
let displayValue = value
if (typeof value === 'number' && fieldName === 'expirationDate') {
displayValue = moment.unix(value).format('YYYY-MM-DD HH:mm:ss Z')
} else if (value === null || value === undefined) {
displayValue = ''
}
return {
value,
html: <div title={displayValue} className={css(styles.cookieColumn)}>{displayValue}</div>
}
})
})}
/>
}

componentDidMount () {
window.addEventListener('load', () => {
const th = document.querySelector('th')
if (th) { th.click() }
})
}

render () {
return <div className={css(styles.cookiesPage)}>
<div className={css(styles.cookiesTitleWrapper)}>
<h1 data-l10n-id='cookiesTitle' className={css(styles.cookiesTitle)} />
<span className='fa fa-info-circle infoCircle' onClick={
aboutActions.createTabRequested.bind(null, {
url: INFO_URL
})
} />
{
this.isCookiesEmpty
? null
: <span className={css(styles.clearCookiesLink)}
data-l10n-id='clearCookies'
onClick={aboutActions.removeCookies.bind(null, null)} />
}
</div>
{
this.isCookiesEmpty
? <div data-l10n-id='noCookiesSaved' />
: this.cookiesTable
}
</div>
}
}

const styles = StyleSheet.create({
cookiesPage: {
userSelect: 'none',
margin: '20px'
},
clearCookiesLink: {
color: 'grey',
cursor: 'pointer',
marginTop: '5px',
float: 'right',
textDecoration: 'underline'
},
cookiesTitle: {
display: 'inline',
userSelect: 'text',
marginRight: '10px'
},
cookiesTitleWrapper: {
marginBottom: '20px'
},
cookieTable: {
width: '100%'
},
cookieColumn: {
maxWidth: '350px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
})

module.exports = <AboutCookies />
3 changes: 3 additions & 0 deletions js/about/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ switch (getBaseUrl(getSourceAboutUrl(window.location.href))) {
case 'about:certerror':
element = require('./certerror')
break
case 'about:cookies':
element = require('./cookies')
break
case 'about:downloads':
element = require('./downloads')
break
Expand Down
Loading

0 comments on commit 492e7fd

Please sign in to comment.