From 83d72787f41d83cb712c1f43e1b5fec6b4527d56 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 31 Jan 2023 18:56:07 +0800 Subject: [PATCH] Use a hidden iframe to open console on Firefox --- ...console-device-action-browser.component.ts | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/app/components/project-map/context-menu/actions/console-device-action-browser/console-device-action-browser.component.ts b/src/app/components/project-map/context-menu/actions/console-device-action-browser/console-device-action-browser.component.ts index 11e706b5..23875107 100644 --- a/src/app/components/project-map/context-menu/actions/console-device-action-browser/console-device-action-browser.component.ts +++ b/src/app/components/project-map/context-menu/actions/console-device-action-browser/console-device-action-browser.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core'; +import { DeviceDetectorService } from 'ngx-device-detector'; import { Node } from '../../../../../cartography/models/node'; import { Server } from '../../../../../models/server'; import { NodeService } from '../../../../../services/node.service'; @@ -12,7 +13,7 @@ export class ConsoleDeviceActionBrowserComponent { @Input() server: Server; @Input() node: Node; - constructor(private toasterService: ToasterService, private nodeService: NodeService) {} + constructor(private toasterService: ToasterService, private nodeService: NodeService, private deviceService: DeviceDetectorService) {} openConsole() { this.nodeService.getNode(this.server, this.node).subscribe((node: Node) => { @@ -21,6 +22,31 @@ export class ConsoleDeviceActionBrowserComponent { }); } + createHiddenIframe(target: Element, uri: string) { + const iframe = document.createElement("iframe"); + iframe.src = uri; + iframe.id = "hiddenIframe"; + iframe.style.display = "none"; + target.appendChild(iframe); + return iframe; + } + + openUriUsingFirefox(uri: string) { + var iframe = (document.querySelector("#hiddenIframe") as HTMLIFrameElement); + + if (!iframe) { + iframe = this.createHiddenIframe(document.body, "about:blank"); + } + + try { + iframe.contentWindow.location.href = uri; + } catch (e) { + if (e.name === "NS_ERROR_UNKNOWN_PROTOCOL") { + this.toasterService.error('Protocol handler does not exist'); + } + } + } + startConsole() { if (this.node.status !== 'started') { this.toasterService.error('This node must be started before a console can be opened'); @@ -33,22 +59,28 @@ export class ConsoleDeviceActionBrowserComponent { this.node.console_host = this.server.host; } + const device = this.deviceService.getDeviceInfo(); + try { + var uri; if (this.node.console_type === 'telnet') { - location.assign( - `gns3+telnet://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}` - ); + uri = `gns3+telnet://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`; } else if (this.node.console_type === 'vnc') { - location.assign( - `gns3+vnc://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}` - ); + uri = `gns3+vnc://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`; } else if (this.node.console_type.startsWith('spice')) { - location.assign( - `gns3+spice://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}` - ); + uri = `gns3+spice://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}` } else { this.toasterService.error('Supported console types are: telnet, vnc, spice and spice+agent.'); } + + if (device.browser === "Firefox") { + // Use a hidden iframe otherwise Firefox will disconnect + // from the GNS3 controller websocket if we use location.assign() + this.openUriUsingFirefox(uri); + } else { + location.assign(uri); + } + } catch (e) { this.toasterService.error(e); }