From fd1c31bf311fc6dfa6813268b257b3628f87cf00 Mon Sep 17 00:00:00 2001 From: AkiraFukushima Date: Thu, 9 May 2019 23:54:53 +0900 Subject: [PATCH 1/5] refs #901 Set preload script to import electron, process in webview --- src/main/index.ts | 4 +- src/main/preload.js | 3 ++ src/renderer/main.ts | 10 ----- src/renderer/router/index.ts | 82 ++++++++++++++++++++++++------------ src/renderer/store/App.ts | 22 +++++----- src/renderer/store/index.ts | 9 ++-- src/types/global.ts | 7 +++ 7 files changed, 86 insertions(+), 51 deletions(-) create mode 100644 src/main/preload.js create mode 100644 src/types/global.ts diff --git a/src/main/index.ts b/src/main/index.ts index eabd1e8d..470c3f27 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -255,7 +255,9 @@ async function createWindow() { webPreferences: { // It is required to use ipcRenderer in renderer process. // But it is not secure, so if you want to disable this option, please use preload script. - nodeIntegration: true + nodeIntegration: true, + contextIsolation: false, + preload: path.resolve(__dirname, './preload.js') } } const config: Config = { diff --git a/src/main/preload.js b/src/main/preload.js new file mode 100644 index 00000000..9ecab4db --- /dev/null +++ b/src/main/preload.js @@ -0,0 +1,3 @@ +const electron = require('electron') +global.ipcRenderer = electron.ipcRenderer +global.process = process diff --git a/src/renderer/main.ts b/src/renderer/main.ts index b82d303d..595d29d5 100644 --- a/src/renderer/main.ts +++ b/src/renderer/main.ts @@ -16,15 +16,6 @@ import router from '@/router' import store from './store' import i18next from '~/src/config/i18n' -declare function require(x: string): any - -declare var process: { - env: { - NODE_ENV: string, - IS_WEB: boolean - } -} - Vue.use(ElementUI, { locale }) Vue.use(shortkey) Vue.use(VueI18Next) @@ -33,7 +24,6 @@ Vue.component('popper', Popper) sync(store, router) -if (!process.env.IS_WEB) Vue.use(require('vue-electron')) Vue.config.productionTip = false const i18n: VueI18Next = new VueI18Next(i18next) diff --git a/src/renderer/router/index.ts b/src/renderer/router/index.ts index 574e81ce..b0e66b8a 100644 --- a/src/renderer/router/index.ts +++ b/src/renderer/router/index.ts @@ -1,6 +1,34 @@ import Vue from 'vue' import Router from 'vue-router' +import Login from '@/components/Login.vue' +import Authorize from '@/components/Authorize.vue' +import Preferences from '@/components/Preferences.vue' +import PreferencesGeneral from '@/components/Preferences/General.vue' +import PreferencesAppearance from '@/components/Preferences/Appearance.vue' +import PreferencesNotification from '@/components/Preferences/Notification.vue' +import PreferencesAccount from '@/components/Preferences/Account.vue' +import PreferencesLanguage from '@/components/Preferences/Language.vue' +import GlobalHeader from '@/components/GlobalHeader.vue' +import Settings from '@/components/Settings.vue' +import SettingsGeneral from '@/components/Settings/General.vue' +import SettingsTimeline from '@/components/Settings/Timeline.vue' +import TimelineSpace from '@/components/TimelineSpace.vue' +import TimelineSpaceContentsHome from '@/components/TimelineSpace/Contents/Home.vue' +import TimelineSpaceContentsNotifications from '@/components/TimelineSpace/Contents/Notifications.vue' +import TimelineSpaceContentsMentions from '@/components/TimelineSpace/Contents/Mentions.vue' +import TimelineSpaceContentsFavourites from '@/components/TimelineSpace/Contents/Favourites.vue' +import TimelineSpaceContentsLocal from '@/components/TimelineSpace/Contents/Local.vue' +import TimelineSpaceContentsPublic from '@/components/TimelineSpace/Contents/Public.vue' +import TimelineSpaceContentsHashtag from '@/components/TimelineSpace/Contents/Hashtag.vue' +import TimelineSpaceContentsHashtagList from '@/components/TimelineSpace/Contents/Hashtag/List.vue' +import TimelineSpaceContentsHashtagTag from '@/components/TimelineSpace/Contents/Hashtag/Tag.vue' +import TimelineSpaceContentsSearch from '@/components/TimelineSpace/Contents/Search.vue' +import TimelineSpaceContentsDirectMessages from '@/components/TimelineSpace/Contents/DirectMessages.vue' +import TimelineSpaceContentsListsIndex from '@/components/TimelineSpace/Contents/Lists/Index.vue' +import TimelineSpaceContentsListsEdit from '@/components/TimelineSpace/Contents/Lists/Edit.vue' +import TimelineSpaceContentsListsShow from '@/components/TimelineSpace/Contents/Lists/Show.vue' + Vue.use(Router) const router = new Router({ @@ -8,38 +36,38 @@ const router = new Router({ { path: '/login', name: 'login', - component: require('@/components/Login').default + component: Login }, { path: '/authorize', name: 'authorize', - component: require('@/components/Authorize').default, + component: Authorize, props: route => ({ url: route.query.url }) }, { path: '/preferences/', name: 'preferences', - component: require('@/components/Preferences').default, + component: Preferences, children: [ { path: 'general', name: 'general', - component: require('@/components/Preferences/General').default + component: PreferencesGeneral }, { path: 'appearance', name: 'appearance', - component: require('@/components/Preferences/Appearance').default + component: PreferencesAppearance }, { path: 'notification', name: 'notification', - component: require('@/components/Preferences/Notification').default + component: PreferencesNotification }, { path: 'account', name: 'account', - component: require('@/components/Preferences/Account').default + component: PreferencesAccount }, { path: 'network', @@ -49,48 +77,48 @@ const router = new Router({ { path: 'language', name: 'language', - component: require('@/components/Preferences/Language').default + component: PreferencesLanguage } ] }, { path: '/', name: 'global-header', - component: require('@/components/GlobalHeader').default, + component: GlobalHeader, children: [ { path: ':id/settings/', - component: require('@/components/Settings').default, + component: Settings, children: [ { path: 'general', - component: require('@/components/Settings/General').default + component: SettingsGeneral }, { path: 'timeline', - component: require('@/components/Settings/Timeline').default + component: SettingsTimeline } ] }, { path: ':id/', name: 'timeline-space', - component: require('@/components/TimelineSpace').default, + component: TimelineSpace, children: [ { path: 'home', name: 'home', - component: require('@/components/TimelineSpace/Contents/Home').default + component: TimelineSpaceContentsHome }, { path: 'notifications', name: 'notifications', - component: require('@/components/TimelineSpace/Contents/Notifications').default + component: TimelineSpaceContentsNotifications }, { path: 'mentions', name: 'mentions', - component: require('@/components/TimelineSpace/Contents/Mentions').default + component: TimelineSpaceContentsMentions }, { path: 'follow-requests', @@ -100,31 +128,31 @@ const router = new Router({ { path: 'favourites', name: 'favourites', - component: require('@/components/TimelineSpace/Contents/Favourites').default + component: TimelineSpaceContentsFavourites }, { path: 'local', name: 'local', - component: require('@/components/TimelineSpace/Contents/Local').default + component: TimelineSpaceContentsLocal }, { path: 'public', name: 'public', - component: require('@/components/TimelineSpace/Contents/Public').default + component: TimelineSpaceContentsPublic }, { path: 'hashtag/', - component: require('@/components/TimelineSpace/Contents/Hashtag').default, + component: TimelineSpaceContentsHashtag, children: [ { path: '', name: 'hashtag-list', - component: require('@/components/TimelineSpace/Contents/Hashtag/List').default + component: TimelineSpaceContentsHashtagList }, { path: ':tag', name: 'tag', - component: require('@/components/TimelineSpace/Contents/Hashtag/Tag').default, + component: TimelineSpaceContentsHashtagTag, props: true } ] @@ -132,28 +160,28 @@ const router = new Router({ { path: 'search', name: 'search', - component: require('@/components/TimelineSpace/Contents/Search').default + component: TimelineSpaceContentsSearch }, { path: 'direct-messages', name: 'direct-messages', - component: require('@/components/TimelineSpace/Contents/DirectMessages').default + component: TimelineSpaceContentsDirectMessages }, { path: 'lists', name: 'lists', - component: require('@/components/TimelineSpace/Contents/Lists/Index').default + component: TimelineSpaceContentsListsIndex }, { path: 'lists/:list_id/edit', name: 'edit-list', - component: require('@/components/TimelineSpace/Contents/Lists/Edit').default, + component: TimelineSpaceContentsListsEdit, props: true }, { path: 'lists/:list_id', name: 'list', - component: require('@/components/TimelineSpace/Contents/Lists/Show').default, + component: TimelineSpaceContentsListsShow, props: true } ] diff --git a/src/renderer/store/App.ts b/src/renderer/store/App.ts index ed5415cd..9b1693ec 100644 --- a/src/renderer/store/App.ts +++ b/src/renderer/store/App.ts @@ -1,4 +1,3 @@ -import { ipcRenderer } from 'electron' import { MutationTree, ActionTree, Module } from 'vuex' import router from '@/router' import { LightTheme, DarkTheme, SolarizedLightTheme, SolarizedDarkTheme, KimbieDarkTheme, ThemeColorType } from '~/src/constants/themeColor' @@ -12,6 +11,9 @@ import { Notify } from '~/src/types/notify' import { BaseConfig } from '~/src/types/preference' import { Appearance } from '~/src/types/appearance' import { ProxyConfig } from 'megalodon' +import { MyWindow } from '~/src/types/global' + +const win = window as MyWindow export type AppState = { theme: ThemeColorType @@ -107,22 +109,22 @@ const mutations: MutationTree = { const actions: ActionTree = { watchShortcutsEvents: () => { - ipcRenderer.on('open-preferences', () => { + win.ipcRenderer.on('open-preferences', () => { router.push('/preferences/general') }) }, removeShortcutsEvents: () => { - ipcRenderer.removeAllListeners('open-preferences') + win.ipcRenderer.removeAllListeners('open-preferences') }, loadPreferences: ({ commit, dispatch }) => { return new Promise((resolve, reject) => { - ipcRenderer.send('get-preferences') - ipcRenderer.once('error-get-preferences', (_, err: Error) => { - ipcRenderer.removeAllListeners('response-get-preferences') + win.ipcRenderer.send('get-preferences') + win.ipcRenderer.once('error-get-preferences', (_, err: Error) => { + win.ipcRenderer.removeAllListeners('response-get-preferences') reject(err) }) - ipcRenderer.once('response-get-preferences', (_, conf: BaseConfig) => { - ipcRenderer.removeAllListeners('error-get-preferences') + win.ipcRenderer.once('response-get-preferences', (_, conf: BaseConfig) => { + win.ipcRenderer.removeAllListeners('error-get-preferences') dispatch('updateTheme', conf.appearance) commit(MUTATION_TYPES.UPDATE_DISPLAY_NAME_STYLE, conf.appearance.displayNameStyle) commit(MUTATION_TYPES.UPDATE_FONT_SIZE, conf.appearance.fontSize) @@ -166,11 +168,11 @@ const actions: ActionTree = { }, loadProxy: ({ commit }) => { return new Promise(resolve => { - ipcRenderer.once('response-get-proxy-configuration', (_, proxy: ProxyConfig | false) => { + win.ipcRenderer.once('response-get-proxy-configuration', (_, proxy: ProxyConfig | false) => { commit(MUTATION_TYPES.UPDATE_PROXY_CONFIGURATION, proxy) resolve(proxy) }) - ipcRenderer.send('get-proxy-configuration') + win.ipcRenderer.send('get-proxy-configuration') }) } } diff --git a/src/renderer/store/index.ts b/src/renderer/store/index.ts index b060fee0..49365d6c 100644 --- a/src/renderer/store/index.ts +++ b/src/renderer/store/index.ts @@ -11,10 +11,13 @@ import TimelineSpace, { TimelineSpaceModuleState } from './TimelineSpace' import Preferences, { PreferencesModuleState } from './Preferences' import Settings, { SettingsModuleState } from './Settings' import organisms, { OrganismsModuleState } from './organisms' +import { MyWindow } from '~/src/types/global' Vue.use(Vuex) -export type RootState = { +const win = window as MyWindow + +export interface RootState { App: AppState GlobalHeader: GlobalHeaderState Login: LoginState @@ -27,8 +30,8 @@ export type RootState = { } export default new Vuex.Store({ - strict: process.env.NODE_ENV !== 'production', - plugins: process.env.NODE_ENV !== 'production' ? [createLogger({})] : [], + strict: win.process.env.NODE_ENV !== 'production', + plugins: win.process.env.NODE_ENV !== 'production' ? [createLogger({})] : [], modules: { App, GlobalHeader, diff --git a/src/types/global.ts b/src/types/global.ts new file mode 100644 index 00000000..beedd48c --- /dev/null +++ b/src/types/global.ts @@ -0,0 +1,7 @@ +import { Shell, IpcRenderer } from 'electron' + +export interface MyWindow extends Window { + shell: Shell + ipcRenderer: IpcRenderer + process: NodeJS.Process +} From e8bfffc58b34664435e9b3ce46076364798a5642 Mon Sep 17 00:00:00 2001 From: AkiraFukushima Date: Fri, 10 May 2019 00:05:40 +0900 Subject: [PATCH 2/5] refs #901 Replace shell and clipboard using window object --- spec/renderer/integration/store/App.spec.ts | 13 +- src/main/preload.js | 2 + .../Contents/SideBar/AccountProfile.vue | 241 +++++++++--------- .../TimelineSpace/Modals/NewToot.vue | 3 +- .../components/TimelineSpace/SideMenu.vue | 3 +- .../organisms/Notification/Favourite.vue | 3 +- .../organisms/Notification/Reblog.vue | 3 +- src/renderer/components/organisms/Toot.vue | 7 +- src/types/global.ts | 3 +- 9 files changed, 144 insertions(+), 134 deletions(-) diff --git a/spec/renderer/integration/store/App.spec.ts b/spec/renderer/integration/store/App.spec.ts index 5a5376f0..15da405a 100644 --- a/spec/renderer/integration/store/App.spec.ts +++ b/spec/renderer/integration/store/App.spec.ts @@ -1,6 +1,6 @@ import { createLocalVue } from '@vue/test-utils' import Vuex from 'vuex' -import { ipcMain } from '~/spec/mock/electron' +import { ipcMain, ipcRenderer } from '~/spec/mock/electron' import App from '@/store/App' import DisplayStyle from '~/src/constants/displayStyle' import { LightTheme, DarkTheme } from '~/src/constants/themeColor' @@ -8,6 +8,7 @@ import Theme from '~/src/constants/theme' import TimeFormat from '~/src/constants/timeFormat' import Language from '~/src/constants/language' import DefaultFonts from '@/utils/fonts' +import { MyWindow } from '~/src/types/global' const state = () => { return { @@ -43,6 +44,7 @@ describe('App', () => { let localVue beforeEach(() => { + ;(window).ipcRenderer = ipcRenderer localVue = createLocalVue() localVue.use(Vuex) store = new Vuex.Store({ @@ -58,11 +60,10 @@ describe('App', () => { ipcMain.once('get-preferences', (event: any, _) => { event.sender.send('error-get-preferences', new Error()) }) - await store.dispatch('App/loadPreferences') - .catch((err) => { - expect(err instanceof Error).toEqual(true) - expect(store.state.App.theme).toEqual(LightTheme) - }) + await store.dispatch('App/loadPreferences').catch(err => { + expect(err instanceof Error).toEqual(true) + expect(store.state.App.theme).toEqual(LightTheme) + }) }) }) describe('success', () => { diff --git a/src/main/preload.js b/src/main/preload.js index 9ecab4db..0b913b3c 100644 --- a/src/main/preload.js +++ b/src/main/preload.js @@ -1,3 +1,5 @@ const electron = require('electron') global.ipcRenderer = electron.ipcRenderer +global.shell = electron.shell +global.clipboard = electron.clipboard global.process = process diff --git a/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile.vue b/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile.vue index 09232ac0..5271af91 100644 --- a/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile.vue +++ b/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile.vue @@ -1,114 +1,125 @@