refs #982 Load system proxy configuration when launch app

This commit is contained in:
AkiraFukushima 2019-10-27 13:29:49 +09:00
parent 54bac6744c
commit a0a0838fb4
5 changed files with 155 additions and 0 deletions

View File

@ -0,0 +1,60 @@
import path from 'path'
import ProxyConfiguration from '~/src/main/proxy'
import { ManualProxy, ProxyProtocol } from '~/src/types/proxy'
const preferencesDBPath = path.resolve(__dirname, '../../preferences.json')
const proxyConfiguration = new ProxyConfiguration(preferencesDBPath)
describe('Parser', () => {
it('do not use proxy', () => {
proxyConfiguration.setSystemProxy('DIRECT')
const proxy = proxyConfiguration.parseSystemProxy()
expect(proxy).toEqual(false)
})
it('HTTP and HTTPS proxy', () => {
proxyConfiguration.setSystemProxy('PROXY hoge.example.com:8080')
const proxy = proxyConfiguration.parseSystemProxy()
expect(proxy).not.toBe(false)
const manualProxy = proxy as ManualProxy
expect(manualProxy.protocol).toEqual(ProxyProtocol.http)
expect(manualProxy.host).toEqual('hoge.example.com')
expect(manualProxy.port).toEqual('8080')
})
it('SOCKS4 proxy', () => {
proxyConfiguration.setSystemProxy('SOCKS4 hoge.example.com:8080')
const proxy = proxyConfiguration.parseSystemProxy()
expect(proxy).not.toBe(false)
const manualProxy = proxy as ManualProxy
expect(manualProxy.protocol).toEqual(ProxyProtocol.socks4)
})
it('SOCKS4A proxy', () => {
proxyConfiguration.setSystemProxy('SOCKS4A hoge.example.com:8080')
const proxy = proxyConfiguration.parseSystemProxy()
expect(proxy).not.toBe(false)
const manualProxy = proxy as ManualProxy
expect(manualProxy.protocol).toEqual(ProxyProtocol.socks4a)
})
it('SOCKS5 proxy', () => {
proxyConfiguration.setSystemProxy('SOCKS5 hoge.example.com:8080')
const proxy = proxyConfiguration.parseSystemProxy()
expect(proxy).not.toBe(false)
const manualProxy = proxy as ManualProxy
expect(manualProxy.protocol).toEqual(ProxyProtocol.socks5)
})
it('SOCKS5H proxy', () => {
proxyConfiguration.setSystemProxy('SOCKS5H hoge.example.com:8080')
const proxy = proxyConfiguration.parseSystemProxy()
expect(proxy).not.toBe(false)
const manualProxy = proxy as ManualProxy
expect(manualProxy.protocol).toEqual(ProxyProtocol.socks5h)
})
it('SOCKS proxy', () => {
proxyConfiguration.setSystemProxy('SOCKS hoge.example.com:8080')
const proxy = proxyConfiguration.parseSystemProxy()
expect(proxy).not.toBe(false)
const manualProxy = proxy as ManualProxy
expect(manualProxy.protocol).toEqual(ProxyProtocol.socks5)
})
})

1
spec/preferences.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -4,6 +4,7 @@ import {
app,
ipcMain,
shell,
session,
Menu,
Tray,
BrowserWindow,
@ -45,6 +46,7 @@ import HashtagCache from './cache/hashtag'
import AccountCache from './cache/account'
import { InsertAccountCache } from '~/src/types/insertAccountCache'
import { Proxy } from '~/src/types/proxy'
import ProxyConfiguration from './proxy'
/**
* Context menu
@ -144,6 +146,7 @@ const soundBasePath =
process.env.NODE_ENV === 'development' ? path.join(__dirname, '../../build/sounds/') : path.join(process.resourcesPath!, 'build/sounds/')
let launcher: AutoLaunch | null = null
const proxyConfiguration = new ProxyConfiguration(preferencesDBPath)
// On MAS build, auto launch is not working.
// We have to use Launch Agent: https://github.com/Teamwork/node-auto-launch/issues/43
@ -270,6 +273,16 @@ async function createWindow() {
mainWindow.webContents.on('will-navigate', event => event.preventDefault())
/**
* Get system proxy configuration.
*/
if (session && session.defaultSession) {
session.defaultSession.resolveProxy('https://mastodon.social', proxyInfo => {
proxyConfiguration.setSystemProxy(proxyInfo)
log.info(`System proxy configuration: ${proxyInfo}`)
})
}
mainWindow.on('closed', () => {
mainWindow = null
})
@ -982,6 +995,11 @@ ipcMain.on('update-proxy-config', (event: IpcMainEvent, proxy: Proxy) => {
})
})
ipcMain.on('get-proxy-configuration', async (event: IpcMainEvent) => {
const proxy = await proxyConfiguration.getConfig()
event.sender.send('response-get-proxy-configuration', proxy)
})
// language
ipcMain.on('change-language', (event: IpcMainEvent, value: string) => {
const preferences = new Preferences(preferencesDBPath)

View File

@ -1,4 +1,5 @@
import storage from 'electron-json-storage'
import log from 'electron-log'
import objectAssignDeep from 'object-assign-deep'
import DisplayStyle from '../constants/displayStyle'
import Theme from '../constants/theme'
@ -97,6 +98,7 @@ export default class Preferences {
const preferences = await this.get()
return objectAssignDeep({}, Base, preferences)
} catch (err) {
log.error(err)
return Base
}
}

74
src/main/proxy.ts Normal file
View File

@ -0,0 +1,74 @@
import { ProxySource, ManualProxy, ProxyProtocol } from '~/src/types/proxy'
import Preferences from './preferences'
export default class ProxyConfiguration {
public preferences: Preferences
public systemProxy: string | null = null
constructor(preferencesDBPath: string) {
this.preferences = new Preferences(preferencesDBPath)
}
public setSystemProxy(proxy: string) {
this.systemProxy = proxy
}
public async getConfig(): Promise<false | ManualProxy> {
const conf = await this.preferences.get()
const source = conf.proxy.source as ProxySource
switch (source) {
case ProxySource.no:
return false
case ProxySource.system:
if (this.systemProxy) {
return this.parseSystemProxy()
} else {
return false
}
case ProxySource.manual:
return conf.proxy.manualProxyConfig
}
}
public parseSystemProxy(): ManualProxy | false {
if (!this.systemProxy) {
return false
}
if (this.systemProxy === 'DIRECT') {
return false
}
const result = this.systemProxy.match(/^([A-Z0-9]+)\s+([a-z0-9-_.]+):([0-9]+)$/)
if (!result || result.length !== 4) {
return false
}
let protocol = ProxyProtocol.http
switch (result[1]) {
case 'PROXY':
protocol = ProxyProtocol.http
break
case 'SOCKS4':
protocol = ProxyProtocol.socks4
break
case 'SOCKS4A':
protocol = ProxyProtocol.socks4a
break
case 'SOCKS5':
protocol = ProxyProtocol.socks5
break
case 'SOCKS5H':
protocol = ProxyProtocol.socks5h
break
case 'SOCKS':
protocol = ProxyProtocol.socks5
break
}
const manual: ManualProxy = {
protocol: protocol,
host: result[2],
port: result[3],
username: '',
password: ''
}
return manual
}
}