diff options
Diffstat (limited to 'app/lib')
| -rw-r--r-- | app/lib/backend.js | 192 | ||||
| -rw-r--r-- | app/lib/formatters.js | 4 | ||||
| -rw-r--r-- | app/lib/ipc-facade.js | 288 | ||||
| -rw-r--r-- | app/lib/jsonrpc-ws-ipc.js | 67 | ||||
| -rw-r--r-- | app/lib/keyframe-animation.js | 120 | ||||
| -rw-r--r-- | app/lib/problem-report.android.js | 2 | ||||
| -rw-r--r-- | app/lib/problem-report.js | 18 | ||||
| -rw-r--r-- | app/lib/proc.js | 8 | ||||
| -rw-r--r-- | app/lib/relay-settings-builder.js | 67 | ||||
| -rw-r--r-- | app/lib/rpc-file-security.js | 23 | ||||
| -rw-r--r-- | app/lib/styles.js | 10 | ||||
| -rw-r--r-- | app/lib/tempdir.js | 26 | ||||
| -rw-r--r-- | app/lib/transition-rule.js | 17 | ||||
| -rw-r--r-- | app/lib/tray-icon-manager.js | 10 |
14 files changed, 448 insertions, 404 deletions
diff --git a/app/lib/backend.js b/app/lib/backend.js index 27b4b2c927..b043a9b10e 100644 --- a/app/lib/backend.js +++ b/app/lib/backend.js @@ -11,7 +11,14 @@ import type { ReduxStore } from '../redux/store'; import type { AccountToken, BackendState, RelaySettingsUpdate } from './ipc-facade'; import type { ConnectionState } from '../redux/connection/reducers'; -export type ErrorType = 'NO_CREDIT' | 'NO_INTERNET' | 'NO_DAEMON' | 'INVALID_ACCOUNT' | 'NO_ACCOUNT' | 'COMMUNICATION_FAILURE' | 'UNKNOWN_ERROR' ; +export type ErrorType = + | 'NO_CREDIT' + | 'NO_INTERNET' + | 'NO_DAEMON' + | 'INVALID_ACCOUNT' + | 'NO_ACCOUNT' + | 'COMMUNICATION_FAILURE' + | 'UNKNOWN_ERROR'; export class BackendError extends Error { type: ErrorType; @@ -28,55 +35,50 @@ export class BackendError extends Error { } static localizedTitle(type: ErrorType): string { - switch(type) { - case 'NO_CREDIT': - return 'Out of time'; - case 'NO_INTERNET': - return 'Offline'; - default: - return 'Something went wrong'; + switch (type) { + case 'NO_CREDIT': + return 'Out of time'; + case 'NO_INTERNET': + return 'Offline'; + default: + return 'Something went wrong'; } } static localizedMessage(type: ErrorType, cause: ?Error): string { - // TODO: since instanceof now works, BackendError can be replaced by a set // of specific error types - switch(type) { - case 'NO_CREDIT': - return 'Buy more time, so you can continue using the internet securely'; - case 'NO_INTERNET': - return 'Your internet connection will be secured when you get back online'; - case 'INVALID_ACCOUNT': - return 'Invalid account number'; - case 'NO_ACCOUNT': - return 'No account was set'; - case 'NO_DAEMON': - return 'Could not connect to the Mullvad daemon'; - case 'COMMUNICATION_FAILURE': - return 'api.mullvad.net is blocked, please check your firewall'; - case 'UNKNOWN_ERROR': { - const message = cause - ? ', ' + cause.message - : ''; + switch (type) { + case 'NO_CREDIT': + return 'Buy more time, so you can continue using the internet securely'; + case 'NO_INTERNET': + return 'Your internet connection will be secured when you get back online'; + case 'INVALID_ACCOUNT': + return 'Invalid account number'; + case 'NO_ACCOUNT': + return 'No account was set'; + case 'NO_DAEMON': + return 'Could not connect to the Mullvad daemon'; + case 'COMMUNICATION_FAILURE': + return 'api.mullvad.net is blocked, please check your firewall'; + case 'UNKNOWN_ERROR': { + const message = cause ? ', ' + cause.message : ''; - return 'An unknown error occurred' + message; - } - default: - return ''; + return 'An unknown error occurred' + message; + } + default: + return ''; } } - } - export type IpcCredentials = { connectionString: string, sharedSecret: string, }; export function parseIpcCredentials(data: string): ?IpcCredentials { const [connectionString, sharedSecret] = data.split('\n', 2); - if(connectionString && sharedSecret !== undefined) { + if (connectionString && sharedSecret !== undefined) { return { connectionString, sharedSecret, @@ -86,12 +88,10 @@ export function parseIpcCredentials(data: string): ?IpcCredentials { } } - /** * Backend implementation */ export class Backend { - _ipc: IpcFacade; _credentials: ?IpcCredentials; _authenticationPromise: ?Promise<void>; @@ -101,8 +101,7 @@ export class Backend { this._store = store; this._credentials = credentials; - - if(ipc) { + if (ipc) { this._ipc = ipc; // force to re-authenticate when connection closed @@ -137,19 +136,19 @@ export class Backend { try { await this._fetchRelayLocations(); - } catch(e) { + } catch (e) { log.error('Failed to fetch the relay locations: ', e.message); } try { await this._fetchLocation(); - } catch(e) { + } catch (e) { log.error('Failed to fetch the location: ', e.message); } try { await this._fetchAllowLan(); - } catch(e) { + } catch (e) { log.error('Failed to fetch the LAN sharing policy: ', e.message); } @@ -172,9 +171,7 @@ export class Backend { log.info('Log in complete'); - this._store.dispatch( - accountActions.loginSuccessful(accountData.expiry) - ); + this._store.dispatch(accountActions.loginSuccessful(accountData.expiry)); await this.fetchRelaySettings(); // Redirect the user after some time to allow for @@ -186,8 +183,7 @@ export class Backend { }, 1000); await this._fetchAccountHistory(); - - } catch(e) { + } catch (e) { log.error('Failed to log in,', e.message); const err = this._rpcErrorToBackendError(e); @@ -202,15 +198,15 @@ export class Backend { const isJsonRpcError = e.hasOwnProperty('code'); if (isJsonRpcError) { - switch(e.code) { - case -200: // Account doesn't exist - return new BackendError('INVALID_ACCOUNT'); - case -32603: // Internal error - // We treat all internal backend errors as the user cannot reach - // api.mullvad.net. This is not always true of course, but it is - // true so often that we choose to disregard the other edge cases - // for now. - return new BackendError('COMMUNICATION_FAILURE'); + switch (e.code) { + case -200: // Account doesn't exist + return new BackendError('INVALID_ACCOUNT'); + case -32603: // Internal error + // We treat all internal backend errors as the user cannot reach + // api.mullvad.net. This is not always true of course, but it is + // true so often that we choose to disregard the other edge cases + // for now. + return new BackendError('COMMUNICATION_FAILURE'); } } @@ -230,7 +226,7 @@ export class Backend { this._store.dispatch(accountActions.startLogin()); const accountToken = await this._ipc.getAccount(); - if(!accountToken) { + if (!accountToken) { throw new BackendError('NO_ACCOUNT'); } @@ -322,19 +318,19 @@ export class Backend { const relaySettings = await this._ipc.getRelaySettings(); log.debug('Got relay settings from backend', JSON.stringify(relaySettings)); - if(relaySettings.normal) { + if (relaySettings.normal) { const payload = {}; const normal = relaySettings.normal; const tunnel = normal.tunnel; const location = normal.location; - if(location === 'any') { + if (location === 'any') { payload.location = 'any'; } else { payload.location = location.only; } - if(tunnel === 'any') { + if (tunnel === 'any') { payload.port = 'any'; payload.protocol = 'any'; } else { @@ -345,19 +341,26 @@ export class Backend { this._store.dispatch( settingsActions.updateRelay({ - normal: payload - }) + normal: payload, + }), ); - } else if(relaySettings.custom_tunnel_endpoint) { + } else if (relaySettings.custom_tunnel_endpoint) { const custom_tunnel_endpoint = relaySettings.custom_tunnel_endpoint; - const { host, tunnel: { openvpn: { port, protocol } } } = custom_tunnel_endpoint; + const { + host, + tunnel: { + openvpn: { port, protocol }, + }, + } = custom_tunnel_endpoint; this._store.dispatch( settingsActions.updateRelay({ custom_tunnel_endpoint: { - host, port, protocol - } - }) + host, + port, + protocol, + }, + }), ); } } @@ -367,7 +370,7 @@ export class Backend { await this._ensureAuthenticated(); await this._ipc.removeAccountFromHistory(accountToken); await this._fetchAccountHistory(); - } catch(e) { + } catch (e) { log.error('Failed to remove account token from history', e.message); } } @@ -376,10 +379,8 @@ export class Backend { try { await this._ensureAuthenticated(); const accountHistory = await this._ipc.getAccountHistory(); - this._store.dispatch( - accountActions.updateAccountHistory(accountHistory) - ); - } catch(e) { + this._store.dispatch(accountActions.updateAccountHistory(accountHistory)); + } catch (e) { log.info('Failed to fetch account history,', e.message); throw e; } @@ -402,12 +403,10 @@ export class Backend { latitude: city.latitude, longitude: city.longitude, hasActiveRelays: city.has_active_relays, - })) + })), })); - this._store.dispatch( - settingsActions.updateRelayLocations(storedLocations) - ); + this._store.dispatch(settingsActions.updateRelayLocations(storedLocations)); } async _fetchLocation() { @@ -426,9 +425,7 @@ export class Backend { mullvadExitIp: location.mullvad_exit_ip, }; - this._store.dispatch( - connectionActions.newLocation(locationUpdate) - ); + this._store.dispatch(connectionActions.newLocation(locationUpdate)); } async setAllowLan(allowLan: boolean) { @@ -436,10 +433,8 @@ export class Backend { await this._ensureAuthenticated(); await this._ipc.setAllowLan(allowLan); - this._store.dispatch( - settingsActions.updateAllowLan(allowLan) - ); - } catch(e) { + this._store.dispatch(settingsActions.updateAllowLan(allowLan)); + } catch (e) { log.error('Failed to change the LAN sharing policy: ', e.message); } } @@ -448,9 +443,7 @@ export class Backend { await this._ensureAuthenticated(); const allowLan = await this._ipc.getAllowLan(); - this._store.dispatch( - settingsActions.updateAllowLan(allowLan) - ); + this._store.dispatch(settingsActions.updateAllowLan(allowLan)); } async fetchSecurityState() { @@ -478,9 +471,7 @@ export class Backend { // update online status in background setTimeout(() => { - const action = navigator.onLine - ? connectionActions.online() - : connectionActions.offline(); + const action = navigator.onLine ? connectionActions.online() : connectionActions.offline(); this._store.dispatch(action); }, 0); @@ -488,8 +479,7 @@ export class Backend { async _registerIpcListeners() { await this._ensureAuthenticated(); - this._ipc.registerStateListener(newState => { - + this._ipc.registerStateListener((newState) => { const connectionState = this._securityStateToConnectionState(newState); log.debug(`Got new state from backend {state: ${newState.state}, \ target_state: ${newState.target_state}}, translated to '${connectionState}'`); @@ -510,23 +500,23 @@ export class Backend { } _dispatchConnectionState(connectionState: ConnectionState) { - switch(connectionState) { - case 'connecting': - this._store.dispatch(connectionActions.connecting()); - break; - case 'connected': - this._store.dispatch(connectionActions.connected()); - break; - case 'disconnected': - this._store.dispatch(connectionActions.disconnected()); - break; + switch (connectionState) { + case 'connecting': + this._store.dispatch(connectionActions.connecting()); + break; + case 'connected': + this._store.dispatch(connectionActions.connected()); + break; + case 'disconnected': + this._store.dispatch(connectionActions.disconnected()); + break; } } _ensureAuthenticated(): Promise<void> { const credentials = this._credentials; - if(credentials) { - if(!this._authenticationPromise) { + if (credentials) { + if (!this._authenticationPromise) { this._authenticationPromise = this._authenticate(credentials.sharedSecret); } return this._authenticationPromise; diff --git a/app/lib/formatters.js b/app/lib/formatters.js index 89d45d44a0..437351621d 100644 --- a/app/lib/formatters.js +++ b/app/lib/formatters.js @@ -1,9 +1,9 @@ // @flow export const formatAccount = (val: string): string => { // display number altogether when longer than 12 - if(val.length > 12) { + if (val.length > 12) { return val; } // display quartets return val.replace(/([0-9]{4})/g, '$1 ').trim(); -};
\ No newline at end of file +}; diff --git a/app/lib/ipc-facade.js b/app/lib/ipc-facade.js index 0a64a5cc68..0aa1d48d3f 100644 --- a/app/lib/ipc-facade.js +++ b/app/lib/ipc-facade.js @@ -1,7 +1,16 @@ // @flow import JsonRpcWs, { InvalidReply } from './jsonrpc-ws-ipc'; -import { object, maybe, string, number, boolean, enumeration, arrayOf, oneOf } from 'validated/schema'; +import { + object, + maybe, + string, + number, + boolean, + enumeration, + arrayOf, + oneOf, +} from 'validated/schema'; import { validate } from 'validated/object'; import type { Node as SchemaNode } from 'validated/schema'; @@ -45,12 +54,16 @@ type TunnelOptions<TOpenVpnParameters> = { }; type RelaySettingsNormal<TTunnelOptions> = { - location: 'any' | { - only: RelayLocation, - }, - tunnel: 'any' | { - only: TTunnelOptions - }, + location: + | 'any' + | { + only: RelayLocation, + }, + tunnel: + | 'any' + | { + only: TTunnelOptions, + }, }; // types describing the structure of RelaySettings @@ -59,46 +72,60 @@ export type RelaySettingsCustom = { tunnel: { openvpn: { port: number, - protocol: RelayProtocol - } - } + protocol: RelayProtocol, + }, + }, }; -export type RelaySettings = {| - normal: RelaySettingsNormal<TunnelOptions<OpenVpnParameters>> -|} | {| - custom_tunnel_endpoint: RelaySettingsCustom -|}; +export type RelaySettings = + | {| + normal: RelaySettingsNormal<TunnelOptions<OpenVpnParameters>>, + |} + | {| + custom_tunnel_endpoint: RelaySettingsCustom, + |}; // types describing the partial update of RelaySettings -export type RelaySettingsNormalUpdate = $Shape< RelaySettingsNormal< TunnelOptions<$Shape<OpenVpnParameters> > > >; -export type RelaySettingsUpdate = {| - normal: RelaySettingsNormalUpdate -|} | {| - custom_tunnel_endpoint: RelaySettingsCustom -|}; +export type RelaySettingsNormalUpdate = $Shape< + RelaySettingsNormal<TunnelOptions<$Shape<OpenVpnParameters>>>, +>; +export type RelaySettingsUpdate = + | {| + normal: RelaySettingsNormalUpdate, + |} + | {| + custom_tunnel_endpoint: RelaySettingsCustom, + |}; -const constraint = <T>(constraintValue: SchemaNode<T>) => oneOf(string, object({ - only: constraintValue, -})); +const constraint = <T>(constraintValue: SchemaNode<T>) => + oneOf( + string, + object({ + only: constraintValue, + }), + ); const RelaySettingsSchema = oneOf( object({ normal: object({ - location: constraint(oneOf( - object({ - city: arrayOf(string), - }), + location: constraint( + oneOf( + object({ + city: arrayOf(string), + }), + object({ + country: string, + }), + ), + ), + tunnel: constraint( object({ - country: string + openvpn: object({ + port: constraint(number), + protocol: constraint(enumeration('udp', 'tcp')), + }), }), - )), - tunnel: constraint(object({ - openvpn: object({ - port: constraint(number), - protocol: constraint(enumeration('udp', 'tcp')), - }), - })), - }) + ), + }), }), object({ custom_tunnel_endpoint: object({ @@ -107,10 +134,10 @@ const RelaySettingsSchema = oneOf( openvpn: object({ port: number, protocol: enumeration('udp', 'tcp'), - }) - }) - }) - }) + }), + }), + }), + }), ); export type RelayList = { @@ -132,44 +159,46 @@ export type RelayListCity = { }; const RelayListSchema = object({ - countries: arrayOf(object({ - name: string, - code: string, - cities: arrayOf(object({ + countries: arrayOf( + object({ name: string, code: string, - latitude: number, - longitude: number, - has_active_relays: boolean, - })), - })), + cities: arrayOf( + object({ + name: string, + code: string, + latitude: number, + longitude: number, + has_active_relays: boolean, + }), + ), + }), + ), }); - export interface IpcFacade { - setConnectionString(string): void, - getAccountData(AccountToken): Promise<AccountData>, - getRelayLocations(): Promise<RelayList>, - getAccount(): Promise<?AccountToken>, - setAccount(accountToken: ?AccountToken): Promise<void>, - updateRelaySettings(RelaySettingsUpdate): Promise<void>, - getRelaySettings(): Promise<RelaySettings>, - setAllowLan(boolean): Promise<void>, - getAllowLan(): Promise<boolean>, - connect(): Promise<void>, - disconnect(): Promise<void>, - shutdown(): Promise<void>, - getLocation(): Promise<Location>, - getState(): Promise<BackendState>, - registerStateListener((BackendState) => void): void, - setCloseConnectionHandler(() => void): void, - authenticate(sharedSecret: string): Promise<void>, - getAccountHistory(): Promise<Array<AccountToken>>, - removeAccountFromHistory(accountToken: AccountToken): Promise<void>, + setConnectionString(string): void; + getAccountData(AccountToken): Promise<AccountData>; + getRelayLocations(): Promise<RelayList>; + getAccount(): Promise<?AccountToken>; + setAccount(accountToken: ?AccountToken): Promise<void>; + updateRelaySettings(RelaySettingsUpdate): Promise<void>; + getRelaySettings(): Promise<RelaySettings>; + setAllowLan(boolean): Promise<void>; + getAllowLan(): Promise<boolean>; + connect(): Promise<void>; + disconnect(): Promise<void>; + shutdown(): Promise<void>; + getLocation(): Promise<Location>; + getState(): Promise<BackendState>; + registerStateListener((BackendState) => void): void; + setCloseConnectionHandler(() => void): void; + authenticate(sharedSecret: string): Promise<void>; + getAccountHistory(): Promise<Array<AccountToken>>; + removeAccountFromHistory(accountToken: AccountToken): Promise<void>; } export class RealIpc implements IpcFacade { - _ipc: JsonRpcWs; constructor(connectionString: string) { @@ -184,14 +213,13 @@ export class RealIpc implements IpcFacade { // send the IPC with 30s timeout since the backend will wait // for a HTTP request before replying - return this._ipc.send('get_account_data', accountToken, 30000) - .then(raw => { - if (typeof raw === 'object' && raw && raw.expiry) { - return raw; - } else { - throw new InvalidReply(raw, 'Expected an object with expiry'); - } - }); + return this._ipc.send('get_account_data', accountToken, 30000).then((raw) => { + if (typeof raw === 'object' && raw && raw.expiry) { + return raw; + } else { + throw new InvalidReply(raw, 'Expected an object with expiry'); + } + }); } async getRelayLocations(): Promise<RelayList> { @@ -205,19 +233,17 @@ export class RealIpc implements IpcFacade { } getAccount(): Promise<?AccountToken> { - return this._ipc.send('get_account') - .then( raw => { - if (raw === undefined || raw === null || typeof raw === 'string') { - return raw; - } else { - throw new InvalidReply(raw); - } - }); + return this._ipc.send('get_account').then((raw) => { + if (raw === undefined || raw === null || typeof raw === 'string') { + return raw; + } else { + throw new InvalidReply(raw); + } + }); } setAccount(accountToken: ?AccountToken): Promise<void> { - return this._ipc.send('set_account', accountToken) - .then(this._ignoreResponse); + return this._ipc.send('set_account', accountToken).then(this._ignoreResponse); } _ignoreResponse(_response: mixed): void { @@ -225,30 +251,27 @@ export class RealIpc implements IpcFacade { } updateRelaySettings(relaySettings: RelaySettingsUpdate): Promise<void> { - return this._ipc.send('update_relay_settings', [relaySettings]) - .then(this._ignoreResponse); + return this._ipc.send('update_relay_settings', [relaySettings]).then(this._ignoreResponse); } getRelaySettings(): Promise<RelaySettings> { - return this._ipc.send('get_relay_settings') - .then( raw => { - try { - const validated: any = validate(RelaySettingsSchema, raw); - return (validated: RelaySettings); - } catch (e) { - throw new InvalidReply(raw, e); - } - }); + return this._ipc.send('get_relay_settings').then((raw) => { + try { + const validated: any = validate(RelaySettingsSchema, raw); + return (validated: RelaySettings); + } catch (e) { + throw new InvalidReply(raw, e); + } + }); } setAllowLan(allowLan: boolean): Promise<void> { - return this._ipc.send('set_allow_lan', [allowLan]) - .then(this._ignoreResponse); + return this._ipc.send('set_allow_lan', [allowLan]).then(this._ignoreResponse); } async getAllowLan(): Promise<boolean> { const raw = await this._ipc.send('get_allow_lan'); - if(typeof(raw) === 'boolean') { + if (typeof raw === 'boolean') { return raw; } else { throw new InvalidReply(raw, 'Expected a boolean'); @@ -256,45 +279,39 @@ export class RealIpc implements IpcFacade { } connect(): Promise<void> { - return this._ipc.send('connect') - .then(this._ignoreResponse); + return this._ipc.send('connect').then(this._ignoreResponse); } disconnect(): Promise<void> { - return this._ipc.send('disconnect') - .then(this._ignoreResponse); + return this._ipc.send('disconnect').then(this._ignoreResponse); } shutdown(): Promise<void> { - return this._ipc.send('shutdown') - .then(this._ignoreResponse); + return this._ipc.send('shutdown').then(this._ignoreResponse); } getLocation(): Promise<Location> { // send the IPC with 30s timeout since the backend will wait // for a HTTP request before replying - return this._ipc.send('get_current_location', [], 30000) - .then(raw => { - try { - const validated: any = validate(LocationSchema, raw); - return (validated: Location); - } catch (e) { - throw new InvalidReply(raw, e); - } - }); + return this._ipc.send('get_current_location', [], 30000).then((raw) => { + try { + const validated: any = validate(LocationSchema, raw); + return (validated: Location); + } catch (e) { + throw new InvalidReply(raw, e); + } + }); } getState(): Promise<BackendState> { - return this._ipc.send('get_state') - .then(raw => { - return this._parseBackendState(raw); - }); + return this._ipc.send('get_state').then((raw) => { + return this._parseBackendState(raw); + }); } _parseBackendState(raw: mixed): BackendState { if (raw && raw.state && raw.target_state) { - const uncheckedRaw: any = raw; const states: Array<SecurityState> = ['secured', 'unsecured']; @@ -313,7 +330,7 @@ export class RealIpc implements IpcFacade { registerStateListener(listener: (BackendState) => void) { this._ipc.on('new_state', (rawEvent) => { - const parsedEvent : BackendState = this._parseBackendState(rawEvent); + const parsedEvent: BackendState = this._parseBackendState(rawEvent); listener(parsedEvent); }); @@ -324,24 +341,21 @@ export class RealIpc implements IpcFacade { } authenticate(sharedSecret: string): Promise<void> { - return this._ipc.send('auth', sharedSecret) - .then(this._ignoreResponse); + return this._ipc.send('auth', sharedSecret).then(this._ignoreResponse); } getAccountHistory(): Promise<Array<AccountToken>> { - return this._ipc.send('get_account_history') - .then(raw => { - if(Array.isArray(raw) && raw.every(i => typeof i === 'string')) { - const checked: any = raw; - return (checked: Array<AccountToken>); - } else { - throw new InvalidReply(raw, 'Expected an array of strings'); - } - }); + return this._ipc.send('get_account_history').then((raw) => { + if (Array.isArray(raw) && raw.every((i) => typeof i === 'string')) { + const checked: any = raw; + return (checked: Array<AccountToken>); + } else { + throw new InvalidReply(raw, 'Expected an array of strings'); + } + }); } removeAccountFromHistory(accountToken: AccountToken): Promise<void> { - return this._ipc.send('remove_account_from_history', accountToken) - .then(this._ignoreResponse); + return this._ipc.send('remove_account_from_history', accountToken).then(this._ignoreResponse); } } diff --git a/app/lib/jsonrpc-ws-ipc.js b/app/lib/jsonrpc-ws-ipc.js index ecf6309380..eb84607be1 100644 --- a/app/lib/jsonrpc-ws-ipc.js +++ b/app/lib/jsonrpc-ws-ipc.js @@ -9,7 +9,7 @@ export type UnansweredRequest = { reject: (mixed) => void, timerId: TimeoutID, message: Object, -} +}; export type JsonRpcError = { type: 'error', @@ -17,9 +17,9 @@ export type JsonRpcError = { id: string, error: { message: string, - } - } -} + }, + }, +}; export type JsonRpcNotification = { type: 'notification', payload: { @@ -27,16 +27,16 @@ export type JsonRpcNotification = { params: { subscription: string, result: mixed, - } - } -} + }, + }, +}; export type JsonRpcSuccess = { type: 'success', payload: { id: string, result: mixed, - } -} + }, +}; export type JsonRpcMessage = JsonRpcError | JsonRpcNotification | JsonRpcSuccess; export class TimeOutError extends Error { @@ -57,7 +57,7 @@ export class InvalidReply extends Error { this.name = 'InvalidReply'; this.reply = reply; - if(msg) { + if (msg) { this.message = msg + ' - '; } this.message += JSON.stringify(reply); @@ -67,22 +67,22 @@ export class InvalidReply extends Error { const DEFAULT_TIMEOUT_MILLIS = 5000; export default class Ipc { - _connectionString: ?string; - _onConnect: Array<{resolve: ()=>void}>; + _onConnect: Array<{ resolve: () => void }>; _unansweredRequests: Map<string, UnansweredRequest>; - _subscriptions: Map<string|number, (mixed) => void>; + _subscriptions: Map<string | number, (mixed) => void>; _websocket: WebSocket; _backoff: ReconnectionBackoff; _websocketFactory: (string) => WebSocket; _closeConnectionHandler: ?() => void; - constructor(connectionString: string, websocketFactory: ?(string)=>WebSocket) { + constructor(connectionString: string, websocketFactory: ?(string) => WebSocket) { this._connectionString = connectionString; this._onConnect = []; this._unansweredRequests = new Map(); this._subscriptions = new Map(); - this._websocketFactory = websocketFactory || (connectionString => new WebSocket(connectionString)); + this._websocketFactory = + websocketFactory || ((connectionString) => new WebSocket(connectionString)); this._backoff = new ReconnectionBackoff(); this._reconnect(); @@ -97,17 +97,19 @@ export default class Ipc { } on(event: string, listener: (mixed) => void): Promise<*> { - log.debug('Adding a listener to', event); return this.send(event + '_subscribe') - .then(subscriptionId => { + .then((subscriptionId) => { if (typeof subscriptionId === 'string' || typeof subscriptionId === 'number') { this._subscriptions.set(subscriptionId, listener); } else { - throw new InvalidReply(subscriptionId, 'The subscription id was not a string or a number'); + throw new InvalidReply( + subscriptionId, + 'The subscription id was not a string or a number', + ); } }) - .catch(e => { + .catch((e) => { log.error('Failed adding listener to', event, ':', e); }); } @@ -116,7 +118,7 @@ export default class Ipc { return new Promise((resolve, reject) => { const id = uuid.v4(); - const params = this._prepareParams(data); + const params = this._prepareParams(data); const timerId = setTimeout(() => this._onTimeout(id), timeout); const jsonrpcMessage = jsonrpc.request(id, action, params); this._unansweredRequests.set(id, { @@ -127,27 +129,27 @@ export default class Ipc { }); this._getWebSocket() - .then(ws => { + .then((ws) => { log.debug('Sending message', id, action); ws.send(jsonrpcMessage); }) - .catch(e => { + .catch((e) => { log.error('Failed sending RPC message "' + action + '":', e); reject(e); }); }); } - _prepareParams(data: mixed): Array<mixed>|Object { + _prepareParams(data: mixed): Array<mixed> | Object { // JSONRPC only accepts arrays and objects as params, but // this isn't very nice to use, so this method wraps other // types in an array. The choice of array is based on try-and-error - if(data === undefined) { + if (data === undefined) { return []; } else if (data === null) { return [null]; - } else if (Array.isArray(data) || typeof(data) === 'object') { + } else if (Array.isArray(data) || typeof data === 'object') { return data; } else { return [data]; @@ -155,8 +157,9 @@ export default class Ipc { } _getWebSocket(): Promise<WebSocket> { - return new Promise(resolve => { - if (this._websocket && this._websocket.readyState === 1) { // Connected + return new Promise((resolve) => { + if (this._websocket && this._websocket.readyState === 1) { + // Connected resolve(this._websocket); } else { log.debug('Waiting for websocket to connect'); @@ -236,7 +239,7 @@ export default class Ipc { log.debug('Websocket is connected'); this._backoff.successfullyConnected(); - while(this._onConnect.length > 0) { + while (this._onConnect.length > 0) { this._onConnect.pop().resolve(); } }; @@ -251,12 +254,16 @@ export default class Ipc { }; this._websocket.onclose = () => { - if(this._closeConnectionHandler) { + if (this._closeConnectionHandler) { this._closeConnectionHandler(); } const delay = this._backoff.getIncreasedBackoff(); - log.warn('The websocket connetion closed, attempting to reconnect it in', delay, 'milliseconds'); + log.warn( + 'The websocket connetion closed, attempting to reconnect it in', + delay, + 'milliseconds', + ); setTimeout(() => this._reconnect(), delay); }; } diff --git a/app/lib/keyframe-animation.js b/app/lib/keyframe-animation.js index 62d9be6cd8..1b52f859c6 100644 --- a/app/lib/keyframe-animation.js +++ b/app/lib/keyframe-animation.js @@ -8,12 +8,11 @@ export type KeyframeAnimationOptions = { startFrame?: number, endFrame?: number, beginFromCurrentState?: boolean, - advanceTo?: 'end' + advanceTo?: 'end', }; export type KeyframeAnimationRange = [number, number]; export default class KeyframeAnimation { - _speed: number = 200; // ms _repeat: boolean = false; _reverse: boolean = false; @@ -33,40 +32,68 @@ export default class KeyframeAnimation { _timeout = null; - set onFrame(newValue: ?OnFrameFn) { this._onFrame = newValue; } - get onFrame(): ?OnFrameFn { this._onFrame; } + set onFrame(newValue: ?OnFrameFn) { + this._onFrame = newValue; + } + get onFrame(): ?OnFrameFn { + this._onFrame; + } // called when animation finished for non-repeating animations. - set onFinish(newValue: ?OnFinishFn) { this._onFinish = newValue; } - get onFinish(): ?OnFinishFn { this._onFinish; } + set onFinish(newValue: ?OnFinishFn) { + this._onFinish = newValue; + } + get onFinish(): ?OnFinishFn { + this._onFinish; + } // pace per frame in ms - set speed(newValue: number) { this._speed = parseInt(newValue); } - get speed(): number { return this._speed; } + set speed(newValue: number) { + this._speed = parseInt(newValue); + } + get speed(): number { + return this._speed; + } - set repeat(newValue: boolean) { this._repeat = newValue; } - get repeat(): boolean { return this._repeat; } + set repeat(newValue: boolean) { + this._repeat = newValue; + } + get repeat(): boolean { + return this._repeat; + } - set reverse(newValue: boolean) { this._reverse = newValue; } - get reverse(): boolean { return this._repeat; } + set reverse(newValue: boolean) { + this._reverse = newValue; + } + get reverse(): boolean { + return this._repeat; + } // alternates the animation direction when it reaches the end // only for repeating animations - set alternate(newValue: boolean) { this._alternate = !!newValue; } - get alternate(): boolean { return this._alternate; } + set alternate(newValue: boolean) { + this._alternate = !!newValue; + } + get alternate(): boolean { + return this._alternate; + } - get nativeImages(): Array<NativeImage> { return this._nativeImages.slice(); } - get isFinished(): boolean { return this._isFinished; } + get nativeImages(): Array<NativeImage> { + return this._nativeImages.slice(); + } + get isFinished(): boolean { + return this._isFinished; + } // create animation from files matching filename pattern. i.e (bubble-frame-{}.png) static fromFilePattern(filePattern: string, range: KeyframeAnimationRange): KeyframeAnimation { const images: Array<NativeImage> = []; - if(range.length !== 2 || range[0] > range[1]) { + if (range.length !== 2 || range[0] > range[1]) { throw new Error('the animation range is invalid'); } - for(let i = range[0]; i <= range[1]; i++) { + for (let i = range[0]; i <= range[1]; i++) { const filePath = filePattern.replace('{}', i.toString()); const image = nativeImage.createFromPath(filePath); images.push(image); @@ -75,13 +102,15 @@ export default class KeyframeAnimation { } static fromFileSequence(files: Array<string>): KeyframeAnimation { - const images: Array<NativeImage> = files.map(filePath => nativeImage.createFromPath(filePath)); + const images: Array<NativeImage> = files.map((filePath) => + nativeImage.createFromPath(filePath), + ); return new KeyframeAnimation(images); } constructor(images: Array<NativeImage>) { const len = images.length; - if(len < 1) { + if (len < 1) { throw new Error('too few images in animation'); } @@ -97,33 +126,33 @@ export default class KeyframeAnimation { play(options: KeyframeAnimationOptions = {}) { let { startFrame, endFrame, beginFromCurrentState, advanceTo } = options; - if(startFrame !== undefined && endFrame !== undefined) { - if(startFrame < 0 || startFrame >= this._numFrames) { + if (startFrame !== undefined && endFrame !== undefined) { + if (startFrame < 0 || startFrame >= this._numFrames) { throw new Error('Invalid start frame'); } - if(endFrame < 0 || endFrame >= this._numFrames) { + if (endFrame < 0 || endFrame >= this._numFrames) { throw new Error('Invalid end frame'); } - if(startFrame < endFrame) { - this._frameRange = [ startFrame, endFrame ]; + if (startFrame < endFrame) { + this._frameRange = [startFrame, endFrame]; } else { - this._frameRange = [ endFrame, startFrame ]; + this._frameRange = [endFrame, startFrame]; } } else { - this._frameRange = [ 0, this._numFrames - 1 ]; + this._frameRange = [0, this._numFrames - 1]; } - if(!beginFromCurrentState || this._isFirstRun) { + if (!beginFromCurrentState || this._isFirstRun) { this._currentFrame = this._frameRange[this._reverse ? 1 : 0]; } - if(this._isFirstRun) { + if (this._isFirstRun) { this._isFirstRun = false; } - if(advanceTo === 'end') { + if (advanceTo === 'end') { this._currentFrame = this._frameRange[this._reverse ? 0 : 1]; } @@ -142,7 +171,7 @@ export default class KeyframeAnimation { } _unscheduleUpdate() { - if(this._timeout) { + if (this._timeout) { clearTimeout(this._timeout); this._timeout = null; } @@ -153,7 +182,7 @@ export default class KeyframeAnimation { } _render() { - if(this._onFrame) { + if (this._onFrame) { this._onFrame(this._nativeImages[this._currentFrame]); } } @@ -161,7 +190,7 @@ export default class KeyframeAnimation { _didFinish() { this._isFinished = true; - if(this._onFinish) { + if (this._onFinish) { this._onFinish(); } } @@ -169,32 +198,34 @@ export default class KeyframeAnimation { _onUpdateFrame() { this._advanceFrame(); - if(this._isFinished) { + if (this._isFinished) { // mark animation as not running when finished this._isRunning = false; } else { this._render(); // check once again since onFrame() may stop animation - if(this._isRunning) { + if (this._isRunning) { this._scheduleUpdate(); } } } _advanceFrame() { - if(this._isFinished) { return; } + if (this._isFinished) { + return; + } let lastFrame = this._frameRange[this._reverse ? 0 : 1]; - if(this._currentFrame === lastFrame) { + if (this._currentFrame === lastFrame) { // mark animation as finished if it's not repeating - if(!this._repeat) { + if (!this._repeat) { this._didFinish(); return; } // change animation direction if marked for alternation - if(this._alternate) { + if (this._alternate) { this._reverse = !this._reverse; this._currentFrame = this._nextFrame(this._currentFrame, this._frameRange, this._reverse); @@ -207,20 +238,19 @@ export default class KeyframeAnimation { } _nextFrame(cur: number, frameRange: KeyframeAnimationRange, isReverse: boolean): number { - if(isReverse) { - if(cur < frameRange[0]) { + if (isReverse) { + if (cur < frameRange[0]) { return cur + 1; - } else if(cur > frameRange[0]) { + } else if (cur > frameRange[0]) { return cur - 1; } } else { - if(cur > frameRange[1]) { + if (cur > frameRange[1]) { return cur - 1; - } else if(cur < frameRange[1]) { + } else if (cur < frameRange[1]) { return cur + 1; } } return cur; } - } diff --git a/app/lib/problem-report.android.js b/app/lib/problem-report.android.js index 63deb102e4..b0bee2264d 100644 --- a/app/lib/problem-report.android.js +++ b/app/lib/problem-report.android.js @@ -9,4 +9,4 @@ const sendProblemReport = (email: string, message: string, savedReport: string) return MobileAppBridge.sendProblemReport(email, message, savedReport); }; -export { collectProblemReport, sendProblemReport };
\ No newline at end of file +export { collectProblemReport, sendProblemReport }; diff --git a/app/lib/problem-report.js b/app/lib/problem-report.js index 94a435b617..32acb32b93 100644 --- a/app/lib/problem-report.js +++ b/app/lib/problem-report.js @@ -22,14 +22,16 @@ const collectProblemReport = (toRedact: Array<string>): Promise<string> => { }, 10000); responseListener = (_event, id, error, reportPath) => { - if(id !== requestId) { return; } + if (id !== requestId) { + return; + } clearTimeout(requestTimeout); removeResponseListener(); - if(error) { - log.error(`Cannot collect a problem report: ${ error.err }`); - log.error(`Stdout: ${ error.stdout }`); + if (error) { + log.error(`Cannot collect a problem report: ${error.err}`); + log.error(`Stdout: ${error.stdout}`); reject(error); } else { resolve(reportPath); @@ -45,11 +47,7 @@ const collectProblemReport = (toRedact: Array<string>): Promise<string> => { }; const sendProblemReport = (email: string, message: string, savedReport: string) => { - const args = ['send', - '--email', email, - '--message', message, - '--report', savedReport, - ]; + const args = ['send', '--email', email, '--message', message, '--report', savedReport]; const binPath = resolveBin('problem-report'); @@ -71,4 +69,4 @@ const sendProblemReport = (email: string, message: string, savedReport: string) }); }; -export { collectProblemReport, sendProblemReport };
\ No newline at end of file +export { collectProblemReport, sendProblemReport }; diff --git a/app/lib/proc.js b/app/lib/proc.js index d0cd46f886..5e7396fa9a 100644 --- a/app/lib/proc.js +++ b/app/lib/proc.js @@ -17,10 +17,10 @@ function getBasePath() { function getExtension() { switch (process.platform) { - case 'win32': - return '.exe'; + case 'win32': + return '.exe'; - default: - return ''; + default: + return ''; } } diff --git a/app/lib/relay-settings-builder.js b/app/lib/relay-settings-builder.js index 4d83956a00..0386d1ef4f 100644 --- a/app/lib/relay-settings-builder.js +++ b/app/lib/relay-settings-builder.js @@ -5,7 +5,7 @@ import type { RelayProtocol, RelaySettingsUpdate, RelaySettingsNormalUpdate, - RelaySettingsCustom + RelaySettingsCustom, } from './ipc-facade'; type LocationBuilder<Self> = { @@ -18,16 +18,16 @@ type LocationBuilder<Self> = { type OpenVPNConfigurator<Self> = { port: { exact: (port: number) => Self, - any: () => Self + any: () => Self, }, protocol: { exact: (protocol: RelayProtocol) => Self, - any: () => Self - } + any: () => Self, + }, }; type TunnelBuilder<Self> = { - openvpn: (configurator: (OpenVPNConfigurator<*>) => void) => Self + openvpn: (configurator: (OpenVPNConfigurator<*>) => void) => Self, }; class NormalRelaySettingsBuilder { @@ -35,7 +35,7 @@ class NormalRelaySettingsBuilder { build(): RelaySettingsUpdate { return { - normal: this._payload + normal: this._payload, }; } @@ -53,22 +53,23 @@ class NormalRelaySettingsBuilder { this._payload.location = 'any'; return this; }, - fromRaw: function (location: 'any' | RelayLocation) { - if(location === 'any') { + fromRaw: function(location: 'any' | RelayLocation) { + if (location === 'any') { return this.any(); } - if(location.city) { + if (location.city) { const [country, city] = location.city; return this.city(country, city); } - if(location.country) { + if (location.country) { return this.country(location.country); } - throw new Error('Unsupported value of RelayLocation' + - (location && JSON.stringify(location)) ); + throw new Error( + 'Unsupported value of RelayLocation' + (location && JSON.stringify(location)), + ); }, }; } @@ -76,18 +77,18 @@ class NormalRelaySettingsBuilder { get tunnel(): TunnelBuilder<NormalRelaySettingsBuilder> { const updateOpenvpn = (next) => { const tunnel = this._payload.tunnel; - if(typeof(tunnel) === 'string' || typeof(tunnel) === 'undefined') { + if (typeof tunnel === 'string' || typeof tunnel === 'undefined') { this._payload.tunnel = { only: { - openvpn: next - } + openvpn: next, + }, }; - } else if(typeof(tunnel) === 'object') { + } else if (typeof tunnel === 'object') { const prev = (tunnel.only && tunnel.only.openvpn) || {}; this._payload.tunnel = { only: { - openvpn: { ...prev, ...next } - } + openvpn: { ...prev, ...next }, + }, }; } }; @@ -114,7 +115,7 @@ class NormalRelaySettingsBuilder { exact: (value: RelayProtocol) => apply({ only: value }), any: () => apply('any'), }; - } + }, }; configurator(openvpnBuilder); @@ -124,20 +125,18 @@ class NormalRelaySettingsBuilder { any: () => { this._payload.tunnel = 'any'; return this; - } + }, }; } - } - type CustomOpenVPNConfigurator<Self> = { port: (port: number) => Self, - protocol: (protocol: RelayProtocol) => Self + protocol: (protocol: RelayProtocol) => Self, }; type CustomTunnelBuilder<Self> = { - openvpn: (configurator: (CustomOpenVPNConfigurator<*>) => void) => Self + openvpn: (configurator: (CustomOpenVPNConfigurator<*>) => void) => Self, }; class CustomRelaySettingsBuilder { @@ -146,14 +145,14 @@ class CustomRelaySettingsBuilder { tunnel: { openvpn: { port: 0, - protocol: 'udp' - } - } + protocol: 'udp', + }, + }, }; build(): RelaySettingsUpdate { return { - custom_tunnel_endpoint: this._payload + custom_tunnel_endpoint: this._payload, }; } @@ -167,24 +166,24 @@ class CustomRelaySettingsBuilder { const tunnel = this._payload.tunnel || {}; const prev = tunnel.openvpn || {}; this._payload.tunnel = { - openvpn: { ...prev, ...next } + openvpn: { ...prev, ...next }, }; }; return { openvpn: (configurator) => { configurator({ - port: function (port: number) { + port: function(port: number) { updateOpenvpn({ port }); return this; }, - protocol: function (protocol: RelayProtocol) { + protocol: function(protocol: RelayProtocol) { updateOpenvpn({ protocol }); return this; - } + }, }); return this; - } + }, }; } } @@ -192,4 +191,4 @@ class CustomRelaySettingsBuilder { export default { normal: () => new NormalRelaySettingsBuilder(), custom: () => new CustomRelaySettingsBuilder(), -};
\ No newline at end of file +}; diff --git a/app/lib/rpc-file-security.js b/app/lib/rpc-file-security.js index eb1901f67f..fa88111c02 100644 --- a/app/lib/rpc-file-security.js +++ b/app/lib/rpc-file-security.js @@ -4,14 +4,14 @@ import fs from 'fs'; export function canTrustRpcAddressFile(path: string): boolean { const platform = process.platform; - switch(platform) { - case 'win32': - return isOwnedByLocalSystem(path); - case 'darwin': - case 'linux': - return isOwnedAndOnlyWritableByRoot(path); - default: - throw new Error(`Unknown platform: ${platform}`); + switch (platform) { + case 'win32': + return isOwnedByLocalSystem(path); + case 'darwin': + case 'linux': + return isOwnedAndOnlyWritableByRoot(path); + default: + throw new Error(`Unknown platform: ${platform}`); } } @@ -27,7 +27,10 @@ function isOwnedByLocalSystem(path: string): boolean { // $FlowFixMe: this module is only available on Windows const winsec = require('windows-security'); const ownerSid = winsec.getFileOwnerSid(path, null); - const isWellKnownSid = winsec.isWellKnownSid(ownerSid, winsec.WellKnownSid.BuiltinAdministratorsSid); + const isWellKnownSid = winsec.isWellKnownSid( + ownerSid, + winsec.WellKnownSid.BuiltinAdministratorsSid, + ); return isWellKnownSid; -}
\ No newline at end of file +} diff --git a/app/lib/styles.js b/app/lib/styles.js index 840c7c79ab..4cde4fdfce 100644 --- a/app/lib/styles.js +++ b/app/lib/styles.js @@ -4,7 +4,9 @@ import { Styles } from 'reactxp'; type ExtractReturnType = (*) => Object; -export function createViewStyles<T: { [string]: Object }>(styles: T): $ObjMap<T, ExtractReturnType> { +export function createViewStyles<T: { [string]: Object }>( + styles: T, +): $ObjMap<T, ExtractReturnType> { const viewStyles = {}; for (const style of Object.keys(styles)) { viewStyles[style] = Styles.createViewStyle(styles[style]); @@ -12,10 +14,12 @@ export function createViewStyles<T: { [string]: Object }>(styles: T): $ObjMap<T, return viewStyles; } -export function createTextStyles<T: { [string]: Object }>(styles: T): $ObjMap<T, ExtractReturnType> { +export function createTextStyles<T: { [string]: Object }>( + styles: T, +): $ObjMap<T, ExtractReturnType> { const textStyles = {}; for (const style of Object.keys(styles)) { textStyles[style] = Styles.createTextStyle(styles[style]); } return textStyles; -}
\ No newline at end of file +} diff --git a/app/lib/tempdir.js b/app/lib/tempdir.js index e9f65cd03b..a3b4fa6d89 100644 --- a/app/lib/tempdir.js +++ b/app/lib/tempdir.js @@ -3,19 +3,19 @@ import path from 'path'; export function getSystemTemporaryDirectory() { - switch(process.platform) { - case 'win32': { - const windowsPath = process.env.windir; - if(windowsPath) { - return path.join(windowsPath, 'Temp'); - } else { - throw new Error('Missing windir in environment variables.'); + switch (process.platform) { + case 'win32': { + const windowsPath = process.env.windir; + if (windowsPath) { + return path.join(windowsPath, 'Temp'); + } else { + throw new Error('Missing windir in environment variables.'); + } } - } - case 'darwin': - case 'linux': - return '/tmp'; - default: - throw new Error(`Not implemented for ${process.platform}`); + case 'darwin': + case 'linux': + return '/tmp'; + default: + throw new Error(`Not implemented for ${process.platform}`); } } diff --git a/app/lib/transition-rule.js b/app/lib/transition-rule.js index a91ba4da66..dfb56b02ce 100644 --- a/app/lib/transition-rule.js +++ b/app/lib/transition-rule.js @@ -2,21 +2,20 @@ export type TransitionDescriptor = { name: string, - duration: number + duration: number, }; export type TransitionFork = { forward: TransitionDescriptor, - backward: TransitionDescriptor + backward: TransitionDescriptor, }; export type TransitionMatch = { direction: 'forward' | 'backward', - descriptor: TransitionDescriptor + descriptor: TransitionDescriptor, }; export default class TransitionRule { - _from: ?string; _to: string; _fork: TransitionFork; @@ -28,20 +27,20 @@ export default class TransitionRule { } match(fromRoute: ?string, toRoute: string): ?TransitionMatch { - if((!this._from || this._from === fromRoute) && this._to === toRoute) { + if ((!this._from || this._from === fromRoute) && this._to === toRoute) { return { direction: 'forward', - descriptor: this._fork['forward'] + descriptor: this._fork['forward'], }; } - if((!this._from || this._from === toRoute) && this._to === fromRoute) { + if ((!this._from || this._from === toRoute) && this._to === fromRoute) { return { direction: 'backward', - descriptor: this._fork['backward'] + descriptor: this._fork['backward'], }; } return null; } -}
\ No newline at end of file +} diff --git a/app/lib/tray-icon-manager.js b/app/lib/tray-icon-manager.js index 0669c0994a..915bd2c8b8 100644 --- a/app/lib/tray-icon-manager.js +++ b/app/lib/tray-icon-manager.js @@ -7,7 +7,6 @@ import type { Tray } from 'electron'; export type TrayIconType = 'unsecured' | 'securing' | 'secured'; export default class TrayIconManager { - _animation: ?KeyframeAnimation; _iconType: TrayIconType; @@ -22,7 +21,7 @@ export default class TrayIconManager { } destroy() { - if(this._animation) { + if (this._animation) { this._animation.stop(); this._animation = null; } @@ -36,7 +35,7 @@ export default class TrayIconManager { return animation; } - _isReverseAnimation(type: TrayIconType): bool { + _isReverseAnimation(type: TrayIconType): boolean { return type === 'unsecured'; } @@ -45,13 +44,14 @@ export default class TrayIconManager { } set iconType(type: TrayIconType) { - if(this._iconType === type || !this._animation) { return; } + if (this._iconType === type || !this._animation) { + return; + } const animation = this._animation; if (type === 'secured') { animation.reverse = true; animation.play({ beginFromCurrentState: true, startFrame: 8, endFrame: 9 }); - } else { animation.reverse = this._isReverseAnimation(type); animation.play({ beginFromCurrentState: true }); |
