From 327144a3aa962b51d9b143941be4e626abbc7ee7 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 7 Jul 2018 16:58:09 +0900 Subject: [wip] content --- src/content/components/common/index.js | 33 +++++++++++++++++++++++++----- src/content/components/common/keymapper.js | 5 +++-- 2 files changed, 31 insertions(+), 7 deletions(-) (limited to 'src/content/components/common') diff --git a/src/content/components/common/index.js b/src/content/components/common/index.js index 6437011..3a23956 100644 --- a/src/content/components/common/index.js +++ b/src/content/components/common/index.js @@ -4,6 +4,7 @@ import FollowComponent from './follow'; import * as settingActions from 'content/actions/setting'; import messages from 'shared/messages'; import * as addonActions from '../../actions/addon'; +import * as re from 'shared/utils/re'; export default class Common { constructor(win, store) { @@ -14,8 +15,10 @@ export default class Common { input.onKey(key => follow.key(key)); input.onKey(key => keymapper.key(key)); + this.win = win; this.store = store; this.prevEnabled = undefined; + this.prevBlacklist = undefined; this.reloadSettings(); @@ -42,14 +45,34 @@ export default class Common { enabled, }); } + + let blacklist = JSON.stringify(this.store.getState().setting.blacklist); + if (blacklist !== this.prevBlacklist) { + this.prevBlacklist = blacklist; + + this.disableIfBlack(this.store.getState().setting.blacklist); + } } - async reloadSettings() { + disableIfBlack(blacklist) { + let loc = this.win.location; + let partial = loc.host + loc.pathname; + let matched = blacklist + .map((item) => { + let pattern = item.includes('/') ? item : item + '/*'; + return re.fromWildcard(pattern); + }) + .some(regex => regex.test(partial)); + if (matched) { + this.store.dispatch(addonActions.disable()); + } else { + this.store.dispatch(addonActions.enable()); + } + } + + reloadSettings() { try { - let settings = await browser.runtime.sendMessage({ - type: messages.SETTINGS_QUERY, - }); - this.store.dispatch(settingActions.set(settings)); + this.store.dispatch(settingActions.load()); } catch (e) { // Sometime sendMessage fails when background script is not ready. console.warn(e); diff --git a/src/content/components/common/keymapper.js b/src/content/components/common/keymapper.js index d9d1b2f..326bdd9 100644 --- a/src/content/components/common/keymapper.js +++ b/src/content/components/common/keymapper.js @@ -20,6 +20,7 @@ export default class KeymapperComponent { this.store = store; } + // eslint-disable-next-line max-statements key(key) { this.store.dispatch(inputActions.keyPress(key)); @@ -47,8 +48,8 @@ export default class KeymapperComponent { return true; } let operation = keymaps.get(matched[0]); - this.store.dispatch(operationActions.exec( - operation, key.repeat, state.setting)); + let act = operationActions.exec(operation, key.repeat, state.setting); + this.store.dispatch(act); this.store.dispatch(inputActions.clearKeys()); return true; } -- cgit v1.2.3 From cf0dcf25226611590d76d263b5a4acdc89510d09 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 7 Jul 2018 17:52:01 +0900 Subject: blacklist as an util --- src/content/components/common/index.js | 31 ++++++++----------------- src/shared/blacklists.js | 13 +++++++++++ test/shared/blacklists.test.js | 42 ++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 src/shared/blacklists.js create mode 100644 test/shared/blacklists.test.js (limited to 'src/content/components/common') diff --git a/src/content/components/common/index.js b/src/content/components/common/index.js index 3a23956..e81bf1f 100644 --- a/src/content/components/common/index.js +++ b/src/content/components/common/index.js @@ -5,6 +5,7 @@ import * as settingActions from 'content/actions/setting'; import messages from 'shared/messages'; import * as addonActions from '../../actions/addon'; import * as re from 'shared/utils/re'; +import * as blacklists from 'shared/blacklists'; export default class Common { constructor(win, store) { @@ -46,27 +47,15 @@ export default class Common { }); } - let blacklist = JSON.stringify(this.store.getState().setting.blacklist); - if (blacklist !== this.prevBlacklist) { - this.prevBlacklist = blacklist; - - this.disableIfBlack(this.store.getState().setting.blacklist); - } - } - - disableIfBlack(blacklist) { - let loc = this.win.location; - let partial = loc.host + loc.pathname; - let matched = blacklist - .map((item) => { - let pattern = item.includes('/') ? item : item + '/*'; - return re.fromWildcard(pattern); - }) - .some(regex => regex.test(partial)); - if (matched) { - this.store.dispatch(addonActions.disable()); - } else { - this.store.dispatch(addonActions.enable()); + let blacklist = this.store.getState().setting.blacklist; + let str = JSON.stringify(blacklist) + if (blacklist !== str) { + this.prevBlacklist = str; + if (blacklists.includes(blacklist, this.win.location)) { + this.store.dispatch(addonActions.disable()); + } else { + this.store.dispatch(addonActions.enable()); + } } } diff --git a/src/shared/blacklists.js b/src/shared/blacklists.js new file mode 100644 index 0000000..21e3e14 --- /dev/null +++ b/src/shared/blacklists.js @@ -0,0 +1,13 @@ +import * as re from 'shared/utils/re'; + +const includes = (blacklist, url) => { + let u = new URL(url) + return blacklist.some((item) => { + if (!item.includes('/')) { + return re.fromWildcard(item).test(u.hostname); + } + return re.fromWildcard(item).test(u.hostname + u.pathname); + }); +} + +export { includes }; diff --git a/test/shared/blacklists.test.js b/test/shared/blacklists.test.js new file mode 100644 index 0000000..87e89c5 --- /dev/null +++ b/test/shared/blacklists.test.js @@ -0,0 +1,42 @@ +import { includes } from 'shared/blacklists'; + +describe("shared/blacklist", () => { + it('matches by *', () => { + let blacklist = ['*']; + + expect(includes(blacklist, 'https://github.com/abc')).to.be.true; + }) + + it('matches by hostname', () => { + let blacklist = ['github.com']; + + expect(includes(blacklist, 'https://github.com')).to.be.true; + expect(includes(blacklist, 'https://gist.github.com')).to.be.false; + expect(includes(blacklist, 'https://github.com/ueokande')).to.be.true; + expect(includes(blacklist, 'https://github.org')).to.be.false; + expect(includes(blacklist, 'https://google.com/search?q=github.org')).to.be.false; + }) + + it('matches by hostname with wildcard', () => { + let blacklist = ['*.github.com']; + + expect(includes(blacklist, 'https://github.com')).to.be.false; + expect(includes(blacklist, 'https://gist.github.com')).to.be.true; + }) + + it('matches by path', () => { + let blacklist = ['github.com/abc']; + + expect(includes(blacklist, 'https://github.com/abc')).to.be.true; + expect(includes(blacklist, 'https://github.com/abcdef')).to.be.false; + expect(includes(blacklist, 'https://gist.github.com/abc')).to.be.false; + }) + + it('matches by path with wildcard', () => { + let blacklist = ['github.com/abc*']; + + expect(includes(blacklist, 'https://github.com/abc')).to.be.true; + expect(includes(blacklist, 'https://github.com/abcdef')).to.be.true; + expect(includes(blacklist, 'https://gist.github.com/abc')).to.be.false; + }) +}); -- cgit v1.2.3 From efa1cb396733ac0bedb7c1e86fd1974fbc801135 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 7 Jul 2018 22:05:22 +0900 Subject: Use official redux on content --- src/content/actions/addon.js | 22 +++++++++++-------- src/content/actions/index.js | 4 +--- src/content/actions/operation.js | 4 ++-- src/content/actions/setting.js | 2 +- src/content/components/common/index.js | 35 +++++++----------------------- src/content/components/common/keymapper.js | 4 +++- src/content/index.js | 1 - src/content/reducers/addon.js | 10 ++------- src/shared/blacklists.js | 4 ++-- test/content/actions/addon.test.js | 25 --------------------- test/content/reducers/addon.test.js | 24 ++------------------ 11 files changed, 34 insertions(+), 101 deletions(-) delete mode 100644 test/content/actions/addon.test.js (limited to 'src/content/components/common') diff --git a/src/content/actions/addon.js b/src/content/actions/addon.js index 8d38025..b30cf16 100644 --- a/src/content/actions/addon.js +++ b/src/content/actions/addon.js @@ -1,15 +1,19 @@ +import messages from 'shared/messages'; import actions from 'content/actions'; -const enable = () => { - return { type: actions.ADDON_ENABLE }; -}; +const enable = () => setEnabled(true); -const disable = () => { - return { type: actions.ADDON_DISABLE }; -}; +const disable = () => setEnabled(false); -const toggleEnabled = () => { - return { type: actions.ADDON_TOGGLE_ENABLED }; +const setEnabled = async(enabled) => { + await browser.runtime.sendMessage({ + type: messages.ADDON_ENABLED_RESPONSE, + enabled, + }); + return { + type: actions.ADDON_SET_ENABLED, + enabled, + }; }; -export { enable, disable, toggleEnabled }; +export { enable, disable, setEnabled }; diff --git a/src/content/actions/index.js b/src/content/actions/index.js index 7e32e12..1c51ab0 100644 --- a/src/content/actions/index.js +++ b/src/content/actions/index.js @@ -1,8 +1,6 @@ export default { // Enable/disable - ADDON_ENABLE: 'addon.enable', - ADDON_DISABLE: 'addon.disable', - ADDON_TOGGLE_ENABLED: 'addon.toggle.enabled', + ADDON_SET_ENABLED: 'addon.set.enabled', // Settings SETTING_SET: 'setting.set', diff --git a/src/content/actions/operation.js b/src/content/actions/operation.js index a1761fc..c1bd1c8 100644 --- a/src/content/actions/operation.js +++ b/src/content/actions/operation.js @@ -9,7 +9,7 @@ import * as addonActions from './addon'; import * as properties from 'shared/settings/properties'; // eslint-disable-next-line complexity, max-lines-per-function -const exec = (operation, repeat, settings) => { +const exec = (operation, repeat, settings, addonEnabled) => { let smoothscroll = settings.properties.smoothscroll || properties.defaults.smoothscroll; switch (operation.type) { @@ -18,7 +18,7 @@ const exec = (operation, repeat, settings) => { case operations.ADDON_DISABLE: return addonActions.disable(); case operations.ADDON_TOGGLE_ENABLED: - return addonActions.toggleEnabled(); + return addonActions.setEnabled(!addonEnabled); case operations.FIND_NEXT: window.top.postMessage(JSON.stringify({ type: messages.FIND_NEXT, diff --git a/src/content/actions/setting.js b/src/content/actions/setting.js index 50c09ca..1c15dd7 100644 --- a/src/content/actions/setting.js +++ b/src/content/actions/setting.js @@ -34,4 +34,4 @@ const load = async() => { return set(settings); }; -export { load }; +export { set, load }; diff --git a/src/content/components/common/index.js b/src/content/components/common/index.js index e81bf1f..a1e71a1 100644 --- a/src/content/components/common/index.js +++ b/src/content/components/common/index.js @@ -4,7 +4,6 @@ import FollowComponent from './follow'; import * as settingActions from 'content/actions/setting'; import messages from 'shared/messages'; import * as addonActions from '../../actions/addon'; -import * as re from 'shared/utils/re'; import * as blacklists from 'shared/blacklists'; export default class Common { @@ -24,44 +23,26 @@ export default class Common { this.reloadSettings(); messages.onMessage(this.onMessage.bind(this)); - store.subscribe(() => this.update()); } onMessage(message) { + let { enabled } = this.store.getState().addon; switch (message.type) { case messages.SETTINGS_CHANGED: return this.reloadSettings(); case messages.ADDON_TOGGLE_ENABLED: - return this.store.dispatch(addonActions.toggleEnabled()); - } - } - - update() { - let enabled = this.store.getState().addon.enabled; - if (enabled !== this.prevEnabled) { - this.prevEnabled = enabled; - - browser.runtime.sendMessage({ - type: messages.ADDON_ENABLED_RESPONSE, - enabled, - }); - } - - let blacklist = this.store.getState().setting.blacklist; - let str = JSON.stringify(blacklist) - if (blacklist !== str) { - this.prevBlacklist = str; - if (blacklists.includes(blacklist, this.win.location)) { - this.store.dispatch(addonActions.disable()); - } else { - this.store.dispatch(addonActions.enable()); - } + this.store.dispatch(addonActions.setEnabled(!enabled)); } } reloadSettings() { try { - this.store.dispatch(settingActions.load()); + this.store.dispatch(settingActions.load()).then(({ value: settings }) => { + let enabled = !blacklists.includes( + settings.blacklist, this.win.location.href + ); + this.store.dispatch(addonActions.setEnabled(enabled)); + }); } catch (e) { // Sometime sendMessage fails when background script is not ready. console.warn(e); diff --git a/src/content/components/common/keymapper.js b/src/content/components/common/keymapper.js index 326bdd9..4c294b4 100644 --- a/src/content/components/common/keymapper.js +++ b/src/content/components/common/keymapper.js @@ -48,7 +48,9 @@ export default class KeymapperComponent { return true; } let operation = keymaps.get(matched[0]); - let act = operationActions.exec(operation, key.repeat, state.setting); + let act = operationActions.exec( + operation, key.repeat, state.setting, state.addon.enabled + ); this.store.dispatch(act); this.store.dispatch(inputActions.clearKeys()); return true; diff --git a/src/content/index.js b/src/content/index.js index d6743ce..3b0b49b 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -10,7 +10,6 @@ const store = createStore( applyMiddleware(promise), ); - if (window.self === window.top) { new TopContentComponent(window, store); // eslint-disable-line no-new } else { diff --git a/src/content/reducers/addon.js b/src/content/reducers/addon.js index b881ca0..0def55a 100644 --- a/src/content/reducers/addon.js +++ b/src/content/reducers/addon.js @@ -6,15 +6,9 @@ const defaultState = { export default function reducer(state = defaultState, action = {}) { switch (action.type) { - case actions.ADDON_ENABLE: + case actions.ADDON_SET_ENABLED: return { ...state, - enabled: true, }; - case actions.ADDON_DISABLE: - return { ...state, - enabled: false, }; - case actions.ADDON_TOGGLE_ENABLED: - return { ...state, - enabled: !state.enabled, }; + enabled: action.enabled, }; default: return state; } diff --git a/src/shared/blacklists.js b/src/shared/blacklists.js index 21e3e14..19ed3f1 100644 --- a/src/shared/blacklists.js +++ b/src/shared/blacklists.js @@ -1,13 +1,13 @@ import * as re from 'shared/utils/re'; const includes = (blacklist, url) => { - let u = new URL(url) + let u = new URL(url); return blacklist.some((item) => { if (!item.includes('/')) { return re.fromWildcard(item).test(u.hostname); } return re.fromWildcard(item).test(u.hostname + u.pathname); }); -} +}; export { includes }; diff --git a/test/content/actions/addon.test.js b/test/content/actions/addon.test.js deleted file mode 100644 index 5f96372..0000000 --- a/test/content/actions/addon.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import actions from 'content/actions'; -import * as addonActions from 'content/actions/addon'; - -describe("addon actions", () => { - describe("enable", () => { - it('create ADDON_ENABLE action', () => { - let action = addonActions.enable(); - expect(action.type).to.equal(actions.ADDON_ENABLE); - }); - }); - - describe("disable", () => { - it('create ADDON_DISABLE action', () => { - let action = addonActions.disable(); - expect(action.type).to.equal(actions.ADDON_DISABLE); - }); - }); - - describe("toggle", () => { - it('create ADDON_TOGGLE_ENABLED action', () => { - let action = addonActions.toggleEnabled(); - expect(action.type).to.equal(actions.ADDON_TOGGLE_ENABLED); - }); - }); -}); diff --git a/test/content/reducers/addon.test.js b/test/content/reducers/addon.test.js index 8c546d2..d4eb845 100644 --- a/test/content/reducers/addon.test.js +++ b/test/content/reducers/addon.test.js @@ -7,31 +7,11 @@ describe("addon reducer", () => { expect(state).to.have.property('enabled', true); }); - it('return next state for ADDON_ENABLE', () => { - let action = { type: actions.ADDON_ENABLE}; + it('return next state for ADDON_SET_ENABLED', () => { + let action = { type: actions.ADDON_SET_ENABLED, enabled: true }; let prev = { enabled: false }; let state = addonReducer(prev, action); expect(state.enabled).is.equal(true); }); - - it('return next state for ADDON_DISABLE', () => { - let action = { type: actions.ADDON_DISABLE}; - let prev = { enabled: true }; - let state = addonReducer(prev, action); - - expect(state.enabled).is.equal(false); - }); - - it('return next state for ADDON_TOGGLE_ENABLED', () => { - let action = { type: actions.ADDON_TOGGLE_ENABLED }; - let state = { enabled: false }; - - state = addonReducer(state, action); - expect(state.enabled).is.equal(true); - - state = addonReducer(state, action); - expect(state.enabled).is.equal(false); - }); - }); -- cgit v1.2.3