[MM-51873] Create central logging module for adding prefixes to differentiate logs between modules (#2652)

* Create central logging module for adding prefixes to differentiate logs between modules

* Turn logger into class

* Merge'd

* Rework to use class more intelligently

* Fix modalView

* Fix webContentEvents

* Update src/main/app/intercom.ts

Co-authored-by: Daniel Espino García <larkox@gmail.com>

* Shorten prefixes on object creation

---------

Co-authored-by: Daniel Espino García <larkox@gmail.com>
This commit is contained in:
Devin Binnie 2023-04-05 12:09:56 -04:00 committed by GitHub
parent 865b00625e
commit 245215c678
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 409 additions and 240 deletions

View file

@ -1,6 +1,5 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import log from 'electron-log';
import Joi from 'joi';
@ -12,9 +11,11 @@ import {AppState} from 'types/appState';
import {ComparableCertificate} from 'types/certificate';
import {PermissionType, TrustedOrigin} from 'types/trustedOrigin';
import {Logger} from 'common/log';
import {TAB_MESSAGING} from 'common/tabs/TabView';
import urlUtils from 'common/utils/url';
const log = new Logger('Validator');
const defaultOptions = {
stripUnknown: true,
};

View file

@ -3,12 +3,14 @@
// See LICENSE.txt for license information.
import {EventEmitter} from 'events';
import log from 'electron-log';
import WindowsRegistry from 'winreg';
import WindowsRegistryUTF8 from 'winreg-utf8';
import {RegistryConfig as RegistryConfigType, Team} from 'types/config';
import {Logger} from 'common/log';
const log = new Logger('RegistryConfig');
const REGISTRY_HIVE_LIST = [WindowsRegistry.HKLM, WindowsRegistry.HKCU];
const BASE_REGISTRY_KEY_PATH = '\\Software\\Policies\\Mattermost';
export const REGISTRY_READ_EVENT = 'registry-read';
@ -42,7 +44,7 @@ export default class RegistryConfig extends EventEmitter {
this.data.teams!.push(...servers);
}
} catch (error) {
log.warn('[RegistryConfig] Nothing retrieved for \'DefaultServerList\'', error);
log.warn('Nothing retrieved for \'DefaultServerList\'', error);
}
// extract EnableServerManagement from the registry
@ -52,7 +54,7 @@ export default class RegistryConfig extends EventEmitter {
this.data.enableServerManagement = enableServerManagement;
}
} catch (error) {
log.warn('[RegistryConfig] Nothing retrieved for \'EnableServerManagement\'', error);
log.warn('Nothing retrieved for \'EnableServerManagement\'', error);
}
// extract EnableAutoUpdater from the registry
@ -62,7 +64,7 @@ export default class RegistryConfig extends EventEmitter {
this.data.enableAutoUpdater = enableAutoUpdater;
}
} catch (error) {
log.warn('[RegistryConfig] Nothing retrieved for \'EnableAutoUpdater\'', error);
log.warn('Nothing retrieved for \'EnableAutoUpdater\'', error);
}
}
@ -161,9 +163,9 @@ export default class RegistryConfig extends EventEmitter {
}
handleRegistryEntryError(e: Error, hive: string, key: string, name?: string, utf8?: boolean) {
log.verbose('There was an error accessing the registry for', {hive, key, name, utf8}, e);
log.debug('There was an error accessing the registry for', {hive, key, name, utf8}, e);
if (utf8) {
log.verbose('Trying without UTF-8...', {hive, key, name});
log.debug('Trying without UTF-8...', {hive, key, name});
return this.getRegistryEntryValues(hive, key, name, false);
}

View file

@ -8,7 +8,6 @@ import path from 'path';
import {EventEmitter} from 'events';
import {ipcMain, nativeTheme, app} from 'electron';
import log from 'electron-log';
import {
AnyConfig,
@ -22,7 +21,7 @@ import {
import {UPDATE_TEAMS, GET_CONFIGURATION, UPDATE_CONFIGURATION, GET_LOCAL_CONFIGURATION, UPDATE_PATHS} from 'common/communication';
import * as Validator from 'common/Validator';
import {Logger} from 'common/log';
import {getDefaultTeamWithTabsFromTeam} from 'common/tabs/TabView';
import Utils from 'common/utils/util';
@ -34,6 +33,8 @@ import buildConfig from './buildConfig';
import RegistryConfig, {REGISTRY_READ_EVENT} from './RegistryConfig';
import migrateConfigItems from './migrationPreferences';
const log = new Logger('Config');
/**
* Handles loading and merging all sources of configuration as well as saving user provided config
*/
@ -160,7 +161,7 @@ export class Config extends EventEmitter {
* @param {*} data value to save for provided key
*/
set = (key: keyof ConfigType, data: ConfigType[keyof ConfigType]): void => {
log.debug('Config.set');
log.debug('set');
this.setMultiple({[key]: data});
}
@ -184,7 +185,7 @@ export class Config extends EventEmitter {
* @param {array} properties an array of config properties to save
*/
setMultiple = (newData: Partial<ConfigType>) => {
log.debug('Config.setMultiple', newData);
log.debug('setMultiple', newData);
this.localConfigData = Object.assign({}, this.localConfigData, newData);
if (newData.teams && this.localConfigData) {

60
src/common/log.test.js Normal file
View file

@ -0,0 +1,60 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import log from 'electron-log';
import {Logger} from 'common/log';
import Util from 'common/utils/util';
jest.unmock('common/log');
jest.mock('electron-log', () => ({
log: jest.fn(),
}));
jest.mock('common/utils/util', () => ({
shorten: jest.fn(),
}));
describe('common/log', () => {
describe('withPrefix', () => {
beforeEach(() => {
Util.shorten.mockImplementation((string) => {
const maxLength = 20;
if (string.length >= maxLength) {
return `${string.slice(0, maxLength - 3)}...`;
}
return string;
});
});
afterEach(() => {
jest.clearAllMocks();
});
it('should just print the log item without prefixes if not provided', () => {
const logger = new Logger();
logger.log('test item');
expect(log.log).toBeCalledWith('test item');
});
it('should print the log item with a prefix', () => {
const logger = new Logger('prefix');
logger.log('test item');
expect(log.log).toBeCalledWith('[prefix]', 'test item');
});
it('should allow for multiple prefixes', () => {
const logger = new Logger('prefix1', 'prefix2');
logger.log('test item');
expect(log.log).toBeCalledWith('[prefix1]', '[prefix2]', 'test item');
});
it('should truncate really long prefixes', () => {
const logger = new Logger('a really really really long prefix');
logger.log('test item');
expect(log.log).toBeCalledWith('[a really really r...]', 'test item');
});
});
});

52
src/common/log.ts Normal file
View file

@ -0,0 +1,52 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import log, {LevelOption} from 'electron-log';
import Util from 'common/utils/util';
export const setLoggingLevel = (level: string) => {
if (log.transports.file.level === level) {
return;
}
log.error('Logger', 'Log level set to:', level);
log.transports.console.level = level as LevelOption;
log.transports.file.level = level as LevelOption;
};
export class Logger {
private prefixes: string[];
constructor(...prefixes: string[]) {
this.prefixes = this.shortenPrefixes(...prefixes);
}
withPrefix = (...prefixes: string[]) => {
return {
error: this.prefixed(log.error, ...prefixes),
warn: this.prefixed(log.warn, ...prefixes),
info: this.prefixed(log.info, ...prefixes),
verbose: this.prefixed(log.verbose, ...prefixes),
debug: this.prefixed(log.debug, ...prefixes),
silly: this.prefixed(log.silly, ...prefixes),
log: this.prefixed(log.log, ...prefixes),
};
}
private prefixed = (func: (...args: any[]) => void, ...additionalPrefixes: string[]) => {
return (...args: any[]) => func(...this.prefixes, ...this.shortenPrefixes(...additionalPrefixes), ...args);
}
private shortenPrefixes = (...prefixes: string[]) => {
return prefixes.map((prefix) => `[${Util.shorten(prefix)}]`);
}
error = this.prefixed(log.error);
warn = this.prefixed(log.warn);
info = this.prefixed(log.info);
verbose = this.prefixed(log.verbose);
debug = this.prefixed(log.debug);
silly = this.prefixed(log.silly);
log = this.prefixed(log.log);
}

View file

@ -12,7 +12,7 @@ jest.mock('main/constants', () => ({
updatePaths: jest.fn(),
}));
jest.mock('electron-log', () => {
jest.mock('common/log', () => {
const logLevelsFn = {
error: jest.fn(),
warn: jest.fn(),
@ -22,15 +22,13 @@ jest.mock('electron-log', () => {
silly: jest.fn(),
};
return {
create: jest.fn(() => ({
Logger: jest.fn().mockImplementation(() => ({
...logLevelsFn,
withPrefix: () => ({
...logLevelsFn,
}),
})),
...logLevelsFn,
transports: {
file: {
level: '',
},
},
setLoggingLevel: jest.fn(),
};
});

View file

@ -5,7 +5,10 @@
import AutoLaunch from 'auto-launch';
import {app} from 'electron';
import isDev from 'electron-is-dev';
import log from 'electron-log';
import {Logger} from 'common/log';
const log = new Logger('AutoLauncher');
export class AutoLauncher {
appLauncher: AutoLaunch;

View file

@ -8,10 +8,13 @@ import os from 'os';
import path from 'path';
import {app, dialog} from 'electron';
import log from 'electron-log';
import {Logger} from 'common/log';
import {localizeMessage} from 'main/i18nManager';
const log = new Logger('CriticalErrorHandler');
export class CriticalErrorHandler {
init = () => {
process.on('unhandledRejection', this.processUncaughtExceptionHandler);

View file

@ -4,7 +4,10 @@
import {EventEmitter} from 'events';
import {app, powerMonitor} from 'electron';
import log from 'electron-log';
import {Logger} from 'common/log';
const log = new Logger('UserActivityMonitor');
/**
* Monitors system idle time, listens for system events and fires status updates as needed

View file

@ -6,16 +6,18 @@
import fs from 'fs';
import {dialog, shell} from 'electron';
import log from 'electron-log';
import {localizeMessage} from 'main/i18nManager';
import buildConfig from 'common/config/buildConfig';
import {Logger} from 'common/log';
import * as Validator from 'common/Validator';
import MainWindow from './windows/mainWindow';
import {allowedProtocolFile} from './constants';
const log = new Logger('AllowProtocolDialog');
export class AllowProtocolDialog {
allowedProtocols: string[];

View file

@ -2,8 +2,8 @@
// See LICENSE.txt for license information.
import {app, BrowserWindow, Event, dialog, WebContents, Certificate, Details} from 'electron';
import log from 'electron-log';
import {Logger} from 'common/log';
import urlUtils from 'common/utils/url';
import Config from 'common/config';
@ -18,13 +18,15 @@ import {getDeeplinkingURL, openDeepLink, resizeScreen} from './utils';
export const certificateErrorCallbacks = new Map();
const log = new Logger('App.App');
//
// app event handlers
//
// activate first app instance, subsequent instances will quit themselves
export function handleAppSecondInstance(event: Event, argv: string[]) {
log.debug('App.handleAppSecondInstance', argv);
log.debug('handleAppSecondInstance', argv);
// Protocol handler for win32
// argv: An array of the second instances (command line / deep linked) arguments
@ -33,7 +35,7 @@ export function handleAppSecondInstance(event: Event, argv: string[]) {
}
export function handleAppWindowAllClosed() {
log.debug('App.handleAppWindowAllClosed');
log.debug('handleAppWindowAllClosed');
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
@ -43,7 +45,7 @@ export function handleAppWindowAllClosed() {
}
export function handleAppBrowserWindowCreated(event: Event, newWindow: BrowserWindow) {
log.debug('App.handleAppBrowserWindowCreated');
log.debug('handleAppBrowserWindowCreated');
// Screen cannot be required before app is ready
resizeScreen(newWindow);
@ -66,7 +68,7 @@ export function handleAppWillFinishLaunching() {
}
export function handleAppBeforeQuit() {
log.debug('App.handleAppBeforeQuit');
log.debug('handleAppBeforeQuit');
// Make sure tray icon gets removed if the user exits via CTRL-Q
destroyTray();
@ -75,7 +77,7 @@ export function handleAppBeforeQuit() {
}
export async function handleAppCertificateError(event: Event, webContents: WebContents, url: string, error: string, certificate: Certificate, callback: (isTrusted: boolean) => void) {
log.verbose('App.handleAppCertificateError', {url, error, certificate});
log.verbose('handleAppCertificateError', {url, error, certificate});
const parsedURL = urlUtils.parseURL(url);
if (!parsedURL) {

View file

@ -5,10 +5,10 @@ import {app} from 'electron';
import {RELOAD_CONFIGURATION} from 'common/communication';
import Config from 'common/config';
import {setLoggingLevel} from 'common/log';
import {handleConfigUpdate} from 'main/app/config';
import {handleMainWindowIsShown} from 'main/app/intercom';
import {setLoggingLevel} from 'main/app/utils';
import WindowManager from 'main/windows/windowManager';
import AutoLauncher from 'main/AutoLauncher';

View file

@ -2,12 +2,12 @@
// See LICENSE.txt for license information.
import {app, ipcMain} from 'electron';
import log, {LogLevel} from 'electron-log';
import {CombinedConfig} from 'types/config';
import {DARK_MODE_CHANGE, EMIT_CONFIGURATION, RELOAD_CONFIGURATION} from 'common/communication';
import Config from 'common/config';
import {Logger, setLoggingLevel} from 'common/log';
import AutoLauncher from 'main/AutoLauncher';
import {setUnreadBadgeSetting} from 'main/badge';
@ -16,22 +16,21 @@ import LoadingScreen from 'main/views/loadingScreen';
import WindowManager from 'main/windows/windowManager';
import {handleMainWindowIsShown} from './intercom';
import {handleUpdateMenuEvent, setLoggingLevel, updateServerInfos, updateSpellCheckerLocales} from './utils';
import {handleUpdateMenuEvent, updateServerInfos, updateSpellCheckerLocales} from './utils';
const log = new Logger('App.Config');
//
// config event handlers
//
export function handleConfigUpdate(newConfig: CombinedConfig) {
if (log.transports.file.level !== newConfig.logLevel) {
log.error('Log level set to:', newConfig.logLevel);
}
if (newConfig.logLevel) {
setLoggingLevel(newConfig.logLevel as LogLevel);
setLoggingLevel(newConfig.logLevel);
}
log.debug('App.Config.handleConfigUpdate');
log.silly('App.Config.handleConfigUpdate', newConfig);
log.debug('handleConfigUpdate');
log.silly('handleConfigUpdate', newConfig);
if (!newConfig) {
return;
@ -77,7 +76,7 @@ export function handleConfigUpdate(newConfig: CombinedConfig) {
}
export function handleDarkModeChange(darkMode: boolean) {
log.debug('App.Config.handleDarkModeChange', darkMode);
log.debug('handleDarkModeChange', darkMode);
refreshTrayImages(Config.trayIconTheme);
WindowManager.sendToRenderer(DARK_MODE_CHANGE, darkMode);

View file

@ -6,7 +6,6 @@ import path from 'path';
import {app, ipcMain, session} from 'electron';
import installExtension, {REACT_DEVELOPER_TOOLS} from 'electron-devtools-installer';
import isDev from 'electron-is-dev';
import log from 'electron-log';
import {
SWITCH_SERVER,
@ -38,6 +37,7 @@ import {
OPEN_APP_MENU,
} from 'common/communication';
import Config from 'common/config';
import {Logger} from 'common/log';
import urlUtils from 'common/utils/url';
import AllowProtocolDialog from 'main/allowProtocolDialog';
@ -103,6 +103,8 @@ import {
export const mainProtocol = protocols?.[0]?.schemes?.[0];
const log = new Logger('App.Initialize');
/**
* Main entry point for the application, ensures that everything initializes in the proper order
*/
@ -302,7 +304,7 @@ function initializeAfterAppReady() {
if (typeof Config.canUpgrade === 'undefined') {
// windows might not be ready, so we have to wait until it is
Config.once('update', () => {
log.debug('Initialize.checkForUpdates');
log.debug('checkForUpdates');
if (Config.canUpgrade && Config.autoCheckForUpdates) {
setTimeout(() => {
updateManager.checkForUpdates(false);
@ -348,7 +350,7 @@ function initializeAfterAppReady() {
// listen for status updates and pass on to renderer
UserActivityMonitor.on('status', (status) => {
log.debug('Initialize.UserActivityMonitor.on(status)', status);
log.debug('UserActivityMonitor.on(status)', status);
WindowManager.sendToMattermostViews(USER_ACTIVITY_UPDATE, status);
});

View file

@ -2,12 +2,12 @@
// See LICENSE.txt for license information.
import {app, dialog, IpcMainEvent, IpcMainInvokeEvent, Menu} from 'electron';
import log from 'electron-log';
import {Team, TeamWithIndex} from 'types/config';
import {MentionData} from 'types/notification';
import Config from 'common/config';
import {Logger} from 'common/log';
import {getDefaultTeamWithTabsFromTeam} from 'common/tabs/TabView';
import {ping} from 'common/utils/requests';
@ -20,8 +20,10 @@ import MainWindow from 'main/windows/mainWindow';
import {handleAppBeforeQuit} from './app';
import {updateServerInfos} from './utils';
const log = new Logger('App.Intercom');
export function handleReloadConfig() {
log.debug('Intercom.handleReloadConfig');
log.debug('handleReloadConfig');
Config.reload();
WindowManager.handleUpdateConfig();
@ -42,17 +44,17 @@ export function handleQuit(e: IpcMainEvent, reason: string, stack: string) {
}
export function handleSwitchServer(event: IpcMainEvent, serverName: string) {
log.silly('Intercom.handleSwitchServer', serverName);
log.silly('handleSwitchServer', serverName);
WindowManager.switchServer(serverName);
}
export function handleSwitchTab(event: IpcMainEvent, serverName: string, tabName: string) {
log.silly('Intercom.handleSwitchTab', {serverName, tabName});
log.silly('handleSwitchTab', {serverName, tabName});
WindowManager.switchTab(serverName, tabName);
}
export function handleCloseTab(event: IpcMainEvent, serverName: string, tabName: string) {
log.debug('Intercom.handleCloseTab', {serverName, tabName});
log.debug('handleCloseTab', {serverName, tabName});
const teams = Config.teams;
teams.forEach((team) => {
@ -70,7 +72,7 @@ export function handleCloseTab(event: IpcMainEvent, serverName: string, tabName:
}
export function handleOpenTab(event: IpcMainEvent, serverName: string, tabName: string) {
log.debug('Intercom.handleOpenTab', {serverName, tabName});
log.debug('handleOpenTab', {serverName, tabName});
const teams = Config.teams;
teams.forEach((team) => {
@ -87,7 +89,7 @@ export function handleOpenTab(event: IpcMainEvent, serverName: string, tabName:
}
export function handleShowOnboardingScreens(showWelcomeScreen: boolean, showNewServerModal: boolean, mainWindowIsVisible: boolean) {
log.debug('Intercom.handleShowOnboardingScreens', {showWelcomeScreen, showNewServerModal, mainWindowIsVisible});
log.debug('handleShowOnboardingScreens', {showWelcomeScreen, showNewServerModal, mainWindowIsVisible});
if (showWelcomeScreen) {
handleWelcomeScreenModal();
@ -124,7 +126,7 @@ export function handleMainWindowIsShown() {
const mainWindow = MainWindow.get();
log.debug('intercom.handleMainWindowIsShown', {configTeams: Config.teams, showWelcomeScreen, showNewServerModal, mainWindow: Boolean(mainWindow)});
log.debug('handleMainWindowIsShown', {configTeams: Config.teams, showWelcomeScreen, showNewServerModal, mainWindow: Boolean(mainWindow)});
if (mainWindow?.isVisible()) {
handleShowOnboardingScreens(showWelcomeScreen(), showNewServerModal(), true);
} else {
@ -135,7 +137,7 @@ export function handleMainWindowIsShown() {
}
export function handleNewServerModal() {
log.debug('Intercom.handleNewServerModal');
log.debug('handleNewServerModal');
const html = getLocalURLString('newServer.html');
@ -167,7 +169,7 @@ export function handleNewServerModal() {
}
export function handleEditServerModal(e: IpcMainEvent, name: string) {
log.debug('Intercom.handleEditServerModal', name);
log.debug('handleEditServerModal', name);
const html = getLocalURLString('editServer.html');
@ -209,7 +211,7 @@ export function handleEditServerModal(e: IpcMainEvent, name: string) {
}
export function handleRemoveServerModal(e: IpcMainEvent, name: string) {
log.debug('Intercom.handleRemoveServerModal', name);
log.debug('handleRemoveServerModal', name);
const html = getLocalURLString('removeServer.html');
@ -249,7 +251,7 @@ export function handleRemoveServerModal(e: IpcMainEvent, name: string) {
}
export function handleWelcomeScreenModal() {
log.debug('Intercom.handleWelcomeScreenModal');
log.debug('handleWelcomeScreenModal');
const html = getLocalURLString('welcomeScreen.html');
@ -281,12 +283,12 @@ export function handleWelcomeScreenModal() {
}
export function handleMentionNotification(event: IpcMainEvent, title: string, body: string, channel: {id: string}, teamId: string, url: string, silent: boolean, data: MentionData) {
log.debug('Intercom.handleMentionNotification', {title, body, channel, teamId, url, silent, data});
log.debug('handleMentionNotification', {title, body, channel, teamId, url, silent, data});
displayMention(title, body, channel, teamId, url, silent, event.sender, data);
}
export function handleOpenAppMenu() {
log.debug('Intercom.handleOpenAppMenu');
log.debug('handleOpenAppMenu');
const windowMenu = Menu.getApplicationMenu();
if (!windowMenu) {
@ -301,7 +303,7 @@ export function handleOpenAppMenu() {
}
export async function handleSelectDownload(event: IpcMainInvokeEvent, startFrom: string) {
log.debug('Intercom.handleSelectDownload', startFrom);
log.debug('handleSelectDownload', startFrom);
const message = 'Specify the folder where files will download';
const result = await dialog.showOpenDialog({defaultPath: startFrom || Config.downloadLocation,
@ -312,7 +314,7 @@ export async function handleSelectDownload(event: IpcMainInvokeEvent, startFrom:
}
export function handleUpdateLastActive(event: IpcMainEvent, serverName: string, viewName: string) {
log.debug('Intercom.handleUpdateLastActive', {serverName, viewName});
log.debug('handleUpdateLastActive', {serverName, viewName});
const teams = Config.teams;
teams.forEach((team) => {

View file

@ -6,13 +6,13 @@ import path from 'path';
import fs from 'fs-extra';
import {app, BrowserWindow, Menu, Rectangle, Session, session, dialog, nativeImage, screen} from 'electron';
import log, {LevelOption} from 'electron-log';
import {MigrationInfo, TeamWithTabs} from 'types/config';
import {RemoteInfo} from 'types/server';
import {Boundaries} from 'types/utils';
import Config from 'common/config';
import {Logger} from 'common/log';
import JsonFileManager from 'common/JsonFileManager';
import {MattermostServer} from 'common/servers/MattermostServer';
import {TAB_FOCALBOARD, TAB_MESSAGING, TAB_PLAYBOOKS} from 'common/tabs/TabView';
@ -35,6 +35,7 @@ import {mainProtocol} from './initialize';
const assetsDir = path.resolve(app.getAppPath(), 'assets');
const appIconURL = path.resolve(assetsDir, 'appicon_with_spacing_32.png');
const appIcon = nativeImage.createFromPath(appIconURL);
const log = new Logger('App.Utils');
export function openDeepLink(deeplinkingUrl: string) {
try {
@ -104,7 +105,7 @@ function openExtraTabs(data: Array<RemoteInfo | string | undefined>, team: TeamW
}
export function handleUpdateMenuEvent() {
log.debug('Utils.handleUpdateMenuEvent');
log.debug('handleUpdateMenuEvent');
const aMenu = createAppMenu(Config, updateManager);
Menu.setApplicationMenu(aMenu);
@ -193,7 +194,7 @@ function getValidWindowPosition(state: Rectangle) {
export function resizeScreen(browserWindow: BrowserWindow) {
function handle() {
log.debug('Utils.resizeScreen.handle');
log.debug('resizeScreen.handle');
const position = browserWindow.getPosition();
const size = browserWindow.getSize();
const validPosition = getValidWindowPosition({
@ -214,7 +215,7 @@ export function resizeScreen(browserWindow: BrowserWindow) {
}
export function flushCookiesStore(session: Session) {
log.debug('Utils.flushCookiesStore');
log.debug('flushCookiesStore');
session.cookies.flushStore().catch((err) => {
log.error(`There was a problem flushing cookies:\n${err}`);
});
@ -289,8 +290,3 @@ export function migrateMacAppStore() {
log.error('MAS: An error occurred importing the existing configuration', e);
}
}
export function setLoggingLevel(level: LevelOption) {
log.transports.console.level = level;
log.transports.file.level = level;
}

View file

@ -4,12 +4,14 @@
import events from 'events';
import {ipcMain} from 'electron';
import log from 'electron-log';
import {Logger} from 'common/log';
import {UPDATE_MENTIONS, UPDATE_TRAY, UPDATE_BADGE, SESSION_EXPIRED, UPDATE_DROPDOWN_MENTIONS} from 'common/communication';
import WindowManager from './windows/windowManager';
const log = new Logger('AppState');
const status = {
unreads: new Map<string, boolean>(),
mentions: new Map<string, number>(),
@ -23,7 +25,7 @@ const emitMentions = (serverName: string) => {
const isExpired = getIsExpired(serverName);
WindowManager.sendToRenderer(UPDATE_MENTIONS, serverName, newMentions, newUnreads, isExpired);
log.silly('AppState.emitMentions', {serverName, isExpired, newMentions, newUnreads});
log.silly('emitMentions', {serverName, isExpired, newMentions, newUnreads});
emitStatus();
};

View file

@ -1,11 +1,11 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {AuthenticationResponseDetails, AuthInfo, WebContents} from 'electron';
import log from 'electron-log';
import {PermissionType} from 'types/trustedOrigin';
import {LoginModalData} from 'types/auth';
import {Logger} from 'common/log';
import {BASIC_AUTH_PERMISSION} from 'common/permissions';
import urlUtils from 'common/utils/url';
@ -15,6 +15,7 @@ import {getLocalURLString, getLocalPreload} from 'main/utils';
import WindowManager from 'main/windows/windowManager';
import MainWindow from 'main/windows/mainWindow';
const log = new Logger('AuthManager');
const preload = getLocalPreload('desktopAPI.js');
const loginModalHtml = getLocalURLString('loginModal.html');
const permissionModalHtml = getLocalURLString('permissionModal.html');
@ -32,7 +33,7 @@ export class AuthManager {
}
handleAppLogin = (event: Event, webContents: WebContents, request: AuthenticationResponseDetails, authInfo: AuthInfo, callback?: (username?: string, password?: string) => void) => {
log.verbose('AuthManager.handleAppLogin', {request, authInfo});
log.verbose('handleAppLogin', {request, authInfo});
event.preventDefault();
const parsedURL = urlUtils.parseURL(request.url);

View file

@ -4,10 +4,10 @@
import path from 'path';
import {dialog, ipcMain, app, nativeImage} from 'electron';
import log from 'electron-log';
import {autoUpdater, CancellationToken, ProgressInfo, UpdateInfo} from 'electron-updater';
import {Logger} from 'common/log';
import downloadsManager from 'main/downloadsManager';
import {localizeMessage} from 'main/i18nManager';
import {displayUpgrade, displayRestartToUpgrade} from 'main/notifications';
@ -28,7 +28,7 @@ import Config from 'common/config';
const NEXT_NOTIFY = 86400000; // 24 hours
const NEXT_CHECK = 3600000; // 1 hour
log.transports.file.level = 'info';
const log = new Logger('UpdateManager');
autoUpdater.logger = log;
autoUpdater.autoDownload = false;
autoUpdater.disableWebInstaller = true;
@ -64,14 +64,14 @@ export class UpdateManager {
this.cancellationToken = new CancellationToken();
autoUpdater.on('error', (err: Error) => {
log.error(`[Mattermost] There was an error while trying to update: ${err}`);
log.error('There was an error while trying to update', err);
});
autoUpdater.on('update-available', (info: UpdateInfo) => {
autoUpdater.removeListener('update-not-available', this.displayNoUpgrade);
this.versionAvailable = info.version;
ipcMain.emit(UPDATE_SHORTCUT_MENU);
log.info(`[Mattermost] available version ${info.version}`);
log.info('New version available:', info.version);
this.notify();
});
@ -79,7 +79,7 @@ export class UpdateManager {
this.versionDownloaded = info.version;
this.downloadedInfo = info;
ipcMain.emit(UPDATE_SHORTCUT_MENU);
log.info(`[Mattermost] downloaded version ${info.version}`);
log.info('Downloaded version', info.version);
this.notifyDownloaded();
});
@ -88,7 +88,7 @@ export class UpdateManager {
});
ipcMain.on(CANCEL_UPGRADE, () => {
log.info('[Mattermost] User Canceled upgrade');
log.info('User Canceled upgrade');
});
ipcMain.on(CHECK_FOR_UPDATES, () => {
@ -179,7 +179,7 @@ export class UpdateManager {
}
}).catch((reason) => {
ipcMain.emit(NO_UPDATE_AVAILABLE);
log.error(`[Mattermost] Failed to check for updates: ${reason}`);
log.error('Failed to check for updates:', reason);
});
this.lastCheck = setTimeout(() => this.checkForUpdates(false), NEXT_CHECK);
}

View file

@ -3,15 +3,16 @@
// See LICENSE.txt for license information.
import {BrowserWindow, app, nativeImage} from 'electron';
import log from 'electron-log';
import {UPDATE_BADGE} from 'common/communication';
import {Logger} from 'common/log';
import {localizeMessage} from 'main/i18nManager';
import * as AppState from './appState';
import MainWindow from './windows/mainWindow';
const log = new Logger('Badge');
const MAX_WIN_COUNT = 99;
let showUnreadBadgeSetting: boolean;
@ -110,7 +111,7 @@ function showBadgeLinux(sessionExpired: boolean, mentionCount: number) {
}
function showBadge(sessionExpired: boolean, mentionCount: number, showUnreadBadge: boolean) {
log.silly('Badge.showBadge', {sessionExpired, mentionCount, showUnreadBadge});
log.silly('showBadge', {sessionExpired, mentionCount, showUnreadBadge});
switch (process.platform) {
case 'win32':

View file

@ -1,14 +1,17 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import log from 'electron-log';
import {Certificate, WebContents} from 'electron';
import {CertificateModalData} from 'types/certificate';
import {Logger} from 'common/log';
import modalManager from './views/modalManager';
import {getLocalURLString, getLocalPreload} from './utils';
import MainWindow from './windows/mainWindow';
const log = new Logger('CertificateManager');
const preload = getLocalPreload('desktopAPI.js');
const html = getLocalURLString('certificateModal.html');
@ -24,7 +27,7 @@ export class CertificateManager {
}
handleSelectCertificate = (event: Event, webContents: WebContents, url: string, list: Certificate[], callback: (certificate?: Certificate | undefined) => void) => {
log.verbose('CertificateManager.handleSelectCertificate', url, list);
log.verbose('handleSelectCertificate', url, list);
if (list.length > 1) {
event.preventDefault(); // prevent the app from getting the first certificate available

View file

@ -6,11 +6,11 @@
import fs from 'fs';
import {Certificate, ipcMain} from 'electron';
import log from 'electron-log';
import {ComparableCertificate} from 'types/certificate';
import {UPDATE_PATHS} from 'common/communication';
import {Logger} from 'common/log';
import urlUtils from 'common/utils/url';
import * as Validator from 'common/Validator';
@ -94,6 +94,6 @@ let certificateStore = new CertificateStore(certificateStorePath);
export default certificateStore;
ipcMain.on(UPDATE_PATHS, () => {
log.debug('certificateStore.UPDATE_PATHS');
new Logger('certificateStore').debug('UPDATE_PATHS');
certificateStore = new CertificateStore(certificateStorePath);
});

View file

@ -4,7 +4,6 @@ import path from 'path';
import fs from 'fs';
import {DownloadItem, Event, WebContents, FileFilter, ipcMain, dialog, shell, Menu, app} from 'electron';
import log from 'electron-log';
import {ProgressInfo, UpdateInfo} from 'electron-updater';
import {DownloadedItem, DownloadItemDoneEventState, DownloadedItems, DownloadItemState, DownloadItemUpdatedEventState} from 'types/downloads';
@ -26,6 +25,7 @@ import {
} from 'common/communication';
import Config from 'common/config';
import JsonFileManager from 'common/JsonFileManager';
import {Logger} from 'common/log';
import {APP_UPDATE_KEY, UPDATE_DOWNLOAD_ITEM} from 'common/constants';
import {DOWNLOADS_DROPDOWN_AUTOCLOSE_TIMEOUT, DOWNLOADS_DROPDOWN_MAX_ITEMS} from 'common/utils/constants';
import * as Validator from 'common/Validator';
@ -37,6 +37,8 @@ import {doubleSecToMs, getPercentage, isStringWithLength, readFilenameFromConten
import appVersionManager from './AppVersionManager';
import {downloadsJson} from './constants';
const log = new Logger('DownloadsManager');
export enum DownloadItemTypeEnum {
FILE = 'file',
UPDATE = 'update',
@ -68,7 +70,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
private init = () => {
// ensure data loaded from file is valid
const validatedJSON = Validator.validateDownloads(this.json);
log.debug('DownloadsManager.init', {'this.json': this.json, validatedJSON});
log.debug('init', {'this.json': this.json, validatedJSON});
if (validatedJSON) {
this.saveAll(validatedJSON);
} else {
@ -100,7 +102,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
handleNewDownload = async (event: Event, item: DownloadItem, webContents: WebContents) => {
log.debug('DownloadsManager.handleNewDownload', {item, sourceURL: webContents.getURL()});
log.debug('handleNewDownload', {item, sourceURL: webContents.getURL()});
const url = item.getURL();
@ -180,7 +182,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
}
checkForDeletedFiles = () => {
log.debug('DownloadsManager.checkForDeletedFiles');
log.debug('checkForDeletedFiles');
const downloads = this.downloads;
let modified = false;
@ -223,7 +225,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
clearDownloadsDropDown = () => {
log.debug('DownloadsManager.clearDownloadsDropDown');
log.debug('clearDownloadsDropDown');
if (this.hasUpdate()) {
this.saveAll({
@ -238,10 +240,10 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
showFileInFolder = (item?: DownloadedItem) => {
log.debug('DownloadsDropdownView.showFileInFolder', {item});
log.debug('showFileInFolder', {item});
if (!item) {
log.debug('DownloadsDropdownView.showFileInFolder', 'ITEM_UNDEFINED');
log.debug('showFileInFolder', 'ITEM_UNDEFINED');
return;
}
@ -260,14 +262,14 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
return;
}
log.debug('DownloadsDropdownView.showFileInFolder', 'NO_DOWNLOAD_LOCATION');
log.debug('showFileInFolder', 'NO_DOWNLOAD_LOCATION');
};
openFile = (item?: DownloadedItem) => {
log.debug('DownloadsDropdownView.openFile', {item});
log.debug('openFile', {item});
if (!item) {
log.debug('DownloadsDropdownView.openFile', 'FILE_UNDEFINED');
log.debug('openFile', 'FILE_UNDEFINED');
return;
}
@ -282,19 +284,19 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
func = app.startAccessingSecurityScopedResource(bookmark.bookmark);
}
shell.openPath(item.location).catch((err) => {
log.debug('DownloadsDropdownView.openFileError', {err});
log.debug('openFileError', {err});
this.showFileInFolder(item);
});
func?.();
} else {
log.debug('DownloadsDropdownView.openFile', 'COULD_NOT_OPEN_FILE');
log.debug('openFile', 'COULD_NOT_OPEN_FILE');
this.markFileAsDeleted(item);
this.showFileInFolder(item);
}
};
clearFile = (item?: DownloadedItem) => {
log.debug('DownloadsDropdownView.clearFile', {item});
log.debug('clearFile', {item});
if (!item || item.type === DownloadItemTypeEnum.UPDATE) {
return;
@ -311,7 +313,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
cancelDownload = (item?: DownloadedItem) => {
log.debug('DownloadsDropdownView.cancelDownload', {item});
log.debug('cancelDownload', {item});
if (!item) {
return;
@ -346,7 +348,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
hasDownloads = () => {
log.debug('DownloadsManager.hasDownloads');
log.debug('hasDownloads');
return (Object.keys(this.downloads)?.length || 0) > 0;
};
@ -355,7 +357,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
openDownloadsDropdown = () => {
log.debug('DownloadsManager.openDownloadsDropdown');
log.debug('openDownloadsDropdown');
this.open = true;
ipcMain.emit(OPEN_DOWNLOADS_DROPDOWN);
WindowManager.sendToRenderer(HIDE_DOWNLOADS_DROPDOWN_BUTTON_BADGE);
@ -386,7 +388,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
private saveAll = (downloads: DownloadedItems): void => {
log.debug('DownloadsManager.saveAll');
log.debug('saveAll');
this.downloads = downloads;
this.setJson(downloads);
@ -395,7 +397,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
private save = (key: string, item: DownloadedItem) => {
log.debug('DownloadsManager.save');
log.debug('save');
this.downloads[key] = item;
this.setValue(key, item);
ipcMain.emit(UPDATE_DOWNLOADS_DROPDOWN, true, this.downloads);
@ -415,7 +417,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
* This function return true if "downloadLocation" is undefined
*/
private shouldShowSaveDialog = (item: DownloadItem, downloadLocation?: string) => {
log.debug('DownloadsManager.shouldShowSaveDialog', {downloadLocation});
log.debug('shouldShowSaveDialog', {downloadLocation});
return !item.hasUserGesture() || !downloadLocation;
};
@ -433,7 +435,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
private closeDownloadsDropdown = () => {
log.debug('DownloadsManager.closeDownloadsDropdown');
log.debug('closeDownloadsDropdown');
this.open = false;
ipcMain.emit(CLOSE_DOWNLOADS_DROPDOWN);
ipcMain.emit(CLOSE_DOWNLOADS_DROPDOWN_MENU);
@ -449,7 +451,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
private upsertFileToDownloads = (item: DownloadItem, state: DownloadItemState, overridePath?: string) => {
const fileId = this.getFileId(item);
log.debug('DownloadsManager.upsertFileToDownloads', {fileId});
log.debug('upsertFileToDownloads', {fileId});
const formattedItem = this.formatDownloadItem(item, state, overridePath);
this.save(fileId, formattedItem);
this.checkIfMaxFilesReached();
@ -479,7 +481,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
private shouldShowBadge = () => {
log.debug('DownloadsManager.shouldShowBadge');
log.debug('shouldShowBadge');
if (this.open === true) {
WindowManager.sendToRenderer(HIDE_DOWNLOADS_DROPDOWN_BUTTON_BADGE);
@ -492,7 +494,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
* DownloadItem event handlers
*/
private updatedEventController = (updatedEvent: Event, state: DownloadItemUpdatedEventState, item: DownloadItem) => {
log.debug('DownloadsManager.updatedEventController', {state});
log.debug('updatedEventController', {state});
this.upsertFileToDownloads(item, state);
@ -504,7 +506,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
};
private doneEventController = (doneEvent: Event, state: DownloadItemDoneEventState, item: DownloadItem, webContents: WebContents) => {
log.debug('DownloadsManager.doneEventController', {state});
log.debug('doneEventController', {state});
if (state === 'completed' && !this.open) {
displayDownloadCompleted(path.basename(item.savePath), item.savePath, WindowManager.getServerNameByWebContentsId(webContents.id) || '');
@ -536,7 +538,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
this.openDownloadsDropdown();
};
private onUpdateDownloaded = (event: Event, info: UpdateInfo) => {
log.debug('DownloadsManager.onUpdateDownloaded', {info});
log.debug('onUpdateDownloaded', {info});
const {version} = info;
const update = this.downloads[APP_UPDATE_KEY];
@ -548,7 +550,7 @@ export class DownloadsManager extends JsonFileManager<DownloadedItems> {
this.openDownloadsDropdown();
};
private onUpdateProgress = (event: Event, progress: ProgressInfo) => {
log.debug('DownloadsManager.onUpdateProgress', {progress});
log.debug('onUpdateProgress', {progress});
const {total, transferred, percent} = progress;
const update = this.downloads[APP_UPDATE_KEY] || {...UPDATE_DOWNLOAD_ITEM};
if (typeof update.addedAt !== 'number' || update.addedAt === 0) {

View file

@ -2,9 +2,9 @@
// See LICENSE.txt for license information.
import {ipcMain} from 'electron';
import log from 'electron-log';
import {GET_AVAILABLE_LANGUAGES, GET_LANGUAGE_INFORMATION} from 'common/communication';
import {Logger} from 'common/log';
import {Language, languages} from '../../i18n/i18n';
@ -16,6 +16,8 @@ export function localizeMessage(s: string, defaultString = '', values: any = {})
return str;
}
const log = new Logger('i18nManager');
export class I18nManager {
currentLanguage: Language;
@ -27,7 +29,7 @@ export class I18nManager {
}
setLocale = (locale: string) => {
log.debug('i18nManager.setLocale', locale);
log.debug('setLocale', locale);
if (this.isLanguageAvailable(locale)) {
this.currentLanguage = this.getLanguages()[locale];

View file

@ -3,9 +3,10 @@
import {execSync} from 'child_process';
import log from 'electron-log';
import {Logger} from 'common/log';
const GNOME_READ_DND = 'gsettings get org.gnome.desktop.notifications show-banners';
const log = new Logger('Linux-DnD');
function getLinuxDoNotDisturb() {
try {

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
import {app, shell, Notification} from 'electron';
import log from 'electron-log';
import {getDoNotDisturb as getDarwinDoNotDisturb} from 'macos-notification-state';
@ -10,6 +9,7 @@ import {MentionData} from 'types/notification';
import Config from 'common/config';
import {PLAY_SOUND} from 'common/communication';
import {Logger} from 'common/log';
import {TAB_MESSAGING} from 'common/tabs/TabView';
import MainWindow from '../windows/mainWindow';
@ -23,8 +23,10 @@ import getWindowsDoNotDisturb from './dnd-windows';
export const currentNotifications = new Map();
const log = new Logger('Notifications');
export function displayMention(title: string, body: string, channel: {id: string}, teamId: string, url: string, silent: boolean, webcontents: Electron.WebContents, data: MentionData) {
log.debug('Notifications.displayMention', {title, body, channel, teamId, url, silent, data});
log.debug('displayMention', {title, body, channel, teamId, url, silent, data});
if (!Notification.isSupported()) {
log.error('notification not supported');
@ -48,7 +50,7 @@ export function displayMention(title: string, body: string, channel: {id: string
const mentionKey = `${mention.teamId}:${mention.channel.id}`;
mention.on('show', () => {
log.debug('Notifications.displayMention.show');
log.debug('displayMention.show');
// On Windows, manually dismiss notifications from the same channel and only show the latest one
if (process.platform === 'win32') {
@ -77,7 +79,7 @@ export function displayMention(title: string, body: string, channel: {id: string
}
export function displayDownloadCompleted(fileName: string, path: string, serverName: string) {
log.debug('Notifications.displayDownloadCompleted', {fileName, path, serverName});
log.debug('displayDownloadCompleted', {fileName, path, serverName});
if (!Notification.isSupported()) {
log.error('notification not supported');

View file

@ -2,9 +2,11 @@
// See LICENSE.txt for license information.
import {net, session} from 'electron';
import log from 'electron-log';
import {COOKIE_NAME_AUTH_TOKEN, COOKIE_NAME_CSRF, COOKIE_NAME_USER_ID} from 'common/constants';
import {Logger} from 'common/log';
const log = new Logger('serverAPI');
export async function getServerAPI<T>(url: URL, isAuthenticated: boolean, onSuccess?: (data: T) => void, onAbort?: () => void, onError?: (error: Error) => void) {
if (isAuthenticated) {
@ -36,11 +38,11 @@ export async function getServerAPI<T>(url: URL, isAuthenticated: boolean, onSucc
if (onSuccess) {
req.on('response', (response: Electron.IncomingMessage) => {
log.silly('getServerAPI.response', response);
log.silly('response', response);
if (response.statusCode === 200) {
let raw = '';
response.on('data', (chunk: Buffer) => {
log.silly('getServerAPI.response.data', `${chunk}`);
log.silly('response.data', `${chunk}`);
raw += `${chunk}`;
});
response.on('end', () => {

View file

@ -1,14 +1,15 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import log from 'electron-log';
import {ClientConfig, RemoteInfo} from 'types/server';
import {MattermostServer} from 'common/servers/MattermostServer';
import {Logger} from 'common/log';
import {getServerAPI} from './serverAPI';
const log = new Logger('ServerInfo');
export class ServerInfo {
server: MattermostServer;
remoteInfo: RemoteInfo;
@ -57,7 +58,7 @@ export class ServerInfo {
}
trySendRemoteInfo = () => {
log.debug('ServerInfo.trySendRemoteInfo', this.server.name, this.remoteInfo);
log.debug('trySendRemoteInfo', this.server.name, this.remoteInfo);
if (this.isRemoteInfoRetrieved()) {
this.onRetrievedRemoteInfo?.(this.remoteInfo);

View file

@ -6,16 +6,18 @@
import fs from 'fs';
import {ipcMain} from 'electron';
import log from 'electron-log';
import {TrustedOrigin, PermissionType} from 'types/trustedOrigin';
import {UPDATE_PATHS} from 'common/communication';
import {Logger} from 'common/log';
import urlUtils from 'common/utils/url';
import * as Validator from 'common/Validator';
import {trustedOriginsStoreFile} from './constants';
const log = new Logger('TrustedOriginsStore');
export class TrustedOriginsStore {
storeFile: string;
data?: Map<string, TrustedOrigin>;
@ -117,7 +119,7 @@ const trustedOriginsStore = new TrustedOriginsStore(trustedOriginsStoreFile);
export default trustedOriginsStore;
ipcMain.on(UPDATE_PATHS, () => {
log.debug('trustedOriginsStore.UPDATE_PATHS');
log.debug('UPDATE_PATHS');
trustedOriginsStore.storeFile = trustedOriginsStoreFile;
if (trustedOriginsStore.data) {
trustedOriginsStore.load();

View file

@ -3,7 +3,6 @@
import {BrowserView, app, ipcMain} from 'electron';
import {BrowserViewConstructorOptions, Event, Input} from 'electron/main';
import log from 'electron-log';
import {EventEmitter} from 'events';
@ -23,6 +22,7 @@ import {
} from 'common/communication';
import {MattermostServer} from 'common/servers/MattermostServer';
import {TabView, TabTuple} from 'common/tabs/TabView';
import {Logger} from 'common/log';
import {ServerInfo} from 'main/server/serverInfo';
import MainWindow from 'main/windows/mainWindow';
@ -42,6 +42,7 @@ export enum Status {
}
const MENTIONS_GROUP = 2;
const log = new Logger('MattermostView');
export class MattermostView extends EventEmitter {
tab: TabView;
@ -94,7 +95,7 @@ export class MattermostView extends EventEmitter {
}
this.view.webContents.on('did-finish-load', () => {
log.debug('MattermostView.did-finish-load', this.tab.name);
log.debug('did-finish-load', this.tab.name);
// wait for screen to truly finish loading before sending the message down
const timeout = setInterval(() => {
@ -355,7 +356,7 @@ export class MattermostView extends EventEmitter {
};
handleInputEvents = (_: Event, input: Input) => {
log.silly('MattermostView.handleInputEvents', {tabName: this.tab.name, input});
log.silly('handleInputEvents', {tabName: this.tab.name, input});
this.registerAltKeyPressed(input);
@ -365,7 +366,7 @@ export class MattermostView extends EventEmitter {
}
handleDidNavigate = (event: Event, url: string) => {
log.debug('MattermostView.handleDidNavigate', {tabName: this.tab.name, url});
log.debug('handleDidNavigate', {tabName: this.tab.name, url});
if (shouldHaveBackBar(this.tab.url || '', url)) {
this.setBounds(getWindowBoundaries(MainWindow.get()!, true));
@ -379,7 +380,7 @@ export class MattermostView extends EventEmitter {
}
handleUpdateTarget = (e: Event, url: string) => {
log.silly('MattermostView.handleUpdateTarget', {tabName: this.tab.name, url});
log.silly('handleUpdateTarget', {tabName: this.tab.name, url});
if (url && !urlUtils.isInternalURL(urlUtils.parseURL(url), this.tab.server.url)) {
this.emit(UPDATE_TARGET_URL, url);
} else {
@ -390,7 +391,7 @@ export class MattermostView extends EventEmitter {
titleParser = /(\((\d+)\) )?(\* )?/g
handleTitleUpdate = (e: Event, title: string) => {
log.debug('MattermostView.handleTitleUpdate', {tabName: this.tab.name, title});
log.debug('handleTitleUpdate', {tabName: this.tab.name, title});
this.updateMentionsFromTitle(title);
}
@ -404,7 +405,7 @@ export class MattermostView extends EventEmitter {
}
handleFaviconUpdate = (e: Event, favicons: string[]) => {
log.silly('MattermostView.handleFaviconUpdate', {tabName: this.tab.name, favicons});
log.silly('handleFaviconUpdate', {tabName: this.tab.name, favicons});
// if unread state is stored for that favicon, retrieve value.
// if not, get related info from preload and store it for future changes
@ -425,7 +426,7 @@ export class MattermostView extends EventEmitter {
// if favicon is null, it means it is the initial load,
// so don't memoize as we don't have the favicons and there is no rush to find out.
handleFaviconIsUnread = (e: Event, favicon: string, viewName: string, result: boolean) => {
log.silly('MattermostView.handleFaviconIsUnread', {favicon, viewName, result});
log.silly('handleFaviconIsUnread', {favicon, viewName, result});
if (this.tab && viewName === this.tab.name) {
appState.updateUnreads(viewName, result);

View file

@ -2,8 +2,6 @@
// See LICENSE.txt for license information.
import {BrowserView, ipcMain, IpcMainEvent} from 'electron';
import log from 'electron-log';
import {CombinedConfig} from 'types/config';
import {CoordinatesToJsonType, DownloadedItem, DownloadsMenuOpenEventPayload} from 'types/downloads';
@ -20,6 +18,7 @@ import {
UPDATE_DOWNLOADS_DROPDOWN_MENU,
UPDATE_DOWNLOADS_DROPDOWN_MENU_ITEM,
} from 'common/communication';
import {Logger} from 'common/log';
import {
DOWNLOADS_DROPDOWN_FULL_WIDTH,
DOWNLOADS_DROPDOWN_MENU_FULL_HEIGHT,
@ -32,6 +31,8 @@ import WindowManager from '../windows/windowManager';
import downloadsManager from 'main/downloadsManager';
import MainWindow from 'main/windows/mainWindow';
const log = new Logger('DownloadsDropdownMenuView');
export default class DownloadsDropdownMenuView {
open: boolean;
view: BrowserView;
@ -81,7 +82,7 @@ export default class DownloadsDropdownMenuView {
}
updateItem = (event: IpcMainEvent, item: DownloadedItem) => {
log.debug('DownloadsDropdownMenuView.updateItem', {item});
log.debug('updateItem', {item});
this.item = item;
@ -89,7 +90,7 @@ export default class DownloadsDropdownMenuView {
}
updateConfig = (event: IpcMainEvent, config: CombinedConfig) => {
log.debug('DownloadsDropdownMenuView.updateConfig');
log.debug('updateConfig');
this.darkMode = config.darkMode;
this.updateDownloadsDropdownMenu();
@ -100,7 +101,7 @@ export default class DownloadsDropdownMenuView {
* the downloads dropdown at the correct position
*/
updateWindowBounds = () => {
log.debug('DownloadsDropdownMenuView.updateWindowBounds');
log.debug('updateWindowBounds');
const mainWindow = MainWindow.get();
if (mainWindow) {
@ -111,7 +112,7 @@ export default class DownloadsDropdownMenuView {
}
updateDownloadsDropdownMenu = () => {
log.debug('DownloadsDropdownMenuView.updateDownloadsDropdownMenu');
log.debug('updateDownloadsDropdownMenu');
this.view.webContents.send(
UPDATE_DOWNLOADS_DROPDOWN_MENU,
@ -123,7 +124,7 @@ export default class DownloadsDropdownMenuView {
}
handleOpen = (event: IpcMainEvent, payload: DownloadsMenuOpenEventPayload = {} as DownloadsMenuOpenEventPayload) => {
log.debug('DownloadsDropdownMenuView.handleOpen', {bounds: this.bounds, payload});
log.debug('handleOpen', {bounds: this.bounds, payload});
if (!this.bounds) {
return;
@ -131,7 +132,7 @@ export default class DownloadsDropdownMenuView {
const {item, coordinates} = payload;
log.debug('DownloadsDropdownMenuView.handleOpen', {item, coordinates});
log.debug('handleOpen', {item, coordinates});
this.open = true;
this.coordinates = coordinates;
@ -144,7 +145,7 @@ export default class DownloadsDropdownMenuView {
}
handleClose = () => {
log.debug('DownloadsDropdownMenuView.handleClose');
log.debug('handleClose');
this.open = false;
this.item = undefined;

View file

@ -3,8 +3,6 @@
import {BrowserView, ipcMain, IpcMainEvent, IpcMainInvokeEvent} from 'electron';
import log from 'electron-log';
import {CombinedConfig} from 'types/config';
import {DownloadedItem, DownloadedItems} from 'types/downloads';
@ -20,6 +18,7 @@ import {
GET_DOWNLOADED_IMAGE_THUMBNAIL_LOCATION,
DOWNLOADS_DROPDOWN_OPEN_FILE,
} from 'common/communication';
import {Logger} from 'common/log';
import {TAB_BAR_HEIGHT, DOWNLOADS_DROPDOWN_WIDTH, DOWNLOADS_DROPDOWN_HEIGHT, DOWNLOADS_DROPDOWN_FULL_WIDTH} from 'common/utils/constants';
import {getLocalPreload, getLocalURLString} from 'main/utils';
@ -27,6 +26,8 @@ import WindowManager from '../windows/windowManager';
import downloadsManager from 'main/downloadsManager';
import MainWindow from 'main/windows/mainWindow';
const log = new Logger('DownloadsDropdownView');
export default class DownloadsDropdownView {
bounds?: Electron.Rectangle;
darkMode: boolean;
@ -75,7 +76,7 @@ export default class DownloadsDropdownView {
}
updateDownloads = (event: IpcMainEvent, downloads: DownloadedItems) => {
log.debug('DownloadsDropdownView.updateDownloads', {downloads});
log.debug('updateDownloads', {downloads});
this.downloads = downloads;
@ -83,13 +84,13 @@ export default class DownloadsDropdownView {
}
updateDownloadsDropdownMenuItem = (event: IpcMainEvent, item?: DownloadedItem) => {
log.debug('DownloadsDropdownView.updateDownloadsDropdownMenuItem', {item});
log.debug('updateDownloadsDropdownMenuItem', {item});
this.item = item;
this.updateDownloadsDropdown();
}
updateConfig = (event: IpcMainEvent, config: CombinedConfig) => {
log.debug('DownloadsDropdownView.updateConfig');
log.debug('updateConfig');
this.darkMode = config.darkMode;
this.updateDownloadsDropdown();
@ -100,7 +101,7 @@ export default class DownloadsDropdownView {
* the downloads dropdown at the correct position
*/
updateWindowBounds = () => {
log.debug('DownloadsDropdownView.updateWindowBounds');
log.debug('updateWindowBounds');
const mainWindow = MainWindow.get();
if (mainWindow) {
@ -111,7 +112,7 @@ export default class DownloadsDropdownView {
}
updateDownloadsDropdown = () => {
log.debug('DownloadsDropdownView.updateDownloadsDropdown');
log.debug('updateDownloadsDropdown');
this.view.webContents.send(
UPDATE_DOWNLOADS_DROPDOWN,
@ -123,7 +124,7 @@ export default class DownloadsDropdownView {
}
handleOpen = () => {
log.debug('DownloadsDropdownView.handleOpen', {bounds: this.bounds});
log.debug('handleOpen', {bounds: this.bounds});
if (!this.bounds) {
return;
@ -137,7 +138,7 @@ export default class DownloadsDropdownView {
}
handleClose = () => {
log.debug('DownloadsDropdownView.handleClose');
log.debug('handleClose');
this.view.setBounds(this.getBounds(0, 0));
downloadsManager.onClose();
@ -150,7 +151,7 @@ export default class DownloadsDropdownView {
}
openFile = (e: IpcMainEvent, item: DownloadedItem) => {
log.debug('DownloadsDropdownView.openFile', {item});
log.debug('openFile', {item});
downloadsManager.openFile(item);
}
@ -192,7 +193,7 @@ export default class DownloadsDropdownView {
}
handleReceivedDownloadsDropdownSize = (event: IpcMainEvent, width: number, height: number) => {
log.silly('DownloadsDropdownView.handleReceivedDownloadsDropdownSize', {width, height});
log.silly('handleReceivedDownloadsDropdownSize', {width, height});
this.bounds = this.getBounds(width, height);
if (downloadsManager.getIsOpen()) {

View file

@ -2,9 +2,9 @@
// See LICENSE.txt for license information.
import {BrowserView, app, ipcMain} from 'electron';
import log from 'electron-log';
import {DARK_MODE_CHANGE, LOADING_SCREEN_ANIMATION_FINISHED, TOGGLE_LOADING_SCREEN_VISIBILITY} from 'common/communication';
import {Logger} from 'common/log';
import {getLocalPreload, getLocalURLString, getWindowBoundaries} from 'main/utils';
import MainWindow from 'main/windows/mainWindow';
@ -15,6 +15,8 @@ enum LoadingScreenState {
HIDDEN = 3,
}
const log = new Logger('LoadingScreen');
export class LoadingScreen {
private view?: BrowserView;
private state: LoadingScreenState;

View file

@ -4,8 +4,6 @@
import {BrowserWindow, ipcMain} from 'electron';
import {IpcMainEvent, IpcMainInvokeEvent} from 'electron/main';
import log from 'electron-log';
import {CombinedConfig} from 'types/config';
import {
@ -20,6 +18,7 @@ import {
RESIZE_MODAL,
} from 'common/communication';
import Config from 'common/config';
import {Logger} from 'common/log';
import {getAdjustedWindowBoundaries} from 'main/utils';
import WebContentsEventManager from 'main/views/webContentEvents';
@ -27,6 +26,8 @@ import WindowManager from 'main/windows/windowManager';
import {ModalView} from './modalView';
const log = new Logger('ModalManager');
export class ModalManager {
modalQueue: Array<ModalView<any, any>>;
modalPromises: Map<string, Promise<any>>;
@ -74,7 +75,7 @@ export class ModalManager {
}
handleInfoRequest = (event: IpcMainInvokeEvent) => {
log.debug('ModalManager.handleInfoRequest');
log.debug('handleInfoRequest');
const requestModal = this.findModalByCaller(event);
if (requestModal) {
@ -98,7 +99,7 @@ export class ModalManager {
}
handleModalFinished = (mode: 'resolve' | 'reject', event: IpcMainEvent, data: unknown) => {
log.debug('ModalManager.handleModalFinished', {mode, data});
log.debug('handleModalFinished', {mode, data});
const requestModal = this.findModalByCaller(event);
if (requestModal) {
@ -131,7 +132,7 @@ export class ModalManager {
}
handleResizeModal = (event: IpcMainEvent, bounds: Electron.Rectangle) => {
log.debug('ModalManager.handleResizeModal', {bounds, modalQueueLength: this.modalQueue.length});
log.debug('handleResizeModal', {bounds, modalQueueLength: this.modalQueue.length});
if (this.modalQueue.length) {
const currentModal = this.modalQueue[0];
@ -147,7 +148,7 @@ export class ModalManager {
handleEmitConfiguration = (event: IpcMainEvent, config: CombinedConfig) => {
if (this.modalQueue.length) {
log.debug('ModalManager.handleEmitConfiguration');
log.debug('handleEmitConfiguration');
}
this.modalQueue.forEach((modal) => {

View file

@ -2,7 +2,8 @@
// See LICENSE.txt for license information.
import {BrowserView, BrowserWindow} from 'electron';
import log from 'electron-log';
import {Logger} from 'common/log';
import ContextMenu from '../contextMenu';
import {getWindowBoundaries} from '../utils';
@ -25,12 +26,14 @@ export class ModalView<T, T2> {
status: Status;
contextMenu: ContextMenu;
uncloseable: boolean;
private log: Logger;
constructor(key: string, html: string, preload: string, data: T, onResolve: (value: T2) => void, onReject: (value: T2) => void, currentWindow: BrowserWindow, uncloseable: boolean) {
this.key = key;
this.html = html;
this.data = data;
log.info(`preloading with ${preload}`);
this.log = new Logger('ModalView', key);
this.log.info(`preloading with ${preload}`);
this.view = new BrowserView({webPreferences: {
preload,
@ -48,8 +51,8 @@ export class ModalView<T, T2> {
try {
this.view.webContents.loadURL(this.html);
} catch (e) {
log.error('there was an error loading the modal:');
log.error(e);
this.log.error('there was an error loading the modal:');
this.log.error(e);
}
this.contextMenu = new ContextMenu({}, this.view);
@ -84,7 +87,7 @@ export class ModalView<T, T2> {
}
if (withDevTools) {
log.info(`showing dev tools for ${this.key}`);
this.log.info(`showing dev tools for ${this.key}`);
this.view.webContents.openDevTools({mode: 'detach'});
}
}

View file

@ -3,8 +3,6 @@
import {BrowserView, ipcMain, IpcMainEvent} from 'electron';
import log from 'electron-log';
import {CombinedConfig, Team, TeamWithTabs, TeamWithTabsAndGpo} from 'types/config';
import {
@ -17,12 +15,15 @@ import {
RECEIVE_DROPDOWN_MENU_SIZE,
SET_ACTIVE_VIEW,
} from 'common/communication';
import * as AppState from '../appState';
import {Logger} from 'common/log';
import {TAB_BAR_HEIGHT, THREE_DOT_MENU_WIDTH, THREE_DOT_MENU_WIDTH_MAC, MENU_SHADOW_WIDTH} from 'common/utils/constants';
import {getLocalPreload, getLocalURLString} from 'main/utils';
import * as AppState from '../appState';
import WindowManager from '../windows/windowManager';
import MainWindow from '../windows/mainWindow';
const log = new Logger('TeamDropdownView');
export default class TeamDropdownView {
view: BrowserView;
bounds?: Electron.Rectangle;
@ -68,9 +69,8 @@ export default class TeamDropdownView {
}
updateConfig = (event: IpcMainEvent, config: CombinedConfig) => {
log.silly('TeamDropdownView.config', {config});
log.silly('config', {config});
this.teams = this.addGpoToTeams(config.teams, config.registryTeams);
this.darkMode = config.darkMode;
this.enableServerManagement = config.enableServerManagement;
this.hasGPOTeams = config.registryTeams && config.registryTeams.length > 0;
@ -78,14 +78,14 @@ export default class TeamDropdownView {
}
updateActiveTeam = (event: IpcMainEvent, name: string) => {
log.silly('TeamDropdownView.updateActiveTeam', {name});
log.silly('updateActiveTeam', {name});
this.activeTeam = name;
this.updateDropdown();
}
updateMentions = (expired: Map<string, boolean>, mentions: Map<string, number>, unreads: Map<string, boolean>) => {
log.silly('TeamDropdownView.updateMentions', {expired, mentions, unreads});
log.silly('updateMentions', {expired, mentions, unreads});
this.unreads = unreads;
this.mentions = mentions;
@ -99,7 +99,7 @@ export default class TeamDropdownView {
}
updateDropdown = () => {
log.silly('TeamDropdownView.updateDropdown');
log.silly('updateDropdown');
this.view.webContents.send(
UPDATE_TEAMS_DROPDOWN,
@ -116,7 +116,7 @@ export default class TeamDropdownView {
}
handleOpen = () => {
log.debug('TeamDropdownView.handleOpen');
log.debug('handleOpen');
if (!this.bounds) {
return;
@ -129,7 +129,7 @@ export default class TeamDropdownView {
}
handleClose = () => {
log.debug('TeamDropdownView.handleClose');
log.debug('handleClose');
this.view.setBounds(this.getBounds(0, 0));
WindowManager.sendToRenderer(CLOSE_TEAMS_DROPDOWN);
@ -137,7 +137,7 @@ export default class TeamDropdownView {
}
handleReceivedMenuSize = (event: IpcMainEvent, width: number, height: number) => {
log.silly('TeamDropdownView.handleReceivedMenuSize', {width, height});
log.silly('handleReceivedMenuSize', {width, height});
this.bounds = this.getBounds(width, height);
if (this.isOpen) {

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
import {BrowserView, dialog, ipcMain, IpcMainEvent} from 'electron';
import log from 'electron-log';
import {BrowserViewConstructorOptions} from 'electron/main';
import {Tuple as tuple} from '@bloomberg/record-tuple-polyfill';
@ -23,6 +22,7 @@ import {
MAIN_WINDOW_SHOWN,
} from 'common/communication';
import Config from 'common/config';
import {Logger} from 'common/log';
import urlUtils, {equalUrlsIgnoringSubpath} from 'common/utils/url';
import Utils from 'common/utils/util';
import {MattermostServer} from 'common/servers/MattermostServer';
@ -42,6 +42,7 @@ import modalManager from './modalManager';
import WebContentsEventManager from './webContentEvents';
import LoadingScreen from './loadingScreen';
const log = new Logger('ViewManager');
const URL_VIEW_DURATION = 10 * SECOND;
const URL_VIEW_HEIGHT = 20;
@ -114,7 +115,7 @@ export class ViewManager {
* close, open, or reload tabs, taking care to reuse tabs and
* preserve focus on the currently selected tab. */
reloadConfiguration = (configServers: TeamWithTabs[]) => {
log.debug('viewManager.reloadConfiguration');
log.debug('reloadConfiguration');
const focusedTuple: TabTuple | undefined = this.views.get(this.currentView as string)?.urlTypeTuple;
@ -188,7 +189,7 @@ export class ViewManager {
}
showInitial = () => {
log.verbose('viewManager.showInitial');
log.verbose('showInitial');
const servers = this.getServers();
if (servers.length) {
@ -211,7 +212,7 @@ export class ViewManager {
}
showByName = (name: string) => {
log.debug('viewManager.showByName', name);
log.debug('showByName', name);
const newView = this.views.get(name);
if (newView) {
@ -258,7 +259,7 @@ export class ViewManager {
}
activateView = (viewName: string) => {
log.debug('viewManager.activateView', viewName);
log.debug('activateView', viewName);
if (this.currentView === viewName) {
this.showByName(this.currentView);
@ -272,7 +273,7 @@ export class ViewManager {
}
finishLoading = (server: string) => {
log.debug('viewManager.finishLoading', server);
log.debug('finishLoading', server);
const view = this.views.get(server);
if (view && this.getCurrentView() === view) {
@ -299,7 +300,7 @@ export class ViewManager {
}
failLoading = (tabName: string) => {
log.debug('viewManager.failLoading', tabName);
log.debug('failLoading', tabName);
LoadingScreen.fade();
if (this.currentView === tabName) {
@ -339,7 +340,7 @@ export class ViewManager {
}
showURLView = (url: URL | string) => {
log.silly('viewManager.showURLView', url);
log.silly('showURLView', url);
if (this.urlViewCancel) {
this.urlViewCancel();
@ -415,7 +416,7 @@ export class ViewManager {
}
deeplinkSuccess = (viewName: string) => {
log.debug('viewManager.deeplinkSuccess', viewName);
log.debug('deeplinkSuccess', viewName);
const view = this.views.get(viewName);
if (!view) {
@ -435,7 +436,7 @@ export class ViewManager {
}
getViewByURL = (inputURL: URL | string, ignoreScheme = false) => {
log.silly('ViewManager.getViewByURL', `${inputURL}`, ignoreScheme);
log.silly('getViewByURL', `${inputURL}`, ignoreScheme);
const parsedURL = urlUtils.parseURL(inputURL);
if (!parsedURL) {

View file

@ -2,9 +2,9 @@
// See LICENSE.txt for license information.
import {BrowserWindow, session, shell, WebContents} from 'electron';
import log from 'electron-log';
import Config from 'common/config';
import {Logger} from 'common/log';
import urlUtils from 'common/utils/url';
import {flushCookiesStore} from 'main/app/utils';
@ -23,6 +23,7 @@ type CustomLogin = {
inProgress: boolean;
}
const log = new Logger('WebContentsEventManager');
const scheme = protocols && protocols[0] && protocols[0].schemes && protocols[0].schemes[0];
export class WebContentsEventManager {
@ -35,6 +36,13 @@ export class WebContentsEventManager {
this.listeners = {};
}
private log = (webContentsId?: number) => {
if (webContentsId) {
return log.withPrefix(String(webContentsId));
}
return log;
}
private isTrustedPopupWindow = (webContentsId: number) => {
if (!this.popupWindow) {
return false;
@ -52,7 +60,7 @@ export class WebContentsEventManager {
generateWillNavigate = (webContentsId: number) => {
return (event: Event, url: string) => {
log.debug('webContentEvents.will-navigate', {webContentsId, url});
this.log(webContentsId).debug('will-navigate', url);
const parsedURL = urlUtils.parseURL(url)!;
const serverURL = this.getServerURLFromWebContentsId(webContentsId);
@ -81,14 +89,14 @@ export class WebContentsEventManager {
return;
}
log.info(`Prevented desktop from navigating to: ${url}`);
this.log(webContentsId).info(`Prevented desktop from navigating to: ${url}`);
event.preventDefault();
};
};
generateDidStartNavigation = (webContentsId: number) => {
return (event: Event, url: string) => {
log.debug('webContentEvents.did-start-navigation', {webContentsId, url});
this.log(webContentsId).debug('did-start-navigation', {webContentsId, url});
const parsedURL = urlUtils.parseURL(url)!;
const serverURL = this.getServerURLFromWebContentsId(webContentsId);
@ -106,17 +114,17 @@ export class WebContentsEventManager {
};
denyNewWindow = (details: Electron.HandlerDetails): {action: 'deny' | 'allow'} => {
log.warn(`Prevented popup window to open a new window to ${details.url}.`);
this.log().warn(`Prevented popup window to open a new window to ${details.url}.`);
return {action: 'deny'};
};
generateNewWindowListener = (webContentsId: number, spellcheck?: boolean) => {
return (details: Electron.HandlerDetails): {action: 'deny' | 'allow'} => {
log.debug('webContentEvents.new-window', details.url);
this.log(webContentsId).debug('new-window', details.url);
const parsedURL = urlUtils.parseURL(details.url);
if (!parsedURL) {
log.warn(`Ignoring non-url ${details.url}`);
this.log(webContentsId).warn(`Ignoring non-url ${details.url}`);
return {action: 'deny'};
}
@ -170,11 +178,11 @@ export class WebContentsEventManager {
return {action: 'deny'};
}
if (urlUtils.isAdminUrl(serverURL, parsedURL)) {
log.info(`${details.url} is an admin console page, preventing to open a new window`);
this.log(webContentsId).info(`${details.url} is an admin console page, preventing to open a new window`);
return {action: 'deny'};
}
if (this.popupWindow && this.popupWindow.win.webContents.getURL() === details.url) {
log.info(`Popup window already open at provided url: ${details.url}`);
this.log(webContentsId).info(`Popup window already open at provided url: ${details.url}`);
return {action: 'deny'};
}
@ -314,14 +322,14 @@ export class WebContentsEventManager {
contents.removeListener('did-start-navigation', didStartNavigation);
removeListeners?.(contents);
} catch (e) {
log.error(`Error while trying to detach listeners, this might be ok if the process crashed: ${e}`);
this.log(contents.id).error(`Error while trying to detach listeners, this might be ok if the process crashed: ${e}`);
}
};
this.listeners[contents.id] = removeWebContentsListeners;
contents.once('render-process-gone', (event, details) => {
if (details.reason !== 'clean-exit') {
log.error('Renderer process for a webcontent is no longer available:', details.reason);
this.log(contents.id).error('Renderer process for a webcontent is no longer available:', details.reason);
}
removeWebContentsListeners();
});

View file

@ -3,7 +3,6 @@
import {EventEmitter} from 'events';
import {BrowserWindow, ipcMain, IpcMainEvent, Rectangle} from 'electron';
import log from 'electron-log';
import {
CallsJoinedCallMessage,
@ -16,6 +15,7 @@ import {MattermostView} from 'main/views/MattermostView';
import {getLocalPreload} from 'main/utils';
import {Logger} from 'common/log';
import {CALLS_PLUGIN_ID, MINIMUM_CALLS_WIDGET_HEIGHT, MINIMUM_CALLS_WIDGET_WIDTH} from 'common/utils/constants';
import Utils from 'common/utils/util';
import urlUtils, {getFormattedPathName} from 'common/utils/url';
@ -31,6 +31,8 @@ type LoadURLOpts = {
extraHeaders: string;
}
const log = new Logger('CallsWidgetWindow');
export default class CallsWidgetWindow extends EventEmitter {
public win: BrowserWindow;
private main: BrowserWindow;
@ -86,7 +88,7 @@ export default class CallsWidgetWindow extends EventEmitter {
}
public async close() {
log.debug('CallsWidgetWindow.close');
log.debug('close');
return new Promise<void>((resolve) => {
if (this.win.isDestroyed()) {
resolve();
@ -113,7 +115,7 @@ export default class CallsWidgetWindow extends EventEmitter {
if (url === this.getWidgetURL()) {
return;
}
log.warn(`CallsWidgetWindow: prevented widget window from navigating to: ${url}`);
log.warn(`prevented widget window from navigating to: ${url}`);
ev.preventDefault();
}
@ -125,7 +127,7 @@ export default class CallsWidgetWindow extends EventEmitter {
}
private onClosed = () => {
log.debug('CallsWidgetWindow.onClosed');
log.debug('onClosed');
this.emit('closed');
this.removeAllListeners('closed');
ipcMain.off(CALLS_WIDGET_RESIZE, this.onResize);
@ -150,10 +152,10 @@ export default class CallsWidgetWindow extends EventEmitter {
}
private onResize = (ev: IpcMainEvent, _: string, msg: CallsWidgetResizeMessage) => {
log.debug('CallsWidgetWindow.onResize', msg);
log.debug('onResize', msg);
if (!this.isAllowedEvent(ev)) {
log.warn('CallsWidgetWindow.onResize', 'Disallowed calls event');
log.warn('onResize', 'Disallowed calls event');
return;
}
@ -170,7 +172,7 @@ export default class CallsWidgetWindow extends EventEmitter {
}
private onShareScreen = (ev: IpcMainEvent, _: string, message: CallsWidgetShareScreenMessage) => {
log.debug('CallsWidgetWindow.onShareScreen');
log.debug('onShareScreen');
if (!this.isAllowedEvent(ev)) {
log.warn('Disallowed calls event');
@ -181,10 +183,10 @@ export default class CallsWidgetWindow extends EventEmitter {
}
private onJoinedCall = (ev: IpcMainEvent, _: string, message: CallsJoinedCallMessage) => {
log.debug('CallsWidgetWindow.onJoinedCall');
log.debug('onJoinedCall');
if (!this.isAllowedEvent(ev)) {
log.warn('CallsWidgetWindow.onJoinedCall', 'Disallowed calls event');
log.warn('onJoinedCall', 'Disallowed calls event');
return;
}
@ -204,7 +206,7 @@ export default class CallsWidgetWindow extends EventEmitter {
}
private onShow = () => {
log.debug('CallsWidgetWindow.onShow');
log.debug('onShow');
this.win.focus();
this.win.setVisibleOnAllWorkspaces(true, {visibleOnFullScreen: true, skipTransformProcessType: true});
@ -237,7 +239,7 @@ export default class CallsWidgetWindow extends EventEmitter {
};
}
log.warn(`CallsWidgetWindow.onPopOutOpen: prevented window open to ${url}`);
log.warn(`onPopOutOpen: prevented window open to ${url}`);
return {action: 'deny' as const};
}
@ -253,7 +255,7 @@ export default class CallsWidgetWindow extends EventEmitter {
}
private onPopOutClosed = () => {
log.debug('CallsWidgetWindow.onPopOutClosed');
log.debug('onPopOutClosed');
this.popOut?.removeAllListeners('closed');
this.popOut = null;
}

View file

@ -8,12 +8,12 @@ import path from 'path';
import os from 'os';
import {app, BrowserWindow, BrowserWindowConstructorOptions, dialog, Event, globalShortcut, Input, ipcMain, screen} from 'electron';
import log from 'electron-log';
import {SavedWindowState} from 'types/mainWindow';
import {SELECT_NEXT_TAB, SELECT_PREVIOUS_TAB, GET_FULL_SCREEN_STATUS, FOCUS_THREE_DOT_MENU} from 'common/communication';
import Config from 'common/config';
import {Logger} from 'common/log';
import {DEFAULT_WINDOW_HEIGHT, DEFAULT_WINDOW_WIDTH, MINIMUM_WINDOW_HEIGHT, MINIMUM_WINDOW_WIDTH} from 'common/utils/constants';
import Utils from 'common/utils/util';
import * as Validator from 'common/Validator';
@ -24,6 +24,7 @@ import {localizeMessage} from 'main/i18nManager';
import ContextMenu from '../contextMenu';
import {getLocalPreload, getLocalURLString, isInsideRectangle} from '../utils';
const log = new Logger('MainWindow');
const ALT_MENU_KEYS = ['Alt+F', 'Alt+E', 'Alt+V', 'Alt+H', 'Alt+W', 'Alt+P'];
export class MainWindow {
@ -224,7 +225,7 @@ export class MainWindow {
}
private onClose = (event: Event) => {
log.debug('MainWindow.on.close');
log.debug('onClose');
if (!this.win) {
return;

View file

@ -2,16 +2,18 @@
// See LICENSE.txt for license information.
import {BrowserWindow, ipcMain} from 'electron';
import log from 'electron-log';
import {SHOW_SETTINGS_WINDOW} from 'common/communication';
import Config from 'common/config';
import {Logger} from 'common/log';
import ContextMenu from '../contextMenu';
import {getLocalPreload, getLocalURLString} from '../utils';
import MainWindow from './mainWindow';
const log = new Logger('SettingsWindow');
export class SettingsWindow {
private win?: BrowserWindow;

View file

@ -5,7 +5,6 @@
import path from 'path';
import {app, BrowserWindow, systemPreferences, ipcMain, IpcMainEvent, IpcMainInvokeEvent, desktopCapturer} from 'electron';
import log from 'electron-log';
import {
CallsJoinCallMessage,
@ -39,6 +38,7 @@ import {
CALLS_ERROR,
CALLS_LINK_CLICK,
} from 'common/communication';
import {Logger} from 'common/log';
import urlUtils from 'common/utils/url';
import {SECOND} from 'common/utils/constants';
import Config from 'common/config';
@ -61,12 +61,13 @@ import DownloadsDropdownView from '../views/downloadsDropdownView';
import DownloadsDropdownMenuView from '../views/downloadsDropdownMenuView';
import MainWindow from './mainWindow';
import CallsWidgetWindow from './callsWidgetWindow';
import SettingsWindow from './settingsWindow';
// singleton module to manage application's windows
const log = new Logger('WindowManager');
export class WindowManager {
assetsDir: string;
@ -112,7 +113,7 @@ export class WindowManager {
genCallsEventHandler = (handler: CallsEventHandler) => {
return (event: IpcMainEvent, viewName: string, msg?: any) => {
if (this.callsWidgetWindow && !this.callsWidgetWindow.isAllowedEvent(event)) {
log.warn('WindowManager.genCallsEventHandler', 'Disallowed calls event');
log.warn('genCallsEventHandler', 'Disallowed calls event');
return;
}
handler(viewName, msg);
@ -120,7 +121,7 @@ export class WindowManager {
}
createCallsWidgetWindow = async (viewName: string, msg: CallsJoinCallMessage) => {
log.debug('WindowManager.createCallsWidgetWindow');
log.debug('createCallsWidgetWindow');
if (this.callsWidgetWindow) {
// trying to join again the call we are already in should not be allowed.
if (this.callsWidgetWindow.getCallID() === msg.callID) {
@ -148,7 +149,7 @@ export class WindowManager {
}
handleDesktopSourcesModalRequest = () => {
log.debug('WindowManager.handleDesktopSourcesModalRequest');
log.debug('handleDesktopSourcesModalRequest');
if (this.callsWidgetWindow) {
this.switchServer(this.callsWidgetWindow.getServerName());
@ -158,7 +159,7 @@ export class WindowManager {
}
handleCallsWidgetChannelLinkClick = () => {
log.debug('WindowManager.handleCallsWidgetChannelLinkClick');
log.debug('handleCallsWidgetChannelLinkClick');
if (this.callsWidgetWindow) {
this.switchServer(this.callsWidgetWindow.getServerName());
@ -168,7 +169,7 @@ export class WindowManager {
}
handleCallsError = (_: string, msg: CallsErrorMessage) => {
log.debug('WindowManager.handleCallsError', msg);
log.debug('handleCallsError', msg);
if (this.callsWidgetWindow) {
this.switchServer(this.callsWidgetWindow.getServerName());
@ -178,7 +179,7 @@ export class WindowManager {
}
handleCallsLinkClick = (_: string, msg: CallsLinkClickMessage) => {
log.debug('WindowManager.handleCallsLinkClick with linkURL', msg.link);
log.debug('handleCallsLinkClick with linkURL', msg.link);
if (this.callsWidgetWindow) {
this.switchServer(this.callsWidgetWindow.getServerName());
@ -188,13 +189,13 @@ export class WindowManager {
}
handleCallsLeave = () => {
log.debug('WindowManager.handleCallsLeave');
log.debug('handleCallsLeave');
this.callsWidgetWindow?.close();
}
showMainWindow = (deeplinkingURL?: string | URL) => {
log.debug('WindowManager.showMainWindow', deeplinkingURL);
log.debug('showMainWindow', deeplinkingURL);
const mainWindow = MainWindow.get();
if (mainWindow) {
@ -252,7 +253,7 @@ export class WindowManager {
isResizing = false;
handleWillResizeMainWindow = (event: Event, newBounds: Electron.Rectangle) => {
log.silly('WindowManager.handleWillResizeMainWindow');
log.silly('handleWillResizeMainWindow');
if (!(this.viewManager && MainWindow.get())) {
return;
@ -282,7 +283,7 @@ export class WindowManager {
}
handleResizedMainWindow = () => {
log.silly('WindowManager.handleResizedMainWindow');
log.silly('handleResizedMainWindow');
if (MainWindow.get()) {
const bounds = this.getBounds();
@ -300,14 +301,14 @@ export class WindowManager {
}
private throttledWillResize = (newBounds: Electron.Rectangle) => {
log.silly('WindowManager.throttledWillResize', {newBounds});
log.silly('throttledWillResize', {newBounds});
this.isResizing = true;
this.setCurrentViewBounds(newBounds);
}
handleResizeMainWindow = () => {
log.silly('WindowManager.handleResizeMainWindow');
log.silly('handleResizeMainWindow');
if (!(this.viewManager && MainWindow.get())) {
return;
@ -330,7 +331,7 @@ export class WindowManager {
};
setCurrentViewBounds = (bounds: {width: number; height: number}) => {
log.debug('WindowManager.setCurrentViewBounds', {bounds});
log.debug('setCurrentViewBounds', {bounds});
const currentView = this.viewManager?.getCurrentView();
if (currentView) {
@ -471,7 +472,7 @@ export class WindowManager {
}
switchServer = (serverName: string, waitForViewToExist = false) => {
log.debug('windowManager.switchServer');
log.debug('switchServer');
this.showMainWindow();
const server = Config.teams.find((team) => team.name === serverName);
if (!server) {
@ -499,14 +500,14 @@ export class WindowManager {
}
switchTab = (serverName: string, tabName: string) => {
log.debug('windowManager.switchTab');
log.debug('switchTab');
this.showMainWindow();
const tabViewName = getTabViewName(serverName, tabName);
this.viewManager?.showByName(tabViewName);
}
focusBrowserView = () => {
log.debug('WindowManager.focusBrowserView');
log.debug('focusBrowserView');
if (this.viewManager) {
this.viewManager.focus();
@ -533,7 +534,7 @@ export class WindowManager {
}
handleReactAppInitialized = (e: IpcMainEvent, view: string) => {
log.debug('WindowManager.handleReactAppInitialized', view);
log.debug('handleReactAppInitialized', view);
if (this.viewManager) {
this.viewManager.setServerInitialized(view);
@ -592,7 +593,7 @@ export class WindowManager {
}
handleHistory = (event: IpcMainEvent, offset: number) => {
log.debug('WindowManager.handleHistory', offset);
log.debug('handleHistory', offset);
if (this.viewManager) {
const activeView = this.viewManager.getCurrentView();
@ -645,7 +646,7 @@ export class WindowManager {
}
handleBrowserHistoryPush = (e: IpcMainEvent, viewName: string, pathName: string) => {
log.debug('WindowManager.handleBrowserHistoryPush', {viewName, pathName});
log.debug('handleBrowserHistoryPush', {viewName, pathName});
const currentView = this.viewManager?.views.get(viewName);
const cleanedPathName = urlUtils.cleanPathName(currentView?.tab.server.url.pathname || '', pathName);
@ -673,7 +674,7 @@ export class WindowManager {
}
handleBrowserHistoryButton = (e: IpcMainEvent, viewName: string) => {
log.debug('WindowManager.handleBrowserHistoryButton', viewName);
log.debug('handleBrowserHistoryButton', viewName);
const currentView = this.viewManager?.views.get(viewName);
if (currentView) {
@ -692,7 +693,7 @@ export class WindowManager {
}
handleAppLoggedIn = (event: IpcMainEvent, viewName: string) => {
log.debug('WindowManager.handleAppLoggedIn', viewName);
log.debug('handleAppLoggedIn', viewName);
const view = this.viewManager?.views.get(viewName);
if (view && !view.isLoggedIn) {
@ -702,7 +703,7 @@ export class WindowManager {
}
handleAppLoggedOut = (event: IpcMainEvent, viewName: string) => {
log.debug('WindowManager.handleAppLoggedOut', viewName);
log.debug('handleAppLoggedOut', viewName);
const view = this.viewManager?.views.get(viewName);
if (view && view.isLoggedIn) {
@ -719,11 +720,11 @@ export class WindowManager {
}
handleGetDesktopSources = async (viewName: string, opts: Electron.SourcesOptions) => {
log.debug('WindowManager.handleGetDesktopSources', {viewName, opts});
log.debug('handleGetDesktopSources', {viewName, opts});
const view = this.viewManager?.views.get(viewName);
if (!view) {
log.error('WindowManager.handleGetDesktopSources: view not found');
log.error('handleGetDesktopSources: view not found');
return Promise.resolve();
}
@ -784,7 +785,7 @@ export class WindowManager {
}
handleReloadCurrentView = () => {
log.debug('WindowManager.handleReloadCurrentView');
log.debug('handleReloadCurrentView');
const view = this.viewManager?.getCurrentView();
if (!view) {