UNPKG

@theia/core

Version:

Theia is a cloud & desktop IDE framework implemented in TypeScript.

151 lines • 7.8 kB
"use strict"; // ***************************************************************************** // Copyright (C) 2020 Ericsson and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ElectronWebContentChannel = exports.ElectronMessagingContribution = void 0; const inversify_1 = require("inversify"); const contribution_provider_1 = require("../../common/contribution-provider"); const messaging_contribution_1 = require("../../node/messaging/messaging-contribution"); const electron_connection_handler_1 = require("../../electron-common/messaging/electron-connection-handler"); const electron_messaging_service_1 = require("./electron-messaging-service"); const channel_1 = require("../../common/message-rpc/channel"); const common_1 = require("../../common"); const uint8_array_message_buffer_1 = require("../../common/message-rpc/uint8-array-message-buffer"); const electron_api_main_1 = require("../electron-api-main"); /** * This component replicates the role filled by `MessagingContribution` but for Electron. * Unlike the WebSocket based implementation, we do not expect to receive * connection events. Instead, we'll create channels based on incoming `open` * events on the `ipcMain` channel. * This component allows communication between renderer process (frontend) and electron main process. */ let ElectronMessagingContribution = class ElectronMessagingContribution { constructor() { this.channelHandlers = new messaging_contribution_1.MessagingContribution.ConnectionHandlers(); /** * Each electron window has a main channel and its own multiplexer to route multiple client messages the same IPC connection. */ this.windowChannelMultiplexer = new Map(); } init() { electron_api_main_1.TheiaRendererAPI.onIpcData((sender, data) => this.handleIpcEvent(sender, data)); } handleIpcEvent(sender, data) { var _a; // Get the multiplexer for a given window id try { const windowChannelData = (_a = this.windowChannelMultiplexer.get(sender.id)) !== null && _a !== void 0 ? _a : this.createWindowChannelData(sender); windowChannelData.channel.onMessageEmitter.fire(() => new uint8_array_message_buffer_1.Uint8ArrayReadBuffer(data)); } catch (error) { console.error('IPC: Failed to handle message', { error, data }); } } // Creates a new multiplexer for a given sender/window createWindowChannelData(sender) { const mainChannel = this.createWindowMainChannel(sender); const multiplexer = new channel_1.ChannelMultiplexer(mainChannel); multiplexer.onDidOpenChannel(openEvent => { const { channel, id } = openEvent; if (this.channelHandlers.route(id, channel)) { console.debug(`Opening channel for service path '${id}'.`); channel.onClose(() => console.debug(`Closing channel on service path '${id}'.`)); } }); sender.once('did-navigate', () => this.disposeMultiplexer(sender.id, multiplexer, 'Window was refreshed')); // When refreshing the browser window. sender.once('destroyed', () => this.disposeMultiplexer(sender.id, multiplexer, 'Window was closed')); // When closing the browser window. const data = { channel: mainChannel, multiplexer }; this.windowChannelMultiplexer.set(sender.id, data); return data; } /** * Creates the main channel to a window. * @param sender The window that the channel should be established to. */ createWindowMainChannel(sender) { return new ElectronWebContentChannel(sender); } disposeMultiplexer(windowId, multiplexer, reason) { multiplexer.onUnderlyingChannelClose({ reason }); this.windowChannelMultiplexer.delete(windowId); } onStart() { for (const contribution of this.messagingContributions.getContributions()) { contribution.configure(this); } for (const connectionHandler of this.connectionHandlers.getContributions()) { this.channelHandlers.push(connectionHandler.path, (params, channel) => { connectionHandler.onConnection(channel); }); } } // eslint-disable-next-line @typescript-eslint/no-explicit-any ipcChannel(spec, callback) { this.channelHandlers.push(spec, callback); } }; __decorate([ (0, inversify_1.inject)(contribution_provider_1.ContributionProvider), (0, inversify_1.named)(electron_messaging_service_1.ElectronMessagingService.Contribution), __metadata("design:type", Object) ], ElectronMessagingContribution.prototype, "messagingContributions", void 0); __decorate([ (0, inversify_1.inject)(contribution_provider_1.ContributionProvider), (0, inversify_1.named)(electron_connection_handler_1.ElectronConnectionHandler), __metadata("design:type", Object) ], ElectronMessagingContribution.prototype, "connectionHandlers", void 0); __decorate([ (0, inversify_1.postConstruct)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ElectronMessagingContribution.prototype, "init", null); ElectronMessagingContribution = __decorate([ (0, inversify_1.injectable)() ], ElectronMessagingContribution); exports.ElectronMessagingContribution = ElectronMessagingContribution; /** * Used to establish a connection between the ipcMain and the Electron frontend (window). * Messages a transferred via electron IPC. */ class ElectronWebContentChannel extends channel_1.AbstractChannel { constructor(sender) { super(); this.sender = sender; // Make the message emitter public so that we can easily forward messages received from the ipcMain. this.onMessageEmitter = new common_1.Emitter(); } getWriteBuffer() { const writer = new uint8_array_message_buffer_1.Uint8ArrayWriteBuffer(); writer.onCommit(buffer => { if (!this.sender.isDestroyed()) { electron_api_main_1.TheiaRendererAPI.sendData(this.sender, buffer); } }); return writer; } } exports.ElectronWebContentChannel = ElectronWebContentChannel; //# sourceMappingURL=electron-messaging-contribution.js.map