diff --git a/packages/plugin-ext/package.json b/packages/plugin-ext/package.json index 8db527c5fee4a..65413a7b59669 100644 --- a/packages/plugin-ext/package.json +++ b/packages/plugin-ext/package.json @@ -20,6 +20,7 @@ "@theia/task": "^0.5.0", "@theia/workspace": "^0.5.0", "decompress": "^4.2.0", + "getmac": "^1.4.6", "jsonc-parser": "^2.0.2", "lodash.clonedeep": "^4.5.0", "ps-tree": "1.1.0", diff --git a/packages/plugin-ext/src/api/plugin-api.ts b/packages/plugin-ext/src/api/plugin-api.ts index e0f9556e74ee6..8af92111c35fb 100644 --- a/packages/plugin-ext/src/api/plugin-api.ts +++ b/packages/plugin-ext/src/api/plugin-api.ts @@ -92,6 +92,7 @@ export interface ConfigStorage { export interface EnvInit { queryParams: QueryParameters; + language: string; } export interface PluginAPI { diff --git a/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts b/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts index b050ac6a23ae0..198f47c003e3a 100644 --- a/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts +++ b/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts @@ -133,7 +133,7 @@ export class HostedPluginSupport { preferences: getPreferences(this.preferenceProviderProvider), globalState: initData.globalStates, workspaceState: initData.workspaceStates, - env: { queryParams: getQueryParameters() }, + env: { queryParams: getQueryParameters(), language: navigator.language }, extApi: initData.pluginAPIs }, confStorage); setUpPluginApi(worker.rpc, container); @@ -174,7 +174,7 @@ export class HostedPluginSupport { preferences: getPreferences(this.preferenceProviderProvider), globalState: initData.globalStates, workspaceState: initData.workspaceStates, - env: { queryParams: getQueryParameters() }, + env: { queryParams: getQueryParameters(), language: navigator.language }, extApi: initData.pluginAPIs }, confStorage); this.mainPluginApiProviders.getContributions().forEach(p => p.initialize(rpc!, container)); diff --git a/packages/plugin-ext/src/hosted/browser/worker/worker-env-ext.ts b/packages/plugin-ext/src/hosted/browser/worker/worker-env-ext.ts new file mode 100644 index 0000000000000..e667f32a38176 --- /dev/null +++ b/packages/plugin-ext/src/hosted/browser/worker/worker-env-ext.ts @@ -0,0 +1,37 @@ +/******************************************************************************** + * Copyright (C) 2019 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 { EnvExtImpl } from '../../../plugin/env'; +import { RPCProtocol } from '../../../api/rpc-protocol'; + +/** + * Worker specific implementation not returning any FileSystem details + * Extending the common class + */ +export class WorkerEnvExtImpl extends EnvExtImpl { + + constructor(rpc: RPCProtocol) { + super(rpc); + } + + /** + * Throw error for app-root as there is no filesystem in worker context + */ + get appRoot(): string { + throw new Error('There is no app root in worker context'); + } + +} 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 bed91911901f9..d11ef144db951 100644 --- a/packages/plugin-ext/src/hosted/browser/worker/worker-main.ts +++ b/packages/plugin-ext/src/hosted/browser/worker/worker-main.ts @@ -21,13 +21,13 @@ import { MAIN_RPC_CONTEXT, Plugin, emptyPlugin } from '../../../api/plugin-api'; import { createAPIFactory } from '../../../plugin/plugin-context'; import { getPluginId, PluginMetadata } from '../../../common/plugin-protocol'; import * as theia from '@theia/plugin'; -import { EnvExtImpl } from '../../../plugin/env'; import { PreferenceRegistryExtImpl } from '../../../plugin/preference-registry'; import { ExtPluginApi } from '../../../common/plugin-ext-api-contribution'; import { createDebugExtStub } from './debug-stub'; import { EditorsAndDocumentsExtImpl } from '../../../plugin/editors-and-documents'; import { WorkspaceExtImpl } from '../../../plugin/workspace'; import { MessageRegistryExt } from '../../../plugin/message-registry'; +import { WorkerEnvExtImpl } from './worker-env-ext'; // tslint:disable-next-line:no-any const ctx = self as any; @@ -49,7 +49,7 @@ addEventListener('message', (message: any) => { function initialize(contextPath: string, pluginMetadata: PluginMetadata): void { ctx.importScripts('/context/' + contextPath); } -const envExt = new EnvExtImpl(rpc); +const envExt = new WorkerEnvExtImpl(rpc); const editorsAndDocuments = new EditorsAndDocumentsExtImpl(rpc); const messageRegistryExt = new MessageRegistryExt(rpc); const workspaceExt = new WorkspaceExtImpl(rpc, editorsAndDocuments, messageRegistryExt); diff --git a/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts b/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts index 9d146023faa0d..ac237ce0b2405 100644 --- a/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts +++ b/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts @@ -25,6 +25,7 @@ import { DebugExtImpl } from '../../plugin/node/debug/debug'; import { EditorsAndDocumentsExtImpl } from '../../plugin/editors-and-documents'; import { WorkspaceExtImpl } from '../../plugin/workspace'; import { MessageRegistryExt } from '../../plugin/message-registry'; +import { EnvNodeExtImpl } from '../../plugin/node/env-node-ext'; /** * Handle the RPC calls. @@ -40,7 +41,7 @@ export class PluginHostRPC { } initialize() { - const envExt = new EnvExtImpl(this.rpc); + const envExt = new EnvNodeExtImpl(this.rpc); const debugExt = new DebugExtImpl(this.rpc); const editorsAndDocumentsExt = new EditorsAndDocumentsExtImpl(this.rpc); const messageRegistryExt = new MessageRegistryExt(this.rpc); diff --git a/packages/plugin-ext/src/plugin/env.ts b/packages/plugin-ext/src/plugin/env.ts index 93d40eab7ff81..197fc778da852 100644 --- a/packages/plugin-ext/src/plugin/env.ts +++ b/packages/plugin-ext/src/plugin/env.ts @@ -18,13 +18,21 @@ import * as theia from '@theia/plugin'; import { RPCProtocol } from '../api/rpc-protocol'; import { EnvMain, PLUGIN_RPC_CONTEXT } from '../api/plugin-api'; import { QueryParameters } from '../common/env'; +import { v4 } from 'uuid'; -export class EnvExtImpl { +export abstract class EnvExtImpl { private proxy: EnvMain; private queryParameters: QueryParameters; + private lang: string; + private envMachineId: string; + private envSessionId: string; + + public static readonly APP_NAME = 'Eclipse Theia'; constructor(rpc: RPCProtocol) { this.proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.ENV_MAIN); + this.envSessionId = v4(); + this.envMachineId = v4(); } getEnvVariable(envVarName: string): Promise { @@ -48,7 +56,30 @@ export class EnvExtImpl { this.queryParameters = queryParams; } + setLanguage(lang: string): void { + this.lang = lang; + } + getClientOperatingSystem(): Promise { return this.proxy.$getClientOperatingSystem(); } + + get appName(): string { + return EnvExtImpl.APP_NAME; + } + + abstract get appRoot(): string; + + get language(): string { + return this.lang; + } + get machineId(): string { + return this.envMachineId; + } + get sessionId(): string { + return this.envSessionId; + } + get uriScheme(): string { + return 'theia'; + } } diff --git a/packages/plugin-ext/src/plugin/node/env-node-ext.ts b/packages/plugin-ext/src/plugin/node/env-node-ext.ts new file mode 100644 index 0000000000000..14af87d0c49fb --- /dev/null +++ b/packages/plugin-ext/src/plugin/node/env-node-ext.ts @@ -0,0 +1,57 @@ +/******************************************************************************** + * Copyright (C) 2019 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 { EnvExtImpl } from '../env'; +import { RPCProtocol } from '../../api/rpc-protocol'; +import { createHash } from 'crypto'; +import { getMac } from 'getmac'; +import { v4 } from 'uuid'; + +/** + * Provides machineId using mac address. It's only possible on node side + * Extending the common class + */ +export class EnvNodeExtImpl extends EnvExtImpl { + + private macMachineId: string; + + constructor(rpc: RPCProtocol) { + super(rpc); + getMac((err, macAddress) => { + if (err) { + this.macMachineId = v4(); + } else { + this.macMachineId = createHash('sha256').update(macAddress, 'utf8').digest('hex'); + } + }); + + } + + /** + * override machineID + */ + get machineId(): string { + return this.macMachineId; + } + + /** + * Provides application root. + */ + get appRoot(): string { + return __dirname; + } + +} diff --git a/packages/plugin-ext/src/plugin/plugin-context.ts b/packages/plugin-ext/src/plugin/plugin-context.ts index bed7853400fd9..f64656e9fb7a3 100644 --- a/packages/plugin-ext/src/plugin/plugin-context.ts +++ b/packages/plugin-ext/src/plugin/plugin-context.ts @@ -444,7 +444,14 @@ export function createAPIFactory( } }; - const env: typeof theia.env = { + const env: typeof theia.env = Object.freeze({ + get appName() { return envExt.appName; }, + get appRoot() { return envExt.appRoot; }, + get language() { return envExt.language; }, + get machineId() { return envExt.machineId; }, + get sessionId() { return envExt.sessionId; }, + get uriScheme() { return envExt.uriScheme; }, + getEnvVariable(envVarName: string): PromiseLike { return envExt.getEnvVariable(envVarName); }, @@ -458,7 +465,7 @@ export function createAPIFactory( return envExt.getClientOperatingSystem(); } - }; + }); const languageServer: typeof theia.languageServer = { registerLanguageServerProvider(languageServerInfo: theia.LanguageServerInfo): Disposable { diff --git a/packages/plugin-ext/src/plugin/plugin-manager.ts b/packages/plugin-ext/src/plugin/plugin-manager.ts index b133c6ec2fb02..5f02f96c2ce1b 100644 --- a/packages/plugin-ext/src/plugin/plugin-manager.ts +++ b/packages/plugin-ext/src/plugin/plugin-manager.ts @@ -104,6 +104,7 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager { // init query parameters this.envExt.setQueryParameters(pluginInit.env.queryParams); + this.envExt.setLanguage(pluginInit.env.language); this.preferencesManager.init(pluginInit.preferences); diff --git a/packages/plugin-ext/src/typings/index.d.ts b/packages/plugin-ext/src/typings/index.d.ts new file mode 100644 index 0000000000000..5620b70abc161 --- /dev/null +++ b/packages/plugin-ext/src/typings/index.d.ts @@ -0,0 +1,19 @@ +/******************************************************************************** + * Copyright (C) 2019 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 + ********************************************************************************/ + +declare module 'getmac' { + function getMac(cb: (error: Error, macAddress: string) => void): void; +} diff --git a/packages/plugin/src/theia.d.ts b/packages/plugin/src/theia.d.ts index 6b63cfc2e8357..b41449813b06c 100644 --- a/packages/plugin/src/theia.d.ts +++ b/packages/plugin/src/theia.d.ts @@ -4232,6 +4232,38 @@ declare module '@theia/plugin' { * Returns all query parameters of current IDE. */ export function getQueryParameters(): { [key: string]: string | string[] } | undefined; + + /** + * The application name of the editor, like 'Eclipse Theia'. + */ + export const appName: string; + + /** + * The application root folder from which the editor is running. + */ + export const appRoot: string; + + /** + * The custom uri scheme the editor registers to in the operating system. + */ + export const uriScheme: string; + + /** + * Represents the preferred user-language, like `de-CH`, `fr`, or `en-US`. + */ + export const language: string; + + /** + * A unique identifier for the computer. + */ + export const machineId: string; + + /** + * A unique identifier for the current session. + * Changes each time the editor is started. + */ + export const sessionId: string; + } /** diff --git a/yarn.lock b/yarn.lock index feaaefd0a73fb..09ed0997b331a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3373,6 +3373,14 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +eachr@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eachr/-/eachr-3.2.0.tgz#2c35e43ea086516f7997cf80b7aa64d55a4a4484" + integrity sha1-LDXkPqCGUW95l8+At6pk1VpKRIQ= + dependencies: + editions "^1.1.1" + typechecker "^4.3.0" + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -3380,10 +3388,18 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -editions@^1.3.3: +editions@^1.1.1, editions@^1.3.3: version "1.3.4" resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" +editions@^2.0.2, editions@^2.1.0, editions@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/editions/-/editions-2.1.3.tgz#727ccf3ec2c7b12dcc652c71000f16c4824d6f7d" + integrity sha512-xDZyVm0A4nLgMNWVVLJvcwMjI80ShiH/27RyLiCnW1L273TcJIA25C4pwJ33AWV01OX6UriP35Xu+lH4S7HWQw== + dependencies: + errlop "^1.1.1" + semver "^5.6.0" + editorconfig@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.0.tgz#b6dd4a0b6b9e76ce48e066bdc15381aebb8804fd" @@ -3537,6 +3553,13 @@ env-variable@0.0.x: version "0.0.4" resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.4.tgz#0d6280cf507d84242befe35a512b5ae4be77c54e" +errlop@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.1.1.tgz#d9ae4c76c3e64956c5d79e6e035d6343bfd62250" + integrity sha512-WX7QjiPHhsny7/PQvrhS5VMizXXKoKCS3udaBp8gjlARdbn+XmK300eKBAAN0hGyRaTCtRpOaxK+xFVPUJ3zkw== + dependencies: + editions "^2.1.2" + errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -3839,6 +3862,15 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-opts@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-3.3.1.tgz#5abbedc98c0d5202e3278727f9192d7e086c6be1" + integrity sha1-WrvtyYwNUgLjJ4cn+Rktfghsa+E= + dependencies: + eachr "^3.2.0" + editions "^1.1.1" + typechecker "^4.3.0" + extract-zip@^1.0.3: version "1.6.7" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" @@ -4319,6 +4351,14 @@ get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" +getmac@^1.4.6: + version "1.4.6" + resolved "https://registry.yarnpkg.com/getmac/-/getmac-1.4.6.tgz#ffe7db07900e222916939d44e4c7274adbecc662" + integrity sha512-3JPwiIr4P6Sgr6y6SVXX0+l2mrB6pyf4Cdyua7rvEV7SveWQkAp11vrkNym8wvRxzLrBenKRcwe93asdghuwWg== + dependencies: + editions "^2.0.2" + extract-opts "^3.2.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -8518,6 +8558,11 @@ selenium-standalone@^6.15.4: version "5.5.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" +semver@^5.6.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -9541,6 +9586,13 @@ type-is@~1.6.15, type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" +typechecker@^4.3.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.7.0.tgz#5249f427358f45b7250c4924fd4d01ed9ba435e9" + integrity sha512-4LHc1KMNJ6NDGO+dSM/yNfZQRtp8NN7psYrPHUblD62Dvkwsp3VShsbM78kOgpcmMkRTgvwdKOTjctS+uMllgQ== + dependencies: + editions "^2.1.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"