Newer
Older
/* global __dirname, process */
const contextMenu = require('electron-context-menu');
const debug = require('electron-debug');
const isDev = require('electron-is-dev');
const { autoUpdater } = require('electron-updater');
const windowStateKeeper = require('electron-window-state');
setupAlwaysOnTopMain,
setupPowerMonitorMain,
setupScreenSharingMain
} = require('jitsi-meet-electron-utils');
const path = require('path');
const config = require('./app/features/config');
const { openExternalLink } = require('./app/features/utils/openExternalLink');
const pkgJson = require('./package.json');
const { existsSync } = require('fs');
const showDevTools = Boolean(process.env.SHOW_DEV_TOOLS) || (process.argv.indexOf('--show-dev-tools') > -1);
// We need this because of https://github.com/electron/electron/issues/18214
app.commandLine.appendSwitch('disable-site-isolation-trials');
// This allows BrowserWindow.setContentProtection(true) to work on macOS.
// https://github.com/electron/electron/issues/19880
app.commandLine.appendSwitch('disable-features', 'IOSurfaceCapturer');
// Needed until robot.js is fixed: https://github.com/octalmage/robotjs/issues/580
app.allowRendererProcessReuse = false;
autoUpdater.logger = require('electron-log');
autoUpdater.logger.transports.file.level = 'info';
// Enable context menu so things like copy and paste work in input fields.
contextMenu({
showLookUpSelection: false,
showSearchWithGoogle: false,
showCopyImage: false,
showCopyImageAddress: false,
showSaveImage: false,
showSaveImageAs: false,
showInspectElement: true,
showServices: false
});
// Enable DevTools also on release builds to help troubleshoot issues. Don't
// show them automatically though.
debug({
isEnabled: true,
* When in development mode:
* - Enable automatic reloads
if (isDev) {
require('electron-reload')(path.join(__dirname, 'build'));
}
/**
* The window object that will load the iframe with Jitsi Meet.
* IMPORTANT: Must be defined as global in order to not be garbage collected
* acidentally.
*/
let webrtcInternalsWindow = null;
/**
* Add protocol data
*/
const appProtocolSurplus = `${config.default.appProtocolPrefix}://`;
let rendererReady = false;
let protocolDataForFrontApp = null;
* Sets the application menu. It is hidden on all platforms except macOS because
* otherwise copy and paste functionality is not available.
function setApplicationMenu() {
if (process.platform === 'darwin') {
const template = [ {
submenu: [
{
role: 'services',
submenu: []
},
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideothers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
}, {
label: 'Edit',
submenu: [ {
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
selector: 'undo:'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
selector: 'redo:'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
selector: 'cut:'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
selector: 'copy:'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
selector: 'paste:'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
selector: 'selectAll:'
} ]
}, {
label: '&Window',
role: 'window',
submenu: [
{ role: 'minimize' },
{ role: 'close' }
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
} else {
Menu.setApplicationMenu(null);
/**
* Opens new window with index.html(Jitsi Meet is loaded in iframe there).
*/
function createJitsiMeetWindow() {
if (!process.mas) {
autoUpdater.checkForUpdatesAndNotify();
}
// Load the previous window state with fallback to defaults.
const windowState = windowStateKeeper({
defaultWidth: 800,
defaultHeight: 600
});
let basePath = isDev ? __dirname : app.getAppPath();
// runtime detection on mac if this is a universal build with app-arm64.asar'
// as prepared in https://github.com/electron/universal/blob/master/src/index.ts
// if universal build, load the arch-specific real asar as the app does not load otherwise
if (process.platform === 'darwin' && existsSync(path.join(app.getAppPath(), '..', 'app-arm64.asar'))) {
if (process.arch === 'arm64') {
basePath = app.getAppPath().replace('app.asar', 'app-arm64.asar');
} else if (process.arch === 'x64') {
basePath = app.getAppPath().replace('app.asar', 'app-x64.asar');
}
}
// URL for index.html which will be our entry point.
const indexURL = URL.format({
pathname: path.resolve(basePath, './build/index.html'),
protocol: 'file:',
slashes: true
});
// Options used when creating the main Jitsi Meet window.
// Use a preload script in order to provide node specific functionality
// to a isolated BrowserWindow in accordance with electron security
// guideline.
const options = {
x: windowState.x,
y: windowState.y,
width: windowState.width,
height: windowState.height,
icon: path.resolve(basePath, './resources/icon.png'),
enableBlinkFeatures: 'RTCInsertableStreams,WebAssemblySimd',
nodeIntegration: false,
preload: path.resolve(basePath, './build/preload.js')
mainWindow = new BrowserWindow(options);
windowState.manage(mainWindow);
mainWindow.loadURL(indexURL);
initPopupsConfigurationMain(mainWindow);
setupAlwaysOnTopMain(mainWindow);
setupPowerMonitorMain(mainWindow);
setupScreenSharingMain(mainWindow, config.default.appName, pkgJson.build.appId);
mainWindow.webContents.on('new-window', (event, url, frameName) => {
const target = getPopupTarget(url, frameName);
if (!target || target === 'browser') {
mainWindow.on('closed', () => {
mainWindow = null;
mainWindow.once('ready-to-show', () => {
mainWindow.show();
* When someone tries to enter something like jitsi-meet://test
* while app is closed
* it will trigger this event below
*/
handleProtocolCall(process.argv.pop());
/**
* Opens new window with WebRTC internals.
*/
function createWebRTCInternalsWindow() {
const options = {
minWidth: 800,
minHeight: 600,
show: true
};
webrtcInternalsWindow = new BrowserWindow(options);
webrtcInternalsWindow.loadURL('chrome://webrtc-internals');
}
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/**
* Handler for application protocol links to initiate a conference.
*/
function handleProtocolCall(fullProtocolCall) {
// don't touch when something is bad
if (
!fullProtocolCall
|| fullProtocolCall.trim() === ''
|| fullProtocolCall.indexOf(appProtocolSurplus) !== 0
) {
return;
}
const inputURL = fullProtocolCall.replace(appProtocolSurplus, '');
if (app.isReady() && mainWindow === null) {
createJitsiMeetWindow();
}
protocolDataForFrontApp = inputURL;
if (rendererReady) {
mainWindow
.webContents
.send('protocol-data-msg', inputURL);
}
* Handle this on darwin via LSMultipleInstancesProhibited in Info.plist as below does not work on MAS
const gotInstanceLock = process.platform === 'darwin' ? true : app.requestSingleInstanceLock();
if (!gotInstanceLock) {
app.quit();
process.exit(0);
}
/**
* Run the application.
*/
app.on('activate', () => {
if (mainWindow === null) {
createJitsiMeetWindow();
}
});
app.on('certificate-error',
// eslint-disable-next-line max-params
(event, webContents, url, error, certificate, callback) => {
event.preventDefault();
callback(true);
} else {
callback(false);
}
}
);
if (isDev) {
app.on('ready', createWebRTCInternalsWindow);
}
app.on('second-instance', (event, commandLine) => {
/**
* If someone creates second instance of the application, set focus on
* existing window.
*/
if (mainWindow) {
mainWindow.isMinimized() && mainWindow.restore();
mainWindow.focus();
/**
* This is for windows [win32]
* so when someone tries to enter something like jitsi-meet://test
* while app is opened it will trigger protocol handler.
*/
handleProtocolCall(commandLine.pop());
app.quit();
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
// remove so we can register each time as we run the app.
app.removeAsDefaultProtocolClient(config.default.appProtocolPrefix);
// If we are running a non-packaged version of the app && on windows
if (isDev && process.platform === 'win32') {
// Set the path of electron.exe and your app.
// These two additional parameters are only available on windows.
app.setAsDefaultProtocolClient(
config.default.appProtocolPrefix,
process.execPath,
[ path.resolve(process.argv[1]) ]
);
} else {
app.setAsDefaultProtocolClient(config.default.appProtocolPrefix);
}
/**
* This is for mac [darwin]
* so when someone tries to enter something like jitsi-meet://test
* it will trigger this event below
*/
app.on('open-url', (event, data) => {
event.preventDefault();
handleProtocolCall(data);
});
/**
* This is to notify main.js [this] that front app is ready to receive messages.
*/
ipcMain.on('renderer-ready', () => {
rendererReady = true;
if (protocolDataForFrontApp) {
mainWindow
.webContents
.send('protocol-data-msg', protocolDataForFrontApp);
}
});