diff --git a/packages/plugin-ext/src/api/rpc-protocol.ts b/packages/plugin-ext/src/api/rpc-protocol.ts index 743c4f0b063ca..edad8185205f2 100644 --- a/packages/plugin-ext/src/api/rpc-protocol.ts +++ b/packages/plugin-ext/src/api/rpc-protocol.ts @@ -236,7 +236,11 @@ class RPCMultiplexer { public send(msg: string): void { if (this.messagesToSend.length === 0) { - setImmediate(this.sendAccumulatedBound); + if (typeof setImmediate !== 'undefined') { + setImmediate(this.sendAccumulatedBound); + } else { + setTimeout(this.sendAccumulatedBound, 0); + } } this.messagesToSend.push(msg); } diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index 7ba6362451bfc..16d0e9740f41c 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -42,6 +42,7 @@ export interface PluginPackage { displayName: string; description: string; contributes: {}; + packagePath: string; } export const PluginScanner = Symbol('PluginScanner'); diff --git a/packages/plugin-ext/src/hosted/browser/worker/worker-main.ts b/packages/plugin-ext/src/hosted/browser/worker/worker-main.ts index 432edf4c68ed9..ed874da7aa69d 100644 --- a/packages/plugin-ext/src/hosted/browser/worker/worker-main.ts +++ b/packages/plugin-ext/src/hosted/browser/worker/worker-main.ts @@ -43,7 +43,12 @@ rpc.set(MAIN_RPC_CONTEXT.HOSTED_PLUGIN_MANAGER_EXT, new HostedPluginManagerExtIm ctx.importScripts('/context/' + contextPath); }, loadPlugin(contextPath: string, plugin: Plugin): void { - ctx.importScripts('/hostedPlugin/' + getPluginId(plugin.model) + '/' + plugin.pluginPath); + if (isElectron()) { + ctx.importScripts(plugin.pluginPath); + } else { + ctx.importScripts('/hostedPlugin/' + getPluginId(plugin.model) + '/' + plugin.pluginPath); + } + if (plugin.lifecycle.frontendModuleName) { if (!ctx[plugin.lifecycle.frontendModuleName]) { console.error(`WebWorker: Cannot start plugin "${plugin.model.name}". Frontend plugin not found: "${plugin.lifecycle.frontendModuleName}"`); @@ -62,3 +67,11 @@ rpc.set(MAIN_RPC_CONTEXT.HOSTED_PLUGIN_MANAGER_EXT, new HostedPluginManagerExtIm }); } })); + +function isElectron() { + if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) { + return true; + } + + return false; +} diff --git a/packages/plugin-ext/src/hosted/node-electron/plugin-ext-hosted-electron-backend-module.ts b/packages/plugin-ext/src/hosted/node-electron/plugin-ext-hosted-electron-backend-module.ts index 5b37192b5e138..8151bc19becc7 100644 --- a/packages/plugin-ext/src/hosted/node-electron/plugin-ext-hosted-electron-backend-module.ts +++ b/packages/plugin-ext/src/hosted/node-electron/plugin-ext-hosted-electron-backend-module.ts @@ -17,8 +17,11 @@ import { HostedPluginManager, ElectronNodeHostedPluginRunner } from '../node/hosted-plugin-manager'; import { interfaces } from 'inversify'; import { bindCommonHostedBackend } from '../node/plugin-ext-hosted-backend-module'; +import { PluginScanner } from '../../common/plugin-protocol'; +import { TheiaPluginScannerElectron } from './scanner-theia-electron'; export function bindElectronBackend(bind: interfaces.Bind): void { bind(HostedPluginManager).to(ElectronNodeHostedPluginRunner); + bind(PluginScanner).to(TheiaPluginScannerElectron).inSingletonScope(); bindCommonHostedBackend(bind); } diff --git a/packages/plugin-ext/src/hosted/node-electron/scanner-theia-electron.ts b/packages/plugin-ext/src/hosted/node-electron/scanner-theia-electron.ts new file mode 100644 index 0000000000000..db34c94f6979a --- /dev/null +++ b/packages/plugin-ext/src/hosted/node-electron/scanner-theia-electron.ts @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (C) 2018 Red Hat, Inc. 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 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { TheiaPluginScanner } from "../node/scanners/scanner-theia"; +import { injectable } from "inversify"; +import { PluginPackage, PluginModel } from "../../common/plugin-protocol"; +@injectable() +export class TheiaPluginScannerElectron extends TheiaPluginScanner { + getModel(plugin: PluginPackage): PluginModel { + const result = super.getModel(plugin); + if (result.entryPoint.frontend) { + result.entryPoint.frontend = plugin.packagePath + result.entryPoint.frontend; + } + return result; + } +} diff --git a/packages/plugin-ext/src/hosted/node/plugin-ext-hosted-backend-module.ts b/packages/plugin-ext/src/hosted/node/plugin-ext-hosted-backend-module.ts index d76e4243a7291..281c46bb09e04 100644 --- a/packages/plugin-ext/src/hosted/node/plugin-ext-hosted-backend-module.ts +++ b/packages/plugin-ext/src/hosted/node/plugin-ext-hosted-backend-module.ts @@ -31,7 +31,6 @@ export function bindCommonHostedBackend(bind: interfaces.Bind): void { bind(HostedPluginReader).toSelf().inSingletonScope(); bind(HostedPluginServer).to(HostedPluginServerImpl).inSingletonScope(); bind(HostedPluginSupport).toSelf().inSingletonScope(); - bind(PluginScanner).to(TheiaPluginScanner).inSingletonScope(); bind(MetadataScanner).toSelf().inSingletonScope(); bind(BackendApplicationContribution).toDynamicValue(ctx => ctx.container.get(HostedPluginReader)).inSingletonScope(); @@ -50,6 +49,7 @@ export function bindCommonHostedBackend(bind: interfaces.Bind): void { export function bindHostedBackend(bind: interfaces.Bind): void { bind(HostedPluginManager).to(NodeHostedPluginRunner).inSingletonScope(); + bind(PluginScanner).to(TheiaPluginScanner).inSingletonScope(); bindContributionProvider(bind, Symbol.for(HostedPluginUriPostProcessorSymbolName)); bindCommonHostedBackend(bind); } diff --git a/packages/plugin-ext/src/hosted/node/plugin-reader.ts b/packages/plugin-ext/src/hosted/node/plugin-reader.ts index b3c523025fb34..26288355844ee 100644 --- a/packages/plugin-ext/src/hosted/node/plugin-reader.ts +++ b/packages/plugin-ext/src/hosted/node/plugin-reader.ts @@ -73,6 +73,7 @@ export class HostedPluginReader implements BackendApplicationContribution { } const plugin: PluginPackage = require(packageJsonPath); + plugin.packagePath = path; const pluginMetadata = this.scanner.getPluginMetadata(plugin); if (pluginMetadata.model.entryPoint.backend) { pluginMetadata.model.entryPoint.backend = resolve(path, pluginMetadata.model.entryPoint.backend); diff --git a/packages/plugin-ext/src/plugin/plugin-context.ts b/packages/plugin-ext/src/plugin/plugin-context.ts index 502a1e838b921..e1c852aa147ac 100644 --- a/packages/plugin-ext/src/plugin/plugin-context.ts +++ b/packages/plugin-ext/src/plugin/plugin-context.ts @@ -278,7 +278,7 @@ export function createAPI(rpc: RPCProtocol): typeof theia { // tslint:disable-next-line:no-any export function startPlugin(plugin: Plugin, pluginMain: any, plugins: Map void>): void { if (typeof pluginMain[plugin.lifecycle.startMethod] === 'function') { - pluginMain[plugin.lifecycle.startMethod].apply(global, []); + pluginMain[plugin.lifecycle.startMethod].apply(getGlobal(), []); } else { console.log('there is no doStart method on plugin'); } @@ -288,3 +288,9 @@ export function startPlugin(plugin: Plugin, pluginMain: any, plugins: Map