├── py-scripts ├── lib │ ├── __init__.py │ └── env_util.py ├── copy-brave-extension-localization.py └── build-brave-extension.py ├── test ├── mocha.opts ├── app │ ├── background │ │ ├── storeTest.ts │ │ ├── reducersTest.ts │ │ ├── api │ │ │ ├── localeAPITest.ts │ │ │ ├── tabsAPITest.ts │ │ │ └── browserActionAPITest.ts │ │ ├── events │ │ │ ├── shieldsEventsTest.ts │ │ │ ├── windowsEventsTest.ts │ │ │ ├── runtimeEventsTest.ts │ │ │ └── tabsEventsTest.ts │ │ └── windowActionsTest.ts │ ├── actions │ │ ├── webNavigationActionsTest.ts │ │ ├── windowActionsTest.ts │ │ ├── cosmeticFilterActionsTest.ts │ │ ├── tabActionsTest.ts │ │ └── shieldsPanelActionsTest.ts │ ├── components │ │ ├── noScript │ │ │ └── noScriptTest.tsx │ │ └── braveShields │ │ │ ├── braveShieldsFooterTest.tsx │ │ │ └── braveShieldsHeaderTest.tsx │ └── helpers │ │ └── urlUtilsTest.ts ├── setupApp.ts ├── func.ts ├── e2e │ └── braveShieldsPanel.ts └── testData.ts ├── webpack ├── postcss.config.js ├── .eslintrc ├── test.config.js ├── customPublicPath.js ├── prod.config.js ├── dev.config.js └── replace │ ├── JsonpMainTemplate.runtime.js │ └── process-update.js ├── app ├── constants │ ├── runtimeActionTypes.ts │ ├── webNavigationTypes.ts │ ├── tabTypes.ts │ ├── windowTypes.ts │ ├── cosmeticFilterTypes.ts │ ├── resourceIdentifiers.ts │ └── shieldsPanelTypes.ts ├── assets │ ├── img │ │ ├── icon-16.png │ │ ├── icon-32.png │ │ ├── icon-48.png │ │ ├── icon-64.png │ │ ├── icon-128.png │ │ └── icon-256.png │ └── bravelizer.css ├── views │ ├── background.pug │ ├── inject.pug │ └── braveShieldsPanel.pug ├── helpers │ ├── arrayUtils.ts │ └── urlUtils.ts ├── types │ ├── actions │ │ ├── runtimeActions.ts │ │ ├── index.ts │ │ ├── webNavigationActions.ts │ │ ├── windowActions.ts │ │ ├── tabActions.ts │ │ ├── cosmeticFilterActions.ts │ │ └── shieldsPanelActions.ts │ ├── global │ │ ├── tests.d.ts │ │ ├── chrome.d.ts │ │ └── react-chrome-redux.d.ts │ ├── state │ │ ├── mainState.ts │ │ └── shieldsPannelState.ts │ ├── other │ │ ├── noScriptInfo.ts │ │ └── blockTypes.ts │ ├── constants │ │ ├── webNavigationTypes.ts │ │ ├── tabTypes.ts │ │ ├── windowTypes.ts │ │ ├── cosmeticFilterTypes.ts │ │ ├── resourceIdentifiers.ts │ │ └── shieldsPanelTypes.ts │ └── adblock │ │ └── adblockTypes.ts ├── actions │ ├── runtimeActions.ts │ ├── windowActions.ts │ ├── webNavigationActions.ts │ ├── tabActions.ts │ ├── cosmeticFilterActions.ts │ └── shieldsPanelActions.ts ├── background │ ├── actions │ │ ├── tabActions.ts │ │ ├── windowActions.ts │ │ ├── runtimeActions.ts │ │ ├── shieldsPanelActions.ts │ │ ├── webNavigationActions.ts │ │ └── cosmeticFilterActions.ts │ ├── events.ts │ ├── reducers │ │ └── runtimeReducer.ts │ ├── api │ │ ├── localeAPI.ts │ │ ├── tabsAPI.ts │ │ ├── cosmeticFilterAPI.ts │ │ └── browserActionAPI.ts │ ├── events │ │ ├── shieldsEvents.ts │ │ ├── windowsEvents.ts │ │ ├── tabsEvents.ts │ │ ├── webNavigationEvents.ts │ │ ├── runtimeEvents.ts │ │ └── cosmeticFilterEvents.ts │ ├── reducers.ts │ └── store.ts ├── content.ts ├── containers │ └── braveShields.tsx ├── braveShieldsPanel.tsx ├── background.ts ├── manifest.prod.json ├── manifest.dev.json ├── components │ ├── braveShields │ │ ├── braveShieldsFooter.tsx │ │ ├── braveShieldsHeader.tsx │ │ └── braveShields.tsx │ └── noScript │ │ └── noScript.tsx ├── theme.ts └── _locales │ ├── zh_TW │ └── messages.json │ ├── ko │ └── messages.json │ ├── ja │ └── messages.json │ ├── he │ └── messages.json │ ├── am │ └── messages.json │ ├── bn │ └── messages.json │ ├── et │ └── messages.json │ ├── fa │ └── messages.json │ ├── gu │ └── messages.json │ ├── hr │ └── messages.json │ ├── kn │ └── messages.json │ └── lt │ └── messages.json ├── .babelrc ├── tslint.json ├── .vscode └── settings.json ├── appveyor.yml ├── scripts ├── lib │ └── execute.js ├── tests.js ├── build.js ├── dev.js ├── tasks.js └── compress.js ├── tsconfig.json ├── .travis.yml ├── .gitignore ├── README.md └── package.json /py-scripts/lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ts-node/register 2 | --recursive 3 | -------------------------------------------------------------------------------- /webpack/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | ] 4 | } 5 | -------------------------------------------------------------------------------- /app/constants/runtimeActionTypes.ts: -------------------------------------------------------------------------------- 1 | export const RUNTIME_DID_STARTUP = 'RUNTIME_DID_STARTUP' 2 | -------------------------------------------------------------------------------- /app/assets/img/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diracdeltas/brave-extension/master/app/assets/img/icon-16.png -------------------------------------------------------------------------------- /app/assets/img/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diracdeltas/brave-extension/master/app/assets/img/icon-32.png -------------------------------------------------------------------------------- /app/assets/img/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diracdeltas/brave-extension/master/app/assets/img/icon-48.png -------------------------------------------------------------------------------- /app/assets/img/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diracdeltas/brave-extension/master/app/assets/img/icon-64.png -------------------------------------------------------------------------------- /app/assets/img/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diracdeltas/brave-extension/master/app/assets/img/icon-128.png -------------------------------------------------------------------------------- /app/assets/img/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diracdeltas/brave-extension/master/app/assets/img/icon-256.png -------------------------------------------------------------------------------- /webpack/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "import/no-extraneous-dependencies": ["error", { "devDependencies": true }] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "react"], 3 | "plugins": ["add-module-exports", "transform-decorators-legacy", "transform-runtime"] 4 | } 5 | -------------------------------------------------------------------------------- /app/views/background.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | html 4 | head 5 | script(src=env == 'prod' ? '/js/background.bundle.js' : 'http://localhost:3000/js/background.bundle.js') 6 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint-react", "tslint-config-standard"], 3 | "linterOptions": { 4 | "exclude": [ 5 | "build/", 6 | "dev/" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /webpack/test.config.js: -------------------------------------------------------------------------------- 1 | // for babel-plugin-webpack-loaders 2 | const config = require('./prod.config') 3 | 4 | module.exports = { 5 | output: { 6 | libraryTarget: 'commonjs2' 7 | }, 8 | module: { 9 | loaders: config.module.loaders.slice(1) // remove babel-loader 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/helpers/arrayUtils.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const unique = (arr: Array) => [...new Set(arr)] 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnPaste": true, 3 | "editor.tabSize": 2, 4 | "prettier.semi": false, 5 | "javascript.preferences.quoteStyle": "auto", 6 | "typescript.preferences.quoteStyle": "auto", 7 | "prettier.singleQuote": true, 8 | "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true 9 | } -------------------------------------------------------------------------------- /app/types/actions/runtimeActions.ts: -------------------------------------------------------------------------------- 1 | import * as types from '../../constants/runtimeActionTypes' 2 | 3 | interface RuntimeDidStartupReturn { 4 | type: typeof types.RUNTIME_DID_STARTUP 5 | } 6 | 7 | export interface RuntimeDidStartup { 8 | (): RuntimeDidStartupReturn 9 | } 10 | 11 | export type runtimeActions = RuntimeDidStartupReturn 12 | -------------------------------------------------------------------------------- /app/types/global/tests.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'deep-freeze-node' 2 | declare module 'chromedriver' 3 | 4 | // Used in tests 5 | declare namespace NodeJS { 6 | interface Global { 7 | requestAnimationFrame: any 8 | chrome: any 9 | window: any 10 | HTMLElement: any 11 | navigator: any 12 | document: any 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/constants/webNavigationTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const ON_BEFORE_NAVIGATION = 'ON_BEFORE_NAVIGATION' 6 | export const ON_COMMITTED = 'ON_COMMITTED' 7 | -------------------------------------------------------------------------------- /app/types/state/mainState.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as shield from './shieldsPannelState' 6 | 7 | export interface State { 8 | shieldsPanel: shield.State 9 | } 10 | -------------------------------------------------------------------------------- /app/helpers/urlUtils.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const isHttpOrHttps = (url?: string) => { 6 | if (!url) { 7 | return false 8 | } 9 | return /^https?:/i.test(url) 10 | } 11 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '6' 4 | - nodejs_version: '7' 5 | 6 | cache: 7 | - node_modules 8 | 9 | install: 10 | - ps: Install-Product node $env:nodejs_version 11 | - npm install 12 | 13 | test_script: 14 | - node --version 15 | - npm --version 16 | - npm run lint 17 | - npm run test 18 | - npm run build 19 | 20 | build: off 21 | -------------------------------------------------------------------------------- /app/constants/tabTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const ACTIVE_TAB_CHANGED = 'ACTIVE_TAB_CHANGED' 6 | export const TAB_DATA_CHANGED = 'TAB_DATA_CHANGED' 7 | export const TAB_CREATED = 'TAB_CREATED' 8 | -------------------------------------------------------------------------------- /app/constants/windowTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const WINDOW_FOCUS_CHANGED = 'WINDOW_FOCUS_CHANGED' 6 | export const WINDOW_CREATED = 'WINDOW_CREATED' 7 | export const WINDOW_REMOVED = 'WINDOW_REMOVED' 8 | -------------------------------------------------------------------------------- /app/actions/runtimeActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/runtimeActionTypes' 6 | 7 | export function runtimeDidStartup () { 8 | return { 9 | type: types.RUNTIME_DID_STARTUP 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/types/other/noScriptInfo.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export interface NoScriptEntry { 6 | actuallyBlocked: boolean 7 | willBlock: boolean 8 | } 9 | 10 | export interface NoScriptInfo { 11 | [key: string]: NoScriptEntry 12 | } 13 | -------------------------------------------------------------------------------- /app/background/actions/tabActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { bindActionCreators } from 'redux' 6 | import store from '../store' 7 | import * as tabActions from '../../actions/tabActions' 8 | export default bindActionCreators(tabActions, store.dispatch) 9 | -------------------------------------------------------------------------------- /app/types/constants/webNavigationTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../../constants/webNavigationTypes' 6 | 7 | export type ON_BEFORE_NAVIGATION = typeof types.ON_BEFORE_NAVIGATION 8 | export type ON_COMMITTED = typeof types.ON_COMMITTED 9 | -------------------------------------------------------------------------------- /app/background/actions/windowActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { bindActionCreators } from 'redux' 6 | import store from '../store' 7 | import * as windowActions from '../../actions/windowActions' 8 | export default bindActionCreators(windowActions, store.dispatch) 9 | -------------------------------------------------------------------------------- /app/background/actions/runtimeActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { bindActionCreators } from 'redux' 6 | import store from '../store' 7 | import * as runtimeActions from '../../actions/runtimeActions' 8 | export default bindActionCreators(runtimeActions, store.dispatch) 9 | -------------------------------------------------------------------------------- /app/background/events.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | require('./events/windowsEvents') 6 | require('./events/tabsEvents') 7 | require('./events/shieldsEvents') 8 | require('./events/runtimeEvents') 9 | require('./events/webNavigationEvents') 10 | require('./events/cosmeticFilterEvents') 11 | -------------------------------------------------------------------------------- /app/background/actions/shieldsPanelActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { bindActionCreators } from 'redux' 6 | import store from '../store' 7 | import * as shieldsPanelActions from '../../actions/shieldsPanelActions' 8 | export default bindActionCreators(shieldsPanelActions, store.dispatch) 9 | -------------------------------------------------------------------------------- /app/background/actions/webNavigationActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { bindActionCreators } from 'redux' 6 | import store from '../store' 7 | import * as webNavigationActions from '../../actions/webNavigationActions' 8 | export default bindActionCreators(webNavigationActions, store.dispatch) 9 | -------------------------------------------------------------------------------- /app/background/actions/cosmeticFilterActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { bindActionCreators } from 'redux' 6 | import store from '../store' 7 | import * as cosmeticFilterActions from '../../actions/cosmeticFilterActions' 8 | export default bindActionCreators(cosmeticFilterActions, store.dispatch) 9 | -------------------------------------------------------------------------------- /app/types/constants/tabTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../../constants/tabTypes' 6 | 7 | export type ACTIVE_TAB_CHANGED = typeof types.ACTIVE_TAB_CHANGED 8 | export type TAB_CREATED = typeof types.TAB_CREATED 9 | export type TAB_DATA_CHANGED = typeof types.TAB_DATA_CHANGED 10 | -------------------------------------------------------------------------------- /app/types/constants/windowTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../../constants/windowTypes' 6 | 7 | export type WINDOW_CREATED = typeof types.WINDOW_CREATED 8 | export type WINDOW_FOCUS_CHANGED = typeof types.WINDOW_FOCUS_CHANGED 9 | export type WINDOW_REMOVED = typeof types.WINDOW_REMOVED 10 | -------------------------------------------------------------------------------- /app/content.ts: -------------------------------------------------------------------------------- 1 | const unique = require('unique-selector').default 2 | 3 | function getCurrentURL () { 4 | return window.location.hostname 5 | } 6 | 7 | document.addEventListener('contextmenu', (event) => { 8 | let selector = unique(event.target) // this has to be done here, events can't be passed through the messaging API 9 | let baseURI = getCurrentURL() 10 | console.log(selector, baseURI) 11 | chrome.runtime.sendMessage({ 12 | selector: selector, 13 | baseURI: baseURI 14 | }) 15 | }, true) 16 | -------------------------------------------------------------------------------- /app/views/inject.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | html 4 | head 5 | meta(charset='UTF-8') 6 | title Redux TodoMVC Example (Inject) 7 | style. 8 | html, body { 9 | background-color: rgba(0,0,0,0) 10 | } 11 | body 12 | #root 13 | if env !== 'prod' 14 | script(src='chrome-extension://lmhkpmbekcpmknklioeibfkpmmfibljd/js/redux-devtools-extension.js') 15 | script(src=env == 'prod' ? '/js/braveShieldsPanel.bundle.js' : 'https://localhost:3000/js/braveShieldsPanel.bundle.js') 16 | -------------------------------------------------------------------------------- /app/background/reducers/runtimeReducer.ts: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../types/actions' 2 | import * as runtimeActions from '../../constants/runtimeActionTypes' 3 | import * as browserActionAPI from '../api/browserActionAPI' 4 | 5 | type State = { } 6 | 7 | export default function runtimeReducer (state: State = { }, action: Actions): State { 8 | switch (action.type) { 9 | case runtimeActions.RUNTIME_DID_STARTUP: { 10 | browserActionAPI.init() 11 | break 12 | } 13 | } 14 | return state 15 | } 16 | -------------------------------------------------------------------------------- /app/constants/cosmeticFilterTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const SITE_COSMETIC_FILTER_REMOVED = 'SITE_COSMETIC_FILTER_REMOVED' 6 | export const SITE_COSMETIC_FILTER_ADDED = 'SITE_COSMETIC_FILTER_ADDED' 7 | export const LOGGED_STORAGE = 'LOGGED_STORAGE' 8 | export const ALL_COSMETIC_FILTERS_REMOVED = 'ALL_COSMETIC_FILTERS_REMOVED' 9 | -------------------------------------------------------------------------------- /app/types/other/blockTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export type BlockTypes = 'ads' | 'trackers' | 'httpUpgradableResources' | 'javascript' | 'fingerprinting' 6 | export type BlockOptions = 'allow' | 'block' 7 | export type BlockFPOptions = 'allow' | 'block' | 'block_third_party' 8 | export type BlockCookiesOptions = 'allow' | 'block' | 'block_third_party' 9 | -------------------------------------------------------------------------------- /app/background/api/localeAPI.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * Gets the locale message specified in messages.json 7 | * @param {string} message - The locale string 8 | */ 9 | export const getMessage = (message: string): string => { 10 | if (chrome.i18n) { 11 | return chrome.i18n.getMessage(message) 12 | } 13 | 14 | return message 15 | } 16 | -------------------------------------------------------------------------------- /app/types/adblock/adblockTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export type BlockTypes = 'ads' | 'trackers' | 'httpUpgradableResources' | 'javascript' | 'fingerprinting' 6 | export type BlockOptions = 'allow' | 'block' 7 | export type BlockFPOptions = 'allow' | 'block' | 'block_third_party' 8 | export type BlockCookiesOptions = 'allow' | 'block' | 'block_third_party' 9 | -------------------------------------------------------------------------------- /app/types/actions/index.ts: -------------------------------------------------------------------------------- 1 | import { shieldPanelActions } from './shieldsPanelActions' 2 | import { tabActions } from './tabActions' 3 | import { webNavigationActions } from './webNavigationActions' 4 | import { windowActions } from './windowActions' 5 | import { cosmeticFilterActions } from './cosmeticFilterActions' 6 | import { runtimeActions } from './runtimeActions' 7 | 8 | export type Actions = 9 | shieldPanelActions | 10 | tabActions | 11 | webNavigationActions | 12 | windowActions | 13 | cosmeticFilterActions | 14 | runtimeActions 15 | -------------------------------------------------------------------------------- /webpack/customPublicPath.js: -------------------------------------------------------------------------------- 1 | /* global __webpack_public_path__ __HOST__ __PORT__ */ 2 | /* eslint no-global-assign: 0 camelcase: 0 */ 3 | 4 | if (process.env.NODE_ENV === 'production') { 5 | __webpack_public_path__ = chrome.extension.getURL('/js/') 6 | } else { 7 | // In development mode, 8 | const path = `//${__HOST__}:${__PORT__}/js/` 9 | if (window.location.protocol === 'https:' || window.location.search.indexOf('protocol=https') !== -1) { 10 | __webpack_public_path__ = `https:${path}` 11 | } else { 12 | __webpack_public_path__ = `http:${path}` 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/app/background/storeTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as assert from 'assert' 8 | import store from '../../../app/background/store' 9 | import { initialState } from '../../testData' 10 | 11 | describe('store test', () => { 12 | it('store can get state', function () { 13 | assert.deepEqual(store.getState(), initialState) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /app/background/events/shieldsEvents.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import actions from '../actions/shieldsPanelActions' 6 | import { BlockDetails } from '../../types/actions/shieldsPanelActions' 7 | 8 | if (chrome.braveShields) { 9 | chrome.braveShields.onBlocked.addListener((detail: BlockDetails) => { 10 | actions.resourceBlocked(detail) 11 | }) 12 | } else { 13 | console.log('chrome.braveShields not enabled') 14 | } 15 | -------------------------------------------------------------------------------- /app/views/braveShieldsPanel.pug: -------------------------------------------------------------------------------- 1 | 2 | doctype html 3 | 4 | html 5 | head 6 | meta(charset='UTF-8') 7 | title Brave Shields Panel 8 | link(rel='stylesheet', href=env == 'prod' ? '/bravelizer.css' : 'chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/bravelizer.css') 9 | style. 10 | body { 11 | width: 280px; 12 | } 13 | 14 | body 15 | #root 16 | if env !== 'prod' 17 | script(src='chrome-extension://lmhkpmbekcpmknklioeibfkpmmfibljd/js/redux-devtools-extension.js') 18 | script(src=env == 'prod' ? '/js/braveShieldsPanel.bundle.js' : 'http://localhost:3000/js/braveShieldsPanel.bundle.js') 19 | -------------------------------------------------------------------------------- /app/types/constants/cosmeticFilterTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../../constants/cosmeticFilterTypes' 6 | 7 | export type SITE_COSMETIC_FILTER_REMOVED = typeof types.SITE_COSMETIC_FILTER_REMOVED 8 | export type SITE_COSMETIC_FILTER_ADDED = typeof types.SITE_COSMETIC_FILTER_ADDED 9 | export type LOGGED_STORAGE = typeof types.LOGGED_STORAGE 10 | export type ALL_COSMETIC_FILTERS_REMOVED = typeof types.ALL_COSMETIC_FILTERS_REMOVED 11 | -------------------------------------------------------------------------------- /scripts/lib/execute.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec 2 | 3 | module.exports = function (cmds, env, cb) { 4 | if (!env) { 5 | env = {} 6 | } 7 | var cmd = '' 8 | if (!Array.isArray(cmds)) { 9 | cmds = [cmds] 10 | } 11 | cmd += cmds.join('&&') 12 | console.log(cmd) 13 | 14 | for (var key in env) { 15 | if (env.hasOwnProperty(key)) { 16 | process.env[key] = env[key] 17 | } 18 | } 19 | 20 | var r = exec(cmd, { 21 | env: process.env 22 | }, function (err) { 23 | if (cb) { 24 | cb(err) 25 | } 26 | }) 27 | r.stdout.pipe(process.stdout) 28 | r.stderr.pipe(process.stderr) 29 | } 30 | -------------------------------------------------------------------------------- /app/background/reducers.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { combineReducers } from 'redux' 6 | 7 | import shieldsPanelReducer from './reducers/shieldsPanelReducer' 8 | import cosmeticFilterReducer from './reducers/cosmeticFilterReducer' 9 | import runtimeReducer from './reducers/runtimeReducer' 10 | 11 | export default combineReducers({ 12 | shieldsPanel: shieldsPanelReducer, 13 | cosmeticFilter: cosmeticFilterReducer, 14 | runtime: runtimeReducer 15 | }) 16 | -------------------------------------------------------------------------------- /app/background/events/windowsEvents.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import windowActions from '../actions/windowActions' 6 | 7 | chrome.windows.onFocusChanged.addListener((windowId: number) => { 8 | windowActions.windowFocusChanged(windowId) 9 | }) 10 | 11 | chrome.windows.onCreated.addListener((window: chrome.windows.Window) => { 12 | windowActions.windowCreated(window) 13 | }) 14 | 15 | chrome.windows.onRemoved.addListener((windowId: number) => { 16 | windowActions.windowRemoved(windowId) 17 | }) 18 | -------------------------------------------------------------------------------- /app/constants/resourceIdentifiers.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const RESOURCE_IDENTIFIER_ADS = 'ads' 6 | export const RESOURCE_IDENTIFIER_TRACKERS = 'trackers' 7 | export const RESOURCE_IDENTIFIER_HTTP_UPGRADABLE_RESOURCES = 'httpUpgradableResources' 8 | export const RESOURCE_IDENTIFIER_BRAVE_SHIELDS = 'braveShields' 9 | export const RESOURCE_IDENTIFIER_FINGERPRINTING = 'fingerprinting' 10 | export const RESOURCE_IDENTIFIER_COOKIES = 'cookies' 11 | export const RESOURCE_IDENTIFIER_REFERRERS = 'referrers' 12 | -------------------------------------------------------------------------------- /scripts/tests.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | const execute = require('./lib/execute') 6 | 7 | const ACTION = process.env.ACTION 8 | 9 | let cmd = [] 10 | 11 | switch (ACTION) { 12 | case 'lint': 13 | cmd.push('npm run lint') 14 | break 15 | case 'test-unit': 16 | cmd.push('npm run test-unit') 17 | break 18 | } 19 | 20 | execute(cmd, process.env, (err) => { 21 | if (err) { 22 | console.error('failed', err) 23 | process.exit(1) 24 | } 25 | console.log('done') 26 | }) 27 | -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | /* global exec */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | const tasks = require('./tasks') 7 | 8 | const buildDir = process.env.TARGET_GEN_DIR 9 | 10 | tasks.replaceWebpack() 11 | console.log('[Copy assets]') 12 | console.log('-'.repeat(80)) 13 | tasks.copyAssets('prod', buildDir) 14 | 15 | console.log('[Webpack Build]') 16 | console.log('-'.repeat(80)) 17 | if (exec('webpack --config webpack/prod.config.js --progress --profile --colors').code !== 0) { 18 | echo('Erorr: webpack failed') 19 | exit(1) 20 | } 21 | -------------------------------------------------------------------------------- /app/actions/windowActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/windowTypes' 6 | import * as actions from '../types/actions/windowActions' 7 | 8 | export const windowFocusChanged: actions.WindowFocusChanged = (windowId) => { 9 | return { type: types.WINDOW_FOCUS_CHANGED, windowId } 10 | } 11 | 12 | export const windowCreated: actions.WindowCreated = (window) => { 13 | return { type: types.WINDOW_CREATED, window } 14 | } 15 | 16 | export const windowRemoved: actions.WindowRemoved = (windowId) => { 17 | return { type: types.WINDOW_REMOVED, windowId } 18 | } 19 | -------------------------------------------------------------------------------- /app/background/events/tabsEvents.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import tabActions from '../actions/tabActions' 6 | 7 | chrome.tabs.onActivated.addListener((activeInfo: chrome.tabs.TabActiveInfo) => { 8 | tabActions.activeTabChanged(activeInfo.windowId, activeInfo.tabId) 9 | }) 10 | 11 | chrome.tabs.onCreated.addListener(function (tab: chrome.tabs.Tab) { 12 | tabActions.tabCreated(tab) 13 | }) 14 | 15 | chrome.tabs.onUpdated.addListener(function (tabId: number, changeInfo: chrome.tabs.TabChangeInfo, tab: chrome.tabs.Tab) { 16 | tabActions.tabDataChanged(tabId, changeInfo, tab) 17 | }) 18 | -------------------------------------------------------------------------------- /app/actions/webNavigationActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/webNavigationTypes' 6 | import * as actions from '../types/actions/webNavigationActions' 7 | 8 | export const onBeforeNavigate: actions.OnBeforeNavigate = (tabId, url, isMainFrame) => { 9 | return { 10 | type: types.ON_BEFORE_NAVIGATION, 11 | tabId, 12 | url, 13 | isMainFrame 14 | } 15 | } 16 | 17 | export const onCommitted: actions.OnCommitted = (tabId, url, isMainFrame) => { 18 | return { 19 | type: types.ON_COMMITTED, 20 | tabId, 21 | url, 22 | isMainFrame 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scripts/dev.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | const path = require('path') 6 | const tasks = require('./tasks') 7 | const createWebpackServer = require('webpack-httpolyglot-server') 8 | 9 | process.env.TARGET_GEN_DIR = path.join(__dirname, '../dev/') 10 | const buildDir = process.env.TARGET_GEN_DIR 11 | 12 | tasks.replaceWebpack() 13 | console.log('[Copy assets]') 14 | console.log('-'.repeat(80)) 15 | tasks.copyAssets('dev', buildDir) 16 | 17 | console.log('[Webpack Dev]') 18 | console.log('-'.repeat(80)) 19 | createWebpackServer(require('../webpack/dev.config'), { 20 | host: 'localhost', 21 | port: 3000 22 | }) 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./build/", 4 | "sourceMap": true, 5 | "noImplicitAny": true, 6 | "module": "commonjs", 7 | "lib": ["es6", "dom"], 8 | "target": "es5", 9 | "downlevelIteration": true, 10 | "allowJs": true, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "typeRoots" : [ 14 | "./node_modules/@types", 15 | "./app/types/global" 16 | ], 17 | // optional 18 | "forceConsistentCasingInFileNames": true, 19 | "noImplicitReturns": true, 20 | "strictNullChecks": true, 21 | "suppressImplicitAnyIndexErrors": true, 22 | "noUnusedLocals": true 23 | }, 24 | "include": [ 25 | "./app/**/*" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /app/background/events/webNavigationEvents.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import actions from '../actions/webNavigationActions' 6 | 7 | chrome.webNavigation.onBeforeNavigate.addListener(function ({ tabId, url, frameId }: chrome.webNavigation.WebNavigationParentedCallbackDetails) { 8 | const isMainFrame: boolean = frameId === 0 9 | actions.onBeforeNavigate(tabId, url, isMainFrame) 10 | }) 11 | 12 | chrome.webNavigation.onCommitted.addListener(function ({ tabId, url, frameId }: chrome.webNavigation.WebNavigationTransitionCallbackDetails) { 13 | const isMainFrame: boolean = frameId === 0 14 | actions.onCommitted(tabId, url, isMainFrame) 15 | }) 16 | -------------------------------------------------------------------------------- /app/actions/tabActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/tabTypes' 6 | import * as actions from '../types/actions/tabActions' 7 | 8 | export const activeTabChanged: actions.ActiveTabChanged = (windowId, tabId) => { 9 | return { 10 | type: types.ACTIVE_TAB_CHANGED, 11 | windowId, 12 | tabId 13 | } 14 | } 15 | 16 | export const tabCreated: actions.TabCreated = (tab) => { 17 | return { 18 | type: types.TAB_CREATED, 19 | tab 20 | } 21 | } 22 | 23 | export const tabDataChanged: actions.TabDataChanged = (tabId, changeInfo, tab) => { 24 | return { 25 | type: types.TAB_DATA_CHANGED, 26 | tabId, 27 | changeInfo, 28 | tab 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/app/background/reducersTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as assert from 'assert' 8 | import reducers from '../../../app/background/reducers' 9 | import { initialState } from '../../testData' 10 | 11 | describe('reducers test', () => { 12 | it('reducers is a combined reducer function', function () { 13 | assert.equal(typeof reducers, 'function') 14 | }) 15 | 16 | it('reducers passed with an unknown action returns the same input', function () { 17 | const unknownAction = { 18 | type: 'DA07BE00-43FB-44C3-B020-49308A0D3E78' 19 | } 20 | const state = { ...initialState } 21 | assert.equal(reducers(state, unknownAction), state) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /app/constants/shieldsPanelTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | export const SHIELDS_PANEL_DATA_UPDATED = 'SHIELDS_PANEL_DATA_UPDATED' 6 | export const SHIELDS_TOGGLED = 'SHIELDS_TOGGLED' 7 | export const RESOURCE_BLOCKED = 'RESOURCE_BLOCKED' 8 | export const BLOCK_ADS_TRACKERS = 'BLOCK_ADS_TRACKERS' 9 | export const CONTROLS_TOGGLED = 'CONTROLS_TOGGLED' 10 | export const HTTPS_EVERYWHERE_TOGGLED = 'HTTPS_EVERYWHERE_TOGGLED' 11 | export const JAVASCRIPT_TOGGLED = 'JAVASCRIPT_TOGGLED' 12 | export const BLOCK_FINGERPRINTING = 'BLOCK_FINGERPRINTING' 13 | export const BLOCK_COOKIES = 'BLOCK_COOKIES' 14 | export const ALLOW_SCRIPT_ORIGINS_ONCE = 'ALLOW_SCRIPT_ORIGINS_ONCE' 15 | export const CHANGE_NO_SCRIPT_SETTINGS = 'CHANGE_NO_SCRIPT_SETTINGS' 16 | -------------------------------------------------------------------------------- /py-scripts/copy-brave-extension-localization.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import shutil 4 | 5 | def main(): 6 | brave_extension_dir = os.path.realpath(os.path.dirname( 7 | os.path.dirname(os.path.realpath(__file__)))) 8 | brave_extension_browser_resources_dir = os.path.join(brave_extension_dir, 'app') 9 | locales_src_dir_path = brave_extension_browser_resources_dir; 10 | brave_out_dir = sys.argv[1] 11 | locales_dest_dir_path = os.path.join(brave_out_dir, 'brave_extension') 12 | copy_locales(locales_src_dir_path, locales_dest_dir_path) 13 | 14 | def copy_locales(locales_src_dir_path, locales_dest_dir_path): 15 | try: 16 | locales_dest_path = os.path.join(locales_dest_dir_path, '_locales') 17 | shutil.rmtree(locales_dest_path) 18 | except: 19 | pass 20 | shutil.copytree(os.path.join(locales_src_dir_path, '_locales'), locales_dest_path) 21 | 22 | if __name__ == '__main__': 23 | sys.exit(main()) 24 | -------------------------------------------------------------------------------- /app/types/actions/webNavigationActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/webNavigationTypes' 6 | 7 | interface OnBeforeNavigateReturn { 8 | type: types.ON_BEFORE_NAVIGATION, 9 | tabId: number, 10 | url: string, 11 | isMainFrame: boolean 12 | } 13 | 14 | export interface OnBeforeNavigate { 15 | (tabId: number, url: string, isMainFrame: boolean): OnBeforeNavigateReturn 16 | } 17 | 18 | interface OnCommittedReturn { 19 | type: types.ON_COMMITTED, 20 | tabId: number, 21 | url: string, 22 | isMainFrame: boolean 23 | } 24 | 25 | export interface OnCommitted { 26 | (tabId: number, url: string, isMainFrame: boolean): OnCommittedReturn 27 | } 28 | 29 | export type webNavigationActions = 30 | OnBeforeNavigateReturn | 31 | OnCommittedReturn 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: node_js 4 | node_js: 5 | - "8.9" 6 | 7 | branches: 8 | only: 9 | - master 10 | - /\d+\.\d+\.x/ 11 | 12 | cache: 13 | directories: 14 | - node_modules 15 | 16 | env: 17 | - CXX=g++-4.8 NODE_ENV=test ACTION=lint 18 | - CXX=g++-4.8 NODE_ENV=test ACTION=test-unit 19 | 20 | addons: 21 | apt: 22 | sources: 23 | - google-chrome 24 | - ubuntu-toolchain-r-test 25 | packages: 26 | - google-chrome-stable 27 | - g++-4.8 28 | 29 | install: 30 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16" 31 | - npm install 32 | 33 | before_script: 34 | - export DISPLAY=:99.0 35 | - sh -e /etc/init.d/xvfb start & 36 | - sleep 3 37 | 38 | script: 39 | - npm run test-suite 40 | # - npm run build 41 | # We need to pre-package a Brave build for this 42 | # - npm run test-e2e 43 | -------------------------------------------------------------------------------- /app/actions/cosmeticFilterActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/cosmeticFilterTypes' 6 | import * as actions from '../types/actions/cosmeticFilterActions' 7 | 8 | export const siteCosmeticFilterAdded: actions.SiteCosmeticFilterAdded = (origin: string, cssfilter: string) => { 9 | return { 10 | type: types.SITE_COSMETIC_FILTER_ADDED, 11 | origin, 12 | cssfilter 13 | } 14 | } 15 | 16 | export const siteCosmeticFilterRemoved: actions.SiteCosmeticFilterRemoved = (origin: string) => { 17 | return { 18 | type: types.SITE_COSMETIC_FILTER_REMOVED, 19 | origin 20 | } 21 | } 22 | 23 | export const allCosmeticFiltersRemoved: actions.AllCosmeticFiltersRemoved = () => { 24 | return { 25 | type: types.ALL_COSMETIC_FILTERS_REMOVED 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/setupApp.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as jsdom from 'jsdom' 6 | import { getMockChrome } from './testData' 7 | 8 | const { JSDOM } = jsdom 9 | const { document } = (new JSDOM('')).window 10 | 11 | import { configure } from 'enzyme' 12 | import * as Adapter from 'enzyme-adapter-react-16' 13 | 14 | global.document = document 15 | global.window = document.defaultView 16 | global.navigator = global.window.navigator 17 | global.HTMLElement = global.window.HTMLElement 18 | if (global.chrome === undefined) { 19 | global.chrome = getMockChrome() 20 | } 21 | // mocks rAF to suppress React warning while testing 22 | global.requestAnimationFrame = function (cb: () => void) { 23 | return setTimeout(cb, 0) 24 | } 25 | 26 | configure({ adapter: new Adapter() }) -------------------------------------------------------------------------------- /app/containers/braveShields.tsx: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { bindActionCreators } from 'redux' 6 | import { connect } from 'react-redux' 7 | import * as shieldsPanelActions from '../actions/shieldsPanelActions' 8 | import * as shieldsPanelState from '../state/shieldsPanelState' 9 | import BraveShields from '../components/braveShields/braveShields' 10 | import { State } from '../types/state/mainState' 11 | 12 | const mapStateToProps = (state: State) => ({ 13 | shieldsPanelTabData: shieldsPanelState.getActiveTabData(state.shieldsPanel) 14 | }) 15 | 16 | const mapDispatchToProps = (dispatch: any) => ({ 17 | actions: bindActionCreators(shieldsPanelActions, dispatch) 18 | }) 19 | 20 | export default connect( 21 | mapStateToProps, 22 | mapDispatchToProps 23 | )(BraveShields as any) // TODO remove any 24 | -------------------------------------------------------------------------------- /app/background/store.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { applyMiddleware, createStore, Middleware } from 'redux' 6 | import { wrapStore } from 'react-chrome-redux' 7 | import { createLogger } from 'redux-logger' 8 | import thunk from 'redux-thunk' 9 | 10 | import reducer from './reducers' 11 | 12 | const logger = createLogger({ 13 | collapsed: true 14 | }) 15 | 16 | const initialState = {} 17 | 18 | const getMiddleware = () => { 19 | const args: Middleware[] = [thunk] 20 | 21 | if (process.env.NODE_ENV === 'development') { 22 | args.push(logger) 23 | } 24 | 25 | return applyMiddleware(...args) 26 | } 27 | 28 | const store = createStore( 29 | reducer, 30 | initialState, 31 | getMiddleware() 32 | ) 33 | 34 | wrapStore(store, { 35 | portName: 'BRAVE' 36 | }) 37 | 38 | export default store 39 | -------------------------------------------------------------------------------- /test/app/background/api/localeAPITest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it, before, after */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as sinon from 'sinon' 8 | import * as assert from 'assert' 9 | import * as localeAPI from '../../../../app/background/api/localeAPI' 10 | 11 | describe('locale API', () => { 12 | describe('getMessage', function () { 13 | before(function () { 14 | this.spy = sinon.spy(chrome.i18n, 'getMessage') 15 | this.message = 'NESPRESS YOURSELF' 16 | localeAPI.getMessage(this.message) 17 | }) 18 | after(function () { 19 | this.spy.restore() 20 | }) 21 | it('calls chrome.i18n.getMessage with the message', function () { 22 | assert(this.spy.calledOnce) 23 | assert.deepEqual(this.spy.getCall(0).args[0], this.message) 24 | }) 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /app/types/constants/resourceIdentifiers.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | 9 | import * as types from '../../constants/resourceIdentifiers' 10 | 11 | export type RESOURCE_IDENTIFIER_ADS = typeof types.RESOURCE_IDENTIFIER_ADS 12 | export type RESOURCE_IDENTIFIER_TRACKERS = typeof types.RESOURCE_IDENTIFIER_TRACKERS 13 | export type RESOURCE_IDENTIFIER_HTTP_UPGRADABLE_RESOURCES = typeof types.RESOURCE_IDENTIFIER_HTTP_UPGRADABLE_RESOURCES 14 | export type RESOURCE_IDENTIFIER_FINGERPRINTING = typeof types.RESOURCE_IDENTIFIER_FINGERPRINTING 15 | export type RESOURCE_IDENTIFIER_COOKIES = typeof types.RESOURCE_IDENTIFIER_COOKIES 16 | -------------------------------------------------------------------------------- /scripts/tasks.js: -------------------------------------------------------------------------------- 1 | /* global cp mkdir rm exec */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | require('shelljs/global') 7 | 8 | exports.replaceWebpack = () => { 9 | const replaceTasks = [{ 10 | from: 'webpack/replace/JsonpMainTemplate.runtime.js', 11 | to: 'node_modules/webpack/lib/JsonpMainTemplate.runtime.js' 12 | }, { 13 | from: 'webpack/replace/process-update.js', 14 | to: 'node_modules/webpack-hot-middleware/process-update.js' 15 | }] 16 | 17 | replaceTasks.forEach(task => cp(task.from, task.to)) 18 | } 19 | 20 | exports.copyAssets = (type, outputDir) => { 21 | rm('-rf', outputDir) 22 | mkdir(outputDir) 23 | cp(`app/manifest.${type}.json`, `${outputDir}/manifest.json`) 24 | cp('-R', 'app/_locales/', outputDir) 25 | cp('-R', 'app/assets/*', outputDir) 26 | exec(`pug -O "{ env: '${type}' }" -o ${outputDir} app/views/`) 27 | } 28 | -------------------------------------------------------------------------------- /app/braveShieldsPanel.tsx: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as React from 'react' 6 | import * as ReactDOM from 'react-dom' 7 | import { Provider } from 'react-redux' 8 | import { Store } from 'react-chrome-redux' 9 | import BraveShields from './containers/braveShields' 10 | import { State } from './types/state/shieldsPannelState' 11 | 12 | chrome.storage.local.get('state', (obj) => { 13 | const store: Store = new Store({ 14 | portName: 'BRAVE' 15 | }) 16 | 17 | store.ready() 18 | .then(() => { 19 | const mountNode: HTMLElement | null = document.querySelector('#root') 20 | ReactDOM.render( 21 | 22 | 23 | , 24 | mountNode 25 | ) 26 | }) 27 | .catch(() => { 28 | console.error('Problem mounting brave shields') 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /app/types/actions/windowActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/windowTypes' 6 | 7 | interface WindowFocusChangedReturn { 8 | type: types.WINDOW_FOCUS_CHANGED, 9 | windowId: number 10 | } 11 | 12 | export interface WindowFocusChanged { 13 | (windowId: number): WindowFocusChangedReturn 14 | } 15 | 16 | interface WindowCreatedReturn { 17 | type: types.WINDOW_CREATED, 18 | window: chrome.windows.Window 19 | } 20 | 21 | export interface WindowCreated { 22 | (window: chrome.windows.Window): WindowCreatedReturn 23 | } 24 | 25 | interface WindowRemovedReturn { 26 | type: types.WINDOW_REMOVED, 27 | windowId: number 28 | } 29 | 30 | export interface WindowRemoved { 31 | (windowId: number): WindowRemovedReturn 32 | } 33 | 34 | export type windowActions = 35 | WindowFocusChangedReturn | 36 | WindowCreatedReturn | 37 | WindowRemovedReturn 38 | -------------------------------------------------------------------------------- /app/types/constants/shieldsPanelTypes.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../../constants/shieldsPanelTypes' 6 | 7 | export type SHIELDS_PANEL_DATA_UPDATED = typeof types.SHIELDS_PANEL_DATA_UPDATED 8 | export type SHIELDS_TOGGLED = typeof types.SHIELDS_TOGGLED 9 | export type RESOURCE_BLOCKED = typeof types.RESOURCE_BLOCKED 10 | export type BLOCK_ADS_TRACKERS = typeof types.BLOCK_ADS_TRACKERS 11 | export type CONTROLS_TOGGLED = typeof types.CONTROLS_TOGGLED 12 | export type HTTPS_EVERYWHERE_TOGGLED = typeof types.HTTPS_EVERYWHERE_TOGGLED 13 | export type JAVASCRIPT_TOGGLED = typeof types.JAVASCRIPT_TOGGLED 14 | export type BLOCK_FINGERPRINTING = typeof types.BLOCK_FINGERPRINTING 15 | export type BLOCK_COOKIES = typeof types.BLOCK_COOKIES 16 | export type ALLOW_SCRIPT_ORIGINS_ONCE = typeof types.ALLOW_SCRIPT_ORIGINS_ONCE 17 | export type CHANGE_NO_SCRIPT_SETTINGS = typeof types.CHANGE_NO_SCRIPT_SETTINGS 18 | -------------------------------------------------------------------------------- /app/background.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as bluebird from 'bluebird' 6 | global.Promise = bluebird 7 | 8 | function promisifier (method: any) { 9 | // return a function 10 | return function promisified (...args: string[]) { 11 | // which returns a promise 12 | return new Promise((resolve: any) => { 13 | args.push(resolve) 14 | method.apply(this, args) 15 | }) 16 | } 17 | } 18 | 19 | function promisifyAll (obj: object, list: string[]) { 20 | list.forEach(api => bluebird.promisifyAll(obj[api], { promisifier })) 21 | } 22 | 23 | // let chrome extension api support Promise 24 | promisifyAll(chrome, [ 25 | 'browserAction', 26 | 'tabs', 27 | 'windows' 28 | ]) 29 | promisifyAll(chrome.storage, [ 30 | 'local' 31 | ]) 32 | 33 | promisifyAll(chrome.braveShields, [ 34 | 'javascript', 35 | 'plugins' 36 | ]) 37 | 38 | require('./background/events') 39 | require('./background/store') 40 | -------------------------------------------------------------------------------- /app/background/api/tabsAPI.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * Creates a tab with the specified createProperties 7 | * @param {Object} createProperties as per the chrome extension API 8 | * @return a promise which resolves when the tab is created. 9 | */ 10 | export const createTab = (createProperties: chrome.tabs.CreateProperties) => 11 | new Promise((resolve) => { 12 | chrome.tabs.create(createProperties, (tab) => { 13 | resolve(tab) 14 | }) 15 | }) 16 | 17 | /** 18 | * Reloads the specified tab 19 | * @param {number} tabId the tab ID 20 | * @param {boolean} byPassCache true if the cache should be bypassed 21 | * @return a promise which resolves when the tab is reloaded. 22 | */ 23 | export const reloadTab = (tabId: number, bypassCache: boolean) => 24 | new Promise((resolve) => { 25 | chrome.tabs.reload(tabId, { bypassCache }, () => { 26 | resolve() 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /app/types/global/chrome.d.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /// 6 | 7 | type BlockTypes = 'ads' | 'trackers' | 'httpUpgradableResources' | 'javascript' | 'fingerprinting' 8 | 9 | interface BlockDetails { 10 | blockType: BlockTypes 11 | tabId: number 12 | subresource: string 13 | } 14 | 15 | interface BlockDetails { 16 | blockType: BlockTypes 17 | tabId: number 18 | subresource: string 19 | } 20 | declare namespace chrome.tabs { 21 | const setAsync: any 22 | const getAsync: any 23 | } 24 | 25 | declare namespace chrome.windows { 26 | const getAllAsync: any 27 | } 28 | 29 | declare namespace chrome.braveShields { 30 | const onBlocked: { 31 | addListener: (callback: (detail: BlockDetails) => void) => void 32 | emit: (detail: BlockDetails) => void 33 | } 34 | 35 | const allowScriptsOnce: any 36 | const javascript: any 37 | const plugins: any 38 | } 39 | -------------------------------------------------------------------------------- /scripts/compress.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | const fs = require('fs') 6 | const ChromeExtension = require('crx') 7 | /* eslint import/no-unresolved: 0 */ 8 | const name = require('../build/manifest.json').name 9 | const argv = require('minimist')(process.argv.slice(2)) 10 | 11 | const keyPath = argv.key || 'key.pem' 12 | const existsKey = fs.existsSync(keyPath) 13 | const crx = new ChromeExtension({ 14 | appId: argv['app-id'], 15 | codebase: argv.codebase, 16 | privateKey: existsKey ? fs.readFileSync(keyPath) : null 17 | }) 18 | 19 | crx.load('build') 20 | .then(() => crx.loadContents()) 21 | .then((archiveBuffer) => { 22 | fs.writeFile(`${name}.zip`, archiveBuffer) 23 | 24 | if (!argv.codebase || !existsKey) return 25 | crx.pack(archiveBuffer).then((crxBuffer) => { 26 | const updateXML = crx.generateUpdateXML() 27 | 28 | fs.writeFile('update.xml', updateXML) 29 | fs.writeFile(`${name}.crx`, crxBuffer) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /app/types/actions/tabActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/tabTypes' 6 | 7 | interface ActiveTabChangedReturn { 8 | type: types.ACTIVE_TAB_CHANGED, 9 | windowId: number, 10 | tabId: number 11 | } 12 | 13 | export interface ActiveTabChanged { 14 | (windowId: number, tabId: number): ActiveTabChangedReturn 15 | } 16 | 17 | interface TabCreatedReturn { 18 | type: types.TAB_CREATED, 19 | tab: chrome.tabs.Tab 20 | } 21 | 22 | export interface TabCreated { 23 | (tab: chrome.tabs.Tab): TabCreatedReturn 24 | } 25 | 26 | interface TabDataChangedReturn { 27 | type: types.TAB_DATA_CHANGED, 28 | tabId: number, 29 | changeInfo: chrome.tabs.TabChangeInfo, 30 | tab: chrome.tabs.Tab 31 | } 32 | 33 | export interface TabDataChanged { 34 | (tabId: number, changeInfo: chrome.tabs.TabChangeInfo, tab: chrome.tabs.Tab): TabDataChangedReturn 35 | } 36 | 37 | export type tabActions = 38 | ActiveTabChangedReturn | 39 | TabCreatedReturn | 40 | TabDataChangedReturn 41 | -------------------------------------------------------------------------------- /test/app/actions/webNavigationActionsTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as assert from 'assert' 8 | import * as types from '../../../app/constants/webNavigationTypes' 9 | import * as actions from '../../../app/actions/webNavigationActions' 10 | 11 | describe('webNavigationActions', () => { 12 | it('onBeforeNavigate', () => { 13 | const tabId = 1 14 | const url = 'https://www.brave.com' 15 | const isMainFrame = true 16 | assert.deepEqual(actions.onBeforeNavigate(tabId, url, isMainFrame), { 17 | type: types.ON_BEFORE_NAVIGATION, 18 | url, 19 | tabId, 20 | isMainFrame 21 | }) 22 | }) 23 | it('onCommitted', () => { 24 | const tabId = 1 25 | const url = 'https://www.brave.com' 26 | const isMainFrame = true 27 | assert.deepEqual(actions.onCommitted(tabId, url, isMainFrame), { 28 | type: types.ON_COMMITTED, 29 | url, 30 | tabId, 31 | isMainFrame 32 | }) 33 | }) 34 | 35 | }) 36 | -------------------------------------------------------------------------------- /app/types/actions/cosmeticFilterActions.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as types from '../constants/cosmeticFilterTypes' 6 | 7 | interface SiteCosmeticFilterAddedReturn { 8 | type: types.SITE_COSMETIC_FILTER_ADDED, 9 | origin: string, 10 | cssfilter: string 11 | } 12 | 13 | export interface SiteCosmeticFilterAdded { 14 | (origin: string, cssfilter: string): SiteCosmeticFilterAddedReturn 15 | } 16 | 17 | interface SiteCosmeticFilterRemovedReturn { 18 | type: types.SITE_COSMETIC_FILTER_REMOVED, 19 | origin: string 20 | } 21 | 22 | export interface SiteCosmeticFilterRemoved { 23 | (origin: string): SiteCosmeticFilterRemovedReturn 24 | } 25 | 26 | interface AllCosmeticFiltersRemovedReturn { 27 | type: types.ALL_COSMETIC_FILTERS_REMOVED 28 | } 29 | 30 | export interface AllCosmeticFiltersRemoved { 31 | (): AllCosmeticFiltersRemovedReturn 32 | } 33 | 34 | export type cosmeticFilterActions = 35 | SiteCosmeticFilterRemovedReturn | 36 | SiteCosmeticFilterAddedReturn | 37 | AllCosmeticFiltersRemovedReturn 38 | -------------------------------------------------------------------------------- /test/func.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import * as chromedriver from 'chromedriver' 6 | import * as webdriver from 'selenium-webdriver' 7 | 8 | export function delay (time: number) { 9 | return new Promise(resolve => setTimeout(resolve, time)) 10 | } 11 | 12 | let chromedriverIsStarted = false 13 | export function startChromeDriver () { 14 | if (chromedriverIsStarted) return Promise.resolve() 15 | chromedriver.start() 16 | process.on('exit', () => { 17 | chromedriver.stop() 18 | }) 19 | chromedriverIsStarted = true 20 | return delay(1000) 21 | } 22 | 23 | export function buildWebDriver (extPath: string) { 24 | return new webdriver.Builder() 25 | .usingServer('http://localhost:9515') 26 | .withCapabilities({ 27 | chromeOptions: { 28 | args: [`load-extension=${extPath}`], 29 | // TODO: Set this properly for platforms other than macOS 30 | binary: '../../../out/Release/Brave.app/Contents/MacOS/Brave' 31 | } 32 | }) 33 | .forBrowser('chrome') 34 | .build() 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed *.pid.lock 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # nyc test coverage 20 | .nyc_output 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # Bower dependency directory (https://bower.io/) 26 | bower_components 27 | 28 | # node-waf configuration 29 | .lock-wscript 30 | 31 | # Compiled binary addons (http://nodejs.org/api/addons.html) 32 | build/Release 33 | 34 | # Dependency directories 35 | node_modules/ 36 | jspm_packages/ 37 | 38 | # Typescript v1 declaration files 39 | typings/ 40 | 41 | # Optional npm cache directory 42 | .npm 43 | 44 | # Optional REPL history 45 | .node_repl_history 46 | 47 | # Output of 'npm pack' 48 | *.tgz 49 | 50 | # Yarn Integrity file 51 | .yarn-integrity 52 | 53 | # dotenv environment variables file 54 | .env 55 | 56 | # dev files 57 | dev/ 58 | 59 | # macOS files 60 | .DS_Store 61 | 62 | # Release 63 | build/ 64 | 65 | # Ignore python compiled files 66 | *.pyc 67 | -------------------------------------------------------------------------------- /test/app/background/events/shieldsEventsTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it, before, after */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as sinon from 'sinon' 8 | import * as assert from 'assert' 9 | import '../../../../app/background/events/shieldsEvents' 10 | import actions from '../../../../app/background/actions/shieldsPanelActions' 11 | import { blockedResource } from '../../../testData' 12 | 13 | describe('shieldsEvents events', () => { 14 | describe('chrome.braveShields.onBlocked listener', function () { 15 | before(function () { 16 | this.stub = sinon.stub(actions, 'resourceBlocked') 17 | }) 18 | after(function () { 19 | this.stub.restore() 20 | }) 21 | it('forward details to actions.resourceBlocked', function (cb) { 22 | chrome.braveShields.onBlocked.addListener((details) => { 23 | assert.equal(details, blockedResource) 24 | assert(this.stub.withArgs(details).calledOnce) 25 | cb() 26 | }) 27 | chrome.braveShields.onBlocked.emit(blockedResource) 28 | }) 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /test/app/actions/windowActionsTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as assert from 'assert' 8 | import * as types from '../../../app/constants/windowTypes' 9 | import * as actions from '../../../app/actions/windowActions' 10 | 11 | describe('windowActions', () => { 12 | it('windowFocusChanged', () => { 13 | const windowId = 1 14 | assert.deepEqual(actions.windowFocusChanged(windowId), { 15 | type: types.WINDOW_FOCUS_CHANGED, 16 | windowId 17 | }) 18 | }) 19 | 20 | it('windowCreated', () => { 21 | const win: chrome.windows.Window = { 22 | id: 1, 23 | state: 'normal', 24 | focused: true, 25 | alwaysOnTop: false, 26 | incognito: false, 27 | type: 'normal' 28 | } 29 | assert.deepEqual(actions.windowCreated(win), { 30 | type: types.WINDOW_CREATED, 31 | window: win 32 | }) 33 | }) 34 | 35 | it('windowRemoved', () => { 36 | const windowId = 1 37 | assert.deepEqual(actions.windowRemoved(windowId), { 38 | type: types.WINDOW_REMOVED, 39 | windowId 40 | }) 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /app/types/global/react-chrome-redux.d.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | declare module 'react-chrome-redux' { 6 | interface Action { 7 | type: any 8 | } 9 | 10 | interface AnyAction extends Action { 11 | [extraProps: string]: any 12 | } 13 | 14 | interface Unsubscribe { 15 | (): void 16 | } 17 | 18 | type Reducer = (state: S, action: AnyAction) => S 19 | 20 | const wrapStore: (store: object, options?: { 21 | portName?: string 22 | dispatchResponder?: any 23 | }) => void 24 | 25 | class Store { 26 | constructor (options: { 27 | portName: string 28 | state?: object 29 | extensionId?: string 30 | }) 31 | 32 | ready (callBack?: () => void): Promise 33 | 34 | dispatch (data: object): Promise 35 | 36 | getState (): S 37 | 38 | replaceState (newState: S): void 39 | 40 | patchState (partialState: Partial): void 41 | 42 | subscribe (listener: () => void): Unsubscribe 43 | 44 | // this is missing in the original react chrome redux implementatio, but we need it in redux 45 | replaceReducer (nextReducer: Reducer): void 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/app/background/windowActionsTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as assert from 'assert' 8 | import * as types from '../../../app/constants/windowTypes' 9 | import * as actions from '../../../app/actions/windowActions' 10 | 11 | describe('windowActions', () => { 12 | it('windowFocusChanged', () => { 13 | const windowId = 1 14 | assert.deepEqual(actions.windowFocusChanged(windowId), { 15 | type: types.WINDOW_FOCUS_CHANGED, 16 | windowId: windowId 17 | }) 18 | }) 19 | 20 | it('windowCreated', () => { 21 | const window: chrome.windows.Window = { 22 | id: 1, 23 | state: 'normal', 24 | focused: true, 25 | alwaysOnTop: false, 26 | incognito: false, 27 | type: 'normal' 28 | } 29 | assert.deepEqual(actions.windowCreated(window), { 30 | type: types.WINDOW_CREATED, 31 | window 32 | }) 33 | }) 34 | 35 | it('windowRemoved', () => { 36 | const windowId = 1 37 | assert.deepEqual(actions.windowRemoved(windowId), { 38 | type: types.WINDOW_REMOVED, 39 | windowId 40 | }) 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /py-scripts/build-brave-extension.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import sys 4 | import shutil 5 | from lib.util import execute_stdout, scoped_cwd 6 | 7 | NPM = 'npm' 8 | if sys.platform in ['win32', 'cygwin']: 9 | NPM += '.cmd' 10 | 11 | 12 | def main(): 13 | parser = argparse.ArgumentParser(description='Build Brave extension') 14 | parser.add_argument('--output_dir') 15 | parser.add_argument('--brave_extension_dir') 16 | parser.add_argument('--build_dir') 17 | args = parser.parse_args() 18 | 19 | brave_extension_dir = os.path.abspath(args.brave_extension_dir) 20 | build_dir = os.path.abspath(args.build_dir) 21 | output_dir = os.path.abspath(args.output_dir) 22 | 23 | os.chdir(brave_extension_dir) 24 | build_extension('.', build_dir) 25 | copy_output(build_dir, output_dir) 26 | 27 | 28 | def build_extension(dirname, build_dir, env=None): 29 | if env is None: 30 | env = os.environ.copy() 31 | 32 | env["TARGET_GEN_DIR"] = os.path.abspath(build_dir) 33 | 34 | args = [NPM, 'run', 'build'] 35 | with scoped_cwd(dirname): 36 | execute_stdout(args, env) 37 | 38 | 39 | def copy_output(build_dir, output_dir): 40 | try: 41 | shutil.rmtree(output_dir) 42 | os.rmdir(output_dir) 43 | except: 44 | pass 45 | shutil.copytree(build_dir, output_dir) 46 | 47 | if __name__ == '__main__': 48 | sys.exit(main()) 49 | -------------------------------------------------------------------------------- /test/app/actions/cosmeticFilterActionsTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as assert from 'assert' 8 | import * as types from '../../../app/constants/cosmeticFilterTypes' 9 | import * as actions from '../../../app/actions/cosmeticFilterActions' 10 | import {} from '../../../app/types/actions/cosmeticFilterActions' 11 | 12 | describe('cosmeticFilterActions', () => { 13 | it('siteCosmeticFilterAdded action', () => { 14 | const origin = 'https://a.com' 15 | const cssfilter = '#filter' 16 | assert.deepEqual(actions.siteCosmeticFilterAdded(origin, cssfilter), { 17 | type: types.SITE_COSMETIC_FILTER_ADDED, 18 | origin, 19 | cssfilter 20 | }) 21 | }) 22 | it('siteCosmeticFilterRemoved action', () => { 23 | const origin = 'https://a.com' 24 | assert.deepEqual(actions.siteCosmeticFilterRemoved(origin), { 25 | type: types.SITE_COSMETIC_FILTER_REMOVED, 26 | origin 27 | }) 28 | }) 29 | it('allCosmeticFiltersRemoved action', () => { 30 | assert.deepEqual(actions.allCosmeticFiltersRemoved(), { 31 | type: types.ALL_COSMETIC_FILTERS_REMOVED 32 | }) 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Brave Only Extension 2 | 3 | [![Build Status](https://travis-ci.org/brave/brave-extension.svg?branch=master)](https://travis-ci.org/brave/brave-extension) 4 | 5 | > Experiment moving part of the Brave UI into an extension for use in Brave only (Not Chrome, it will use APIs not available in Chrome) 6 | 7 | ## Installation 8 | 9 | ```bash 10 | # clone brave-extension 11 | $ git clone git@github.com:brave/brave-extension.git 12 | 13 | # Install dependencies 14 | $ cd brave-extension 15 | $ npm install 16 | ``` 17 | 18 | ## Development 19 | 20 | ```bash 21 | # Build files will appear in './dev' 22 | # Start webpack development server 23 | $ npm run dev 24 | ``` 25 | 26 | ## Release 27 | 28 | ### Build 29 | 30 | ```bash 31 | # build files to './build' 32 | $ npm run build 33 | ``` 34 | 35 | ### Packaging 36 | 37 | 38 | ```bash 39 | # compress release into a brave.zip and brave.crx. 40 | $ npm run build 41 | $ npm run compress -- [options] 42 | ``` 43 | 44 | ## Test 45 | 46 | * `test/app`: React components, Redux actions & reducers tests 47 | * `test/e2e`: E2E tests (use [chromedriver](https://www.npmjs.com/package/chromedriver), [selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver)) 48 | 49 | ```bash 50 | # lint 51 | $ npm run test-unit 52 | 53 | # test/e2e 54 | $ npm run-script build 55 | $ npm run test-e2e 56 | ``` 57 | 58 | ## LICENSE 59 | 60 | [MPL-2](LICENSE) 61 | -------------------------------------------------------------------------------- /app/background/events/runtimeEvents.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import windowActions from '../actions/windowActions' 6 | import tabActions from '../actions/tabActions' 7 | import runtimeActions from '../actions/runtimeActions' 8 | 9 | function checkForNewWindows () { 10 | chrome.windows.getAllAsync({ populate: true }).then((windows: chrome.windows.Window[]) => { 11 | windows.forEach((win: chrome.windows.Window) => { 12 | windowActions.windowCreated(win) 13 | if (win.tabs) { 14 | win.tabs.forEach((tab: chrome.tabs.Tab) => { 15 | tabActions.tabCreated(tab) 16 | }) 17 | } 18 | }) 19 | }) 20 | } 21 | 22 | chrome.runtime.onStartup.addListener(() => { 23 | runtimeActions.runtimeDidStartup() 24 | checkForNewWindows() 25 | }) 26 | 27 | if (chrome.extension.inIncognitoContext) { 28 | // This is a work-around for a longstanding Chromium bug where onStartup 29 | // isn't called for incognito windows. And since chrome.windows.onCreated 30 | // doesn't get called for the first window, we need to work around it here. 31 | // See https://github.com/brave/brave-browser/issues/1437 for more discussion. 32 | setTimeout(() => { 33 | checkForNewWindows() 34 | }, 1000) 35 | } 36 | -------------------------------------------------------------------------------- /app/manifest.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "name": "Brave", 4 | "manifest_version": 2, 5 | "description": "__MSG_appName__", 6 | "default_locale": "en_US", 7 | "browser_action": { 8 | "default_title": "Brave Shields", 9 | "default_popup": "braveShieldsPanel.html" 10 | }, 11 | "icons": { 12 | "16": "img/icon-16.png", 13 | "32": "img/icon-32.png", 14 | "48": "img/icon-48.png", 15 | "64": "img/icon-64.png", 16 | "128": "img/icon-128.png", 17 | "256": "img/icon-256.png" 18 | }, 19 | "web_accessible_resources": [ 20 | ], 21 | "background": { 22 | "page": "background.html" 23 | }, 24 | "content_scripts": [ 25 | { 26 | "matches": [ 27 | "http://*/*", 28 | "https://*/*" 29 | ], 30 | "js": [ 31 | "js/content.bundle.js" 32 | ], 33 | "run_at": "document_start", 34 | "all_frames": true 35 | } 36 | ], 37 | "permissions": [ "contentSettings", "management", "tabs", "storage", "webNavigation", "contextMenus", "cookies", "*://*/*" ], 38 | "content_security_policy": "default-src 'self'; script-src 'self'; style-src 'unsafe-inline'; img-src 'self' data:;", 39 | "incognito": "split", 40 | "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAupOLMy5Fd4dCSOtjcApsAQOnuBdTs+OvBVt/3P93noIrf068x0xXkvxbn+fpigcqfNamiJ5CjGyfx9zAIs7zcHwbxjOw0Uih4SllfgtK+svNTeE0r5atMWE0xR489BvsqNuPSxYJUmW28JqhaSZ4SabYrRx114KcU6ko7hkjyPkjQa3P+chStJjIKYgu5tWBiMJp5QVLelKoM+xkY6S7efvJ8AfajxCViLGyDQPDviGr2D0VvIBob0D1ZmAoTvYOWafcNCaqaejPDybFtuLFX3pZBqfyOCyyzGhucyCmfBXJALKbhjRAqN5glNsUmGhhPK87TuGATQfVuZtenMvXMQIDAQAB" 41 | } 42 | -------------------------------------------------------------------------------- /app/background/api/cosmeticFilterAPI.ts: -------------------------------------------------------------------------------- 1 | export const addSiteCosmeticFilter = async (origin: string, cssfilter: string) => { 2 | chrome.storage.local.get('cosmeticFilterList', (storeData = {}) => { 3 | let storeList = Object.assign({}, storeData.cosmeticFilterList) 4 | if (storeList[origin] === undefined || storeList[origin].length === 0) { // nothing in filter list for origin 5 | storeList[origin] = [cssfilter] 6 | } else { // add entry 7 | storeList[origin].push(cssfilter) 8 | } 9 | chrome.storage.local.set({ 'cosmeticFilterList': storeList }) 10 | }) 11 | } 12 | 13 | export const removeSiteFilter = (origin: string) => { 14 | chrome.storage.local.get('cosmeticFilterList', (storeData = {}) => { 15 | let storeList = Object.assign({}, storeData.cosmeticFilterList) 16 | delete storeList[origin] 17 | chrome.storage.local.set({ 'cosmeticFilterList': storeList }) 18 | }) 19 | } 20 | 21 | export const applySiteFilters = (hostname: string) => { 22 | chrome.storage.local.get('cosmeticFilterList', (storeData = {}) => { 23 | if (!storeData.cosmeticFilterList) { 24 | console.info('applySiteFilters: no cosmetic filter store yet') 25 | return 26 | } 27 | if (storeData.cosmeticFilterList[hostname] !== undefined) { 28 | storeData.cosmeticFilterList[hostname].map((rule: string) => { 29 | console.log('applying rule', rule) 30 | chrome.tabs.insertCSS({ 31 | code: `${rule} {display: none;}`, 32 | runAt: 'document_start' 33 | }) 34 | }) 35 | } 36 | }) 37 | } 38 | 39 | export const removeAllFilters = () => { 40 | chrome.storage.local.set({ 'cosmeticFilterList': {} }) 41 | } 42 | -------------------------------------------------------------------------------- /test/app/actions/tabActionsTest.ts: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as assert from 'assert' 8 | import * as types from '../../../app/constants/tabTypes' 9 | import * as actions from '../../../app/actions/tabActions' 10 | 11 | describe('tabActions', () => { 12 | it('activeTabChanged', () => { 13 | const windowId = 1 14 | const tabId = 1 15 | assert.deepEqual(actions.activeTabChanged(windowId, tabId), { 16 | type: types.ACTIVE_TAB_CHANGED, 17 | windowId: windowId, 18 | tabId: tabId 19 | }) 20 | }) 21 | 22 | it('tabCreated', () => { 23 | const tab: chrome.tabs.Tab = { 24 | id: 1, 25 | index: 1, 26 | pinned: false, 27 | highlighted: false, 28 | windowId: 1, 29 | active: true, 30 | incognito: false, 31 | selected: false 32 | } 33 | 34 | assert.deepEqual(actions.tabCreated(tab), { 35 | type: types.TAB_CREATED, 36 | tab 37 | }) 38 | }) 39 | 40 | it('tabDataChanged', () => { 41 | const tabId = 1 42 | const changeInfo = {} 43 | const tab: chrome.tabs.Tab = { 44 | id: 1, 45 | index: 1, 46 | pinned: false, 47 | highlighted: false, 48 | windowId: 1, 49 | active: true, 50 | incognito: false, 51 | selected: false 52 | } 53 | assert.deepEqual(actions.tabDataChanged(tabId, changeInfo, tab), { 54 | type: types.TAB_DATA_CHANGED, 55 | tabId, 56 | changeInfo, 57 | tab 58 | }) 59 | }) 60 | }) 61 | -------------------------------------------------------------------------------- /app/manifest.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "name": "Brave", 4 | "manifest_version": 2, 5 | "description": "__MSG_appName__", 6 | "default_locale": "en_US", 7 | "browser_action": { 8 | "default_title": "Brave Shields", 9 | "default_popup": "braveShieldsPanel.html" 10 | }, 11 | "icons": { 12 | "16": "img/icon-16.png", 13 | "32": "img/icon-32.png", 14 | "48": "img/icon-48.png", 15 | "64": "img/icon-64.png", 16 | "128": "img/icon-128.png", 17 | "256": "img/icon-256.png" 18 | }, 19 | "web_accessible_resources": [ 20 | ], 21 | "background": { 22 | "page": "background.html" 23 | }, 24 | "content_scripts": [ 25 | { 26 | "matches": [ 27 | "http://*/*", 28 | "https://*/*" 29 | ], 30 | "js": [ 31 | "js/content.bundle.js" 32 | ], 33 | "run_at": "document_start", 34 | "all_frames": true 35 | } 36 | ], 37 | "permissions": [ "contentSettings", "management", "tabs", "storage", "webNavigation", "contextMenus", "cookies", "*://*/*" ], 38 | "content_security_policy": "default-src 'self'; script-src 'self' http://localhost:3000 https://localhost:3000 'unsafe-eval'; connect-src http://localhost:3000 https://localhost:3000; style-src * 'unsafe-inline' 'self' blob:; img-src 'self' data:;", 39 | "incognito": "split", 40 | "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAupOLMy5Fd4dCSOtjcApsAQOnuBdTs+OvBVt/3P93noIrf068x0xXkvxbn+fpigcqfNamiJ5CjGyfx9zAIs7zcHwbxjOw0Uih4SllfgtK+svNTeE0r5atMWE0xR489BvsqNuPSxYJUmW28JqhaSZ4SabYrRx114KcU6ko7hkjyPkjQa3P+chStJjIKYgu5tWBiMJp5QVLelKoM+xkY6S7efvJ8AfajxCViLGyDQPDviGr2D0VvIBob0D1ZmAoTvYOWafcNCaqaejPDybFtuLFX3pZBqfyOCyyzGhucyCmfBXJALKbhjRAqN5glNsUmGhhPK87TuGATQfVuZtenMvXMQIDAQAB" 41 | } 42 | -------------------------------------------------------------------------------- /app/background/api/browserActionAPI.ts: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | import { isHttpOrHttps } from '../../helpers/urlUtils' 6 | 7 | export const shieldsOnIcon = 'img/icon.svg' 8 | export const shieldsOffIcon = 'img/icon-off.svg' 9 | 10 | /** 11 | * Initializes the browser action UI 12 | */ 13 | export function init () { 14 | // Setup badge color 15 | chrome.browserAction.setBadgeBackgroundColor({ 16 | color: [66, 66, 66, 100] 17 | }) 18 | // Initial / default icon 19 | chrome.browserAction.setIcon({ 20 | path: shieldsOnIcon 21 | }) 22 | // By default, icon is disabled, 23 | // so that we do not enable the icon in a new tab and then disable it 24 | // when the context is not http(s). 25 | chrome.browserAction.disable() 26 | } 27 | 28 | /** 29 | * Sets the badge text 30 | * @param {string} text - The text to put on the badge 31 | */ 32 | export const setBadgeText = (tabId: number, text: string) => { 33 | if (chrome.browserAction) { 34 | chrome.browserAction.setBadgeText({ 35 | tabId, 36 | text: String(text) 37 | }) 38 | } 39 | } 40 | 41 | /** 42 | * Updates the shields icon based on shields state 43 | */ 44 | export const setIcon = (url: string, tabId: number, shieldsOn: boolean) => { 45 | 46 | const actionIsDisabled = !isHttpOrHttps(url) 47 | if (chrome.browserAction) { 48 | chrome.browserAction.setIcon({ 49 | path: shieldsOn ? shieldsOnIcon : shieldsOffIcon, 50 | tabId 51 | }) 52 | if (actionIsDisabled) { 53 | chrome.browserAction.disable(tabId) 54 | } else { 55 | chrome.browserAction.enable(tabId) 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/app/components/noScript/noScriptTest.tsx: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | import 'mocha' 7 | import * as React from 'react' 8 | import * as assert from 'assert' 9 | import NoScript, { NoScriptProps } from '../../../../app/components/noScript/noScript' 10 | import * as actionTypes from '../../../../app/constants/shieldsPanelTypes' 11 | import { shallow } from 'enzyme' 12 | 13 | const fakeProps: NoScriptProps = { 14 | blocked: true, 15 | noScriptInfo: { 16 | 0: { 17 | actuallyBlocked: false, 18 | willBlock: true 19 | }, 20 | 1: { 21 | actuallyBlocked: true, 22 | willBlock: false 23 | } 24 | }, 25 | onSubmit: (origins: string[]) => { 26 | return { 27 | type: actionTypes.ALLOW_SCRIPT_ORIGINS_ONCE, 28 | origins 29 | } 30 | }, 31 | onChangeNoScriptSettings: (origin: string) => { 32 | actionTypes.CHANGE_NO_SCRIPT_SETTINGS, 33 | origin 34 | } 35 | } 36 | 37 | describe('NoScript component', () => { 38 | const baseComponent = (props: NoScriptProps) => 39 |