/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; import { mapEvent, fromNodeEventEmitter, filterEvent } from 'vs/base/common/event'; import { IURLService } from 'vs/platform/url/common/url'; import product from 'vs/platform/node/product'; import { app } from 'electron'; import URI from 'vs/base/common/uri'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; import { ReadyState } from 'vs/platform/windows/common/windows'; function uriFromRawUrl(url: string): URI | null { try { return URI.parse(url); } catch (e) { return null; } } export class ElectronURLListener { private buffer: URI[] = []; private disposables: IDisposable[] = []; constructor( initial: string | string[], @IURLService private urlService: IURLService, @IWindowsMainService private windowsService: IWindowsMainService ) { const globalBuffer = ((global).getOpenUrls() || []) as string[]; const rawBuffer = [ ...(typeof initial === 'string' ? [initial] : initial), ...globalBuffer ]; this.buffer = rawBuffer.map(uriFromRawUrl).filter(uri => !!uri); app.setAsDefaultProtocolClient(product.urlProtocol, process.execPath, ['--open-url', '--']); const onOpenElectronUrl = mapEvent( fromNodeEventEmitter(app, 'open-url', (event: Electron.Event, url: string) => ({ event, url })), ({ event, url }) => { // always prevent default and return the url as string event.preventDefault(); return url; }); const onOpenUrl = filterEvent(mapEvent(onOpenElectronUrl, uriFromRawUrl), uri => !!uri); onOpenUrl(this.open, this, this.disposables); this.windowsService.onWindowReady(this.flushBuffer, this, this.disposables); this.flushBuffer(); } private open(uri: URI): void { const shouldBuffer = this.windowsService.getWindows() .filter(w => w.readyState === ReadyState.READY) .length === 0; if (shouldBuffer) { this.buffer.push(uri); } else { this.urlService.open(uri).then(handled => { if (!handled) { this.buffer.push(uri); } }); } } private flushBuffer(): void { const buffer = this.buffer; this.buffer = []; for (const uri of buffer) { this.open(uri); } } dispose(): void { this.disposables = dispose(this.disposables); } }