diff --git a/src/main/views/pluginsPopUps.test.js b/src/main/views/pluginsPopUps.test.js index 67472b58..ecdce600 100644 --- a/src/main/views/pluginsPopUps.test.js +++ b/src/main/views/pluginsPopUps.test.js @@ -9,6 +9,8 @@ import ViewManager from 'main/views/viewManager'; import PluginsPopUpsManager from './pluginsPopUps'; +import allowProtocolDialog from '../allowProtocolDialog'; + jest.mock('electron', () => ({ shell: { openExternal: jest.fn(), @@ -41,6 +43,10 @@ jest.mock('../contextMenu', () => { }); }); +jest.mock('../allowProtocolDialog', () => ({ + handleDialogEvent: jest.fn(), +})); + describe('PluginsPopUpsManager', () => { afterEach(() => { jest.resetAllMocks(); @@ -121,6 +127,11 @@ describe('PluginsPopUpsManager', () => { expect(ServerViewState.switchServer).toHaveBeenCalledWith(4545); expect(ViewManager.handleDeepLink).toHaveBeenCalledWith(parseURL('http://localhost:8065/team/channel')); + // Verify opening custom protocols is handled through allowProtocolDialog + expect(handlers['window-open']({url: 'custom:somelink'})).toEqual({action: 'deny'}); + expect(allowProtocolDialog.handleDialogEvent).toBeCalledWith('custom:', 'custom:somelink'); + expect(shell.openExternal).not.toHaveBeenCalledWith('custom:somelink'); + // Verify opening external links is allowed through browser expect(handlers['window-open']({url: 'https://www.example.com'})).toEqual({action: 'deny'}); expect(shell.openExternal).toHaveBeenCalledWith('https://www.example.com'); diff --git a/src/main/views/pluginsPopUps.ts b/src/main/views/pluginsPopUps.ts index 97ec1bbd..d9d53620 100644 --- a/src/main/views/pluginsPopUps.ts +++ b/src/main/views/pluginsPopUps.ts @@ -17,9 +17,11 @@ import { } from 'common/utils/url'; import ContextMenu from 'main/contextMenu'; import ViewManager from 'main/views/viewManager'; -import {generateHandleConsoleMessage} from 'main/views/webContentEventsCommon'; +import {generateHandleConsoleMessage, isCustomProtocol} from 'main/views/webContentEventsCommon'; import MainWindow from 'main/windows/mainWindow'; +import allowProtocolDialog from '../allowProtocolDialog'; + const log = new Logger('PluginsPopUpsManager'); type PluginPopUp = { @@ -76,8 +78,14 @@ export class PluginsPopUpsManager { const serverView = ViewManager.getViewByWebContentsId(parentId)?.view; + // Check for custom protocol + if (isCustomProtocol(parsedURL)) { + allowProtocolDialog.handleDialogEvent(parsedURL.protocol, url); + return {action: 'deny'}; + } + // We allow internal (i.e., same server) links to be routed as expected. - if (serverView && parsedURL && isTeamUrl(serverView.server.url, parsedURL, true)) { + if (serverView && isTeamUrl(serverView.server.url, parsedURL, true)) { ServerViewState.switchServer(serverView.server.id); MainWindow.get()?.focus(); ViewManager.handleDeepLink(parsedURL); diff --git a/src/main/views/webContentEvents.ts b/src/main/views/webContentEvents.ts index 8aa52b7f..30144010 100644 --- a/src/main/views/webContentEvents.ts +++ b/src/main/views/webContentEvents.ts @@ -31,9 +31,8 @@ import ViewManager from 'main/views/viewManager'; import CallsWidgetWindow from 'main/windows/callsWidgetWindow'; import MainWindow from 'main/windows/mainWindow'; -import {generateHandleConsoleMessage} from './webContentEventsCommon'; +import {generateHandleConsoleMessage, isCustomProtocol} from './webContentEventsCommon'; -import {protocols} from '../../../electron-builder.json'; import allowProtocolDialog from '../allowProtocolDialog'; import {composeUserAgent} from '../utils'; @@ -42,7 +41,6 @@ type CustomLogin = { } const log = new Logger('WebContentsEventManager'); -const scheme = protocols && protocols[0] && protocols[0].schemes && protocols[0].schemes[0]; export class WebContentsEventManager { customLogins: Record; @@ -169,7 +167,7 @@ export class WebContentsEventManager { } // Check for custom protocol - if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:' && parsedURL.protocol !== `${scheme}:`) { + if (isCustomProtocol(parsedURL)) { allowProtocolDialog.handleDialogEvent(parsedURL.protocol, details.url); return {action: 'deny'}; } diff --git a/src/main/views/webContentEventsCommon.ts b/src/main/views/webContentEventsCommon.ts index 13f2e404..894b77bc 100644 --- a/src/main/views/webContentEventsCommon.ts +++ b/src/main/views/webContentEventsCommon.ts @@ -7,6 +7,8 @@ import type {Event} from 'electron'; import type {Logger} from 'common/log'; import {getLevel} from 'common/log'; +import {protocols} from '../../../electron-builder.json'; + enum ConsoleMessageLevel { Verbose, Info, @@ -34,3 +36,8 @@ export const generateHandleConsoleMessage = (log: Logger) => (_: Event, level: n logFn(...entries); }; + +export function isCustomProtocol(url: URL) { + const scheme = protocols && protocols[0] && protocols[0].schemes && protocols[0].schemes[0]; + return url.protocol !== 'http:' && url.protocol !== 'https:' && url.protocol !== `${scheme}:`; +}