[MM-61040] Handle custom protocols in plugins popouts (#3166)

* Handle custom protocols in plugins popouts

* Improve
This commit is contained in:
Claudio Costa
2024-10-14 08:16:40 -06:00
committed by GitHub
parent 4ac0d68ed8
commit 071e9d32cc
4 changed files with 30 additions and 6 deletions

View File

@@ -9,6 +9,8 @@ import ViewManager from 'main/views/viewManager';
import PluginsPopUpsManager from './pluginsPopUps'; import PluginsPopUpsManager from './pluginsPopUps';
import allowProtocolDialog from '../allowProtocolDialog';
jest.mock('electron', () => ({ jest.mock('electron', () => ({
shell: { shell: {
openExternal: jest.fn(), openExternal: jest.fn(),
@@ -41,6 +43,10 @@ jest.mock('../contextMenu', () => {
}); });
}); });
jest.mock('../allowProtocolDialog', () => ({
handleDialogEvent: jest.fn(),
}));
describe('PluginsPopUpsManager', () => { describe('PluginsPopUpsManager', () => {
afterEach(() => { afterEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
@@ -121,6 +127,11 @@ describe('PluginsPopUpsManager', () => {
expect(ServerViewState.switchServer).toHaveBeenCalledWith(4545); expect(ServerViewState.switchServer).toHaveBeenCalledWith(4545);
expect(ViewManager.handleDeepLink).toHaveBeenCalledWith(parseURL('http://localhost:8065/team/channel')); 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 // Verify opening external links is allowed through browser
expect(handlers['window-open']({url: 'https://www.example.com'})).toEqual({action: 'deny'}); expect(handlers['window-open']({url: 'https://www.example.com'})).toEqual({action: 'deny'});
expect(shell.openExternal).toHaveBeenCalledWith('https://www.example.com'); expect(shell.openExternal).toHaveBeenCalledWith('https://www.example.com');

View File

@@ -17,9 +17,11 @@ import {
} from 'common/utils/url'; } from 'common/utils/url';
import ContextMenu from 'main/contextMenu'; import ContextMenu from 'main/contextMenu';
import ViewManager from 'main/views/viewManager'; 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 MainWindow from 'main/windows/mainWindow';
import allowProtocolDialog from '../allowProtocolDialog';
const log = new Logger('PluginsPopUpsManager'); const log = new Logger('PluginsPopUpsManager');
type PluginPopUp = { type PluginPopUp = {
@@ -76,8 +78,14 @@ export class PluginsPopUpsManager {
const serverView = ViewManager.getViewByWebContentsId(parentId)?.view; 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. // 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); ServerViewState.switchServer(serverView.server.id);
MainWindow.get()?.focus(); MainWindow.get()?.focus();
ViewManager.handleDeepLink(parsedURL); ViewManager.handleDeepLink(parsedURL);

View File

@@ -31,9 +31,8 @@ import ViewManager from 'main/views/viewManager';
import CallsWidgetWindow from 'main/windows/callsWidgetWindow'; import CallsWidgetWindow from 'main/windows/callsWidgetWindow';
import MainWindow from 'main/windows/mainWindow'; 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 allowProtocolDialog from '../allowProtocolDialog';
import {composeUserAgent} from '../utils'; import {composeUserAgent} from '../utils';
@@ -42,7 +41,6 @@ type CustomLogin = {
} }
const log = new Logger('WebContentsEventManager'); const log = new Logger('WebContentsEventManager');
const scheme = protocols && protocols[0] && protocols[0].schemes && protocols[0].schemes[0];
export class WebContentsEventManager { export class WebContentsEventManager {
customLogins: Record<number, CustomLogin>; customLogins: Record<number, CustomLogin>;
@@ -169,7 +167,7 @@ export class WebContentsEventManager {
} }
// Check for custom protocol // Check for custom protocol
if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:' && parsedURL.protocol !== `${scheme}:`) { if (isCustomProtocol(parsedURL)) {
allowProtocolDialog.handleDialogEvent(parsedURL.protocol, details.url); allowProtocolDialog.handleDialogEvent(parsedURL.protocol, details.url);
return {action: 'deny'}; return {action: 'deny'};
} }

View File

@@ -7,6 +7,8 @@ import type {Event} from 'electron';
import type {Logger} from 'common/log'; import type {Logger} from 'common/log';
import {getLevel} from 'common/log'; import {getLevel} from 'common/log';
import {protocols} from '../../../electron-builder.json';
enum ConsoleMessageLevel { enum ConsoleMessageLevel {
Verbose, Verbose,
Info, Info,
@@ -34,3 +36,8 @@ export const generateHandleConsoleMessage = (log: Logger) => (_: Event, level: n
logFn(...entries); 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}:`;
}