UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

1 lines 26.9 kB
{"version":3,"sources":["../../../packages/core/rpc/rpc.ts"],"names":[],"mappings":"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","file":"rpc.d.ts","sourcesContent":["import { Observable, Subject } from 'rxjs';\r\nimport { CoreEnvironment } from '../data/core-environment';\r\nimport { NativeDeferred, NativeQ } from '../data/native-q';\r\nimport { LogLevel } from '../diagnostics/log-level';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { SmeWebTelemetry } from '../diagnostics/sme-web-telemetry';\r\nimport { Strings } from '../generated/strings';\r\nimport { EnvironmentModuleEntryPoint } from '../manifest/environment-modules';\r\nimport {\r\n CommandCallBackType,\r\n RpcActivateDataInternal,\r\n RpcBase,\r\n RpcBaseData,\r\n RpcDeactivateResult,\r\n RpcInboundCommands,\r\n RpcInboundHandlers,\r\n RpcInitData,\r\n RpcInitDataInternal,\r\n RpcInitResult,\r\n RpcMode,\r\n RpcOpenDataInternal,\r\n RpcOpenResult,\r\n RpcOutboundCommands,\r\n RpcOutboundHandlers,\r\n RpcPingResult,\r\n RpcShutdownData,\r\n RpcShutdownResult,\r\n RpcType,\r\n rpcVersion\r\n} from './rpc-base';\r\nimport { RpcManager } from './rpc-manager';\r\nimport { RpcOutbound } from './rpc-outbound';\r\nimport { RpcSeek, RpcSeekMode, RpcSeekResult } from './seek/rpc-seek-model';\r\n\r\n/**\r\n * Deferred data object.\r\n */\r\nexport interface DeferredData<TData, TResult> {\r\n deferred: NativeDeferred<TResult>;\r\n data: TData;\r\n}\r\n\r\n/**\r\n * The Rpc class.\r\n */\r\nexport class Rpc {\r\n // RPC timeout 10 seconds.\r\n private static rpcTimeout = 10 * 1000;\r\n\r\n /**\r\n * This subject is updated whenever there's new reported data\r\n */\r\n private rpcSubjects: { [index: string]: Subject<DeferredData<any, any>> };\r\n\r\n /**\r\n * Deferred response collection.\r\n */\r\n private deferredCollection = new Map<RpcOutboundCommands, DeferredData<any, any>>();\r\n\r\n /**\r\n * Active status of rpc by Observable.\r\n */\r\n private stateChangedInternal: Subject<boolean> = new Subject<boolean>();\r\n\r\n /**\r\n * Active status of rpc.\r\n */\r\n private stateActiveInternal = false;\r\n\r\n /**\r\n * Inbound module handlers to process when rpc is called.\r\n * - called from Module to Shell.\r\n */\r\n private rpcInboundHandlers: RpcInboundHandlers = {\r\n FailedHandler: (data: RpcBaseData) => {\r\n return this.processNextForSubject<RpcBaseData, void>(RpcInboundCommands.Failed, data);\r\n },\r\n SeekHandler: (data: RpcSeek) => {\r\n return Promise.resolve(<RpcSeekResult>{ name: data.sourceName, subName: data.sourceSubName });\r\n }\r\n };\r\n\r\n /**\r\n * Outbound shell handlers to process when rpc is called.\r\n * - called from Shell to Module.\r\n * - if code reached a handler, module is not ready yet.\r\n * set timeout for RPC call.\r\n */\r\n private rpcOutboundHandlers: RpcOutboundHandlers = {\r\n InitHandler: (data: RpcInitDataInternal) =>\r\n this.createTimerPromise<RpcInitDataInternal, RpcInitResult>(\r\n RpcOutboundCommands.Init, Rpc.rpcTimeout,\r\n <RpcInitDataInternal>{ locale: data.locale }),\r\n OpenHandler: (rpcOpenData: RpcOpenDataInternal) =>\r\n this.createTimerPromise<RpcOpenDataInternal, RpcOpenResult>(RpcOutboundCommands.Open, Rpc.rpcTimeout, rpcOpenData),\r\n ActivateHandler: (data: RpcActivateDataInternal) =>\r\n this.createTimerPromise<RpcBaseData, void>(RpcOutboundCommands.Activate, Rpc.rpcTimeout, data),\r\n Deactivate2Handler: (data: RpcBaseData) =>\r\n this.createTimerPromise<RpcBaseData, RpcDeactivateResult>(RpcOutboundCommands.Deactivate2, Rpc.rpcTimeout, data),\r\n ShutdownHandler: (data: RpcShutdownData) =>\r\n this.createTimerPromise<RpcShutdownData, RpcShutdownResult>(RpcOutboundCommands.Shutdown, Rpc.rpcTimeout, data),\r\n PingHandler: () => {\r\n this.changeActiveState(true);\r\n return Promise.resolve(<RpcPingResult>{ name: 'pong' });\r\n }\r\n };\r\n\r\n /**\r\n * Rpc manager object.\r\n */\r\n public rpcManager: RpcManager = new RpcManager();\r\n\r\n /**\r\n * Initializes a new instance of the Rpc class.\r\n *\r\n * @param http the Http class instance injected.\r\n */\r\n constructor() {\r\n this.rpcSubjects = {};\r\n const commands = Object.keys(RpcInboundCommands);\r\n commands.forEach((value) => {\r\n this.rpcSubjects[RpcInboundCommands[value]] = new Subject<any>();\r\n });\r\n }\r\n\r\n /**\r\n * Gets observable to watch the state change.\r\n */\r\n public get stateChanged(): Observable<boolean> {\r\n this.stateChangedInternal.next(this.stateActiveInternal);\r\n return this.stateChangedInternal.asObservable();\r\n }\r\n\r\n /**\r\n * Gets the state of rpc.\r\n */\r\n public get stateActive(): boolean {\r\n return this.stateActiveInternal;\r\n }\r\n\r\n /**\r\n * Gets whether rpc is running on the shell.\r\n */\r\n public get isShell(): boolean {\r\n if (this.rpcManager.rpcChannel == null) {\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.RpcNotInitialized.message;\r\n throw new Error(message);\r\n }\r\n\r\n return this.rpcManager.rpcChannel.rpcMode === RpcMode.Shell;\r\n }\r\n\r\n /**\r\n * Register inbound command handler.\r\n *\r\n * @param command The command name.\r\n * @param handler The command handler.\r\n */\r\n public registerInboundHandler(command: string, handler: CommandCallBackType): void {\r\n const handlerName = RpcBase.commandToHandlerName(command);\r\n this.rpcInboundHandlers[handlerName] = handler;\r\n this.rpcManager.registerInboundHandler(command, handler);\r\n }\r\n\r\n /**\r\n * Register outbound command handler.\r\n *\r\n * @param command The command name.\r\n * @param handler The command handler.\r\n */\r\n public registerOutboundHandler(command: string, handler: CommandCallBackType): void {\r\n const handlerName = RpcBase.commandToHandlerName(command);\r\n this.rpcOutboundHandlers[handlerName] = handler;\r\n }\r\n\r\n /**\r\n * Initializes Rpc configuration\r\n */\r\n public init(): void {\r\n this.rpcManager.init(this.rpcInboundHandlers, this.rpcOutboundHandlers);\r\n if (this.isShell) {\r\n this.changeActiveState(true);\r\n }\r\n }\r\n\r\n /***************************************************************\r\n * Section for Shell usage.\r\n ***************************************************************/\r\n\r\n /**\r\n * This updates its value every time there's a reported data from the rpc channel\r\n */\r\n public moduleSubjects<T>(commandType: RpcInboundCommands): Observable<DeferredData<T, any>> {\r\n return <Observable<DeferredData<T, any>>>this.rpcSubjects[RpcInboundCommands[commandType]];\r\n }\r\n\r\n /**\r\n * Connect a module with name and iframe.\r\n * - start pinging to iframe to wait for response.\r\n *\r\n * @param name the name of the module.\r\n * @param path the path to open the module the module name.\r\n * @param iframe the iframe window object.\r\n * @param primary the primary window to affect router url.\r\n * @return Promise<string> the promise with subName created for the window.\r\n */\r\n public moduleConnect(name: string, path: string, iframe: Window, primary: boolean): Promise<string> {\r\n return this.rpcManager.connectRpcOutbound(name, path, iframe, primary);\r\n }\r\n\r\n /**\r\n * Init the module.\r\n *\r\n * @param name the name of module.\r\n * @param subName the sub name of rpc channel.\r\n * @param entryPointType the entry point type.\r\n * @return Promise<void> the promise object of init result.\r\n */\r\n public moduleInit(name: string, subName: string, entryPoint: EnvironmentModuleEntryPoint): Promise<RpcInitResult> {\r\n const rpc = this.rpcManager.rpcChannel.getRpc<RpcOutbound>(name, subName, RpcType.Outbound);\r\n const self = MsftSme.self();\r\n const data: RpcInitData = {\r\n entryPointType: entryPoint.entryPointType,\r\n entryPointName: entryPoint.name,\r\n theme: self.Resources.theme,\r\n assets: self.Resources.assets,\r\n moduleAssets: self.Resources.moduleAssets,\r\n locale: self.Resources.localeId,\r\n localeRegional: self.Resources.localeRegionalId,\r\n lib: self.Resources.lib,\r\n sessionId: self.Init.sessionId,\r\n modules: self.Environment.modules,\r\n accessibilityMode: self.Resources.accessibilityMode,\r\n sessionExpiration: self.Init.sessionExpiration,\r\n performanceProfile: MsftSme.getPerformanceProfile(),\r\n connectivityLevel: self.Init.connectivityLevel,\r\n consoleDebug: MsftSme.consoleDebug(),\r\n sideLoad: MsftSme.sideLoad(),\r\n experiments: MsftSme.experiments(),\r\n shellVersion: self.Init.shellVersion,\r\n gatewayApiVersion: self.Init.gatewayApiVersion,\r\n gatewayPlatform: self.Init.gatewayPlatform\r\n };\r\n return rpc.init(data).then(result => {\r\n const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Rpc;\r\n // copy the version string of remote module.\r\n if (result && result.version) {\r\n rpc.version = result.version;\r\n Logging.log({\r\n level: LogLevel.Verbose,\r\n message: strings.Version.message.format(rpcVersion, name, rpc.version),\r\n source: 'rpc.moduleInit'\r\n });\r\n } else {\r\n const message = strings.MissingVersion.message.format(name);\r\n Logging.log({\r\n level: LogLevel.Critical,\r\n message,\r\n source: 'rpc.moduleInit'\r\n });\r\n throw new Error(message);\r\n }\r\n\r\n this.changeActiveState(true);\r\n return result;\r\n });\r\n }\r\n\r\n /**\r\n * Open the module by specifying the path and parameters.\r\n *\r\n * @param name the name of module.\r\n * @param subName the sub name of rpc channel.\r\n * @param path the open path.\r\n * @return Promise<RpcOpenResult> the promise object of RpcOpenResult.\r\n */\r\n public moduleOpen(name: string, subName: string, path: string): Promise<RpcOpenResult> {\r\n const rpc = <RpcOutbound>this.rpcManager.rpcChannel.getRpc(name, subName, RpcType.Outbound);\r\n return rpc.open({ path }).then(result => {\r\n this.changeActiveState(true);\r\n return result;\r\n });\r\n }\r\n\r\n /**\r\n * Activate the module to start receiving data.\r\n *\r\n * @param name the module name.\r\n * @param subName the sub name of rpc channel.\r\n * @param primary the primary window to affect router url.\r\n * @param url the inner url to open.\r\n * @return Promise<void> the promise of activation result.\r\n */\r\n public moduleActivate(name: string, subName: string, primary: boolean, url: string): Promise<void> {\r\n const rpc = this.rpcManager.reconnectRpcOutbound(name, subName, primary);\r\n return rpc.activate({ url })\r\n .then(data => {\r\n this.changeActiveState(true);\r\n return data;\r\n });\r\n }\r\n\r\n /**\r\n * Deactivate 2 the module to stop receiving data.\r\n *\r\n * @param name the module name.\r\n * @param subName the sub name of rpc channel.\r\n * @return Promise<void> the promise of deactivation result.\r\n */\r\n public moduleDeactivate2(name: string, subName: string): Promise<RpcDeactivateResult> {\r\n this.changeActiveState(false);\r\n const rpc = this.rpcManager.rpcChannel.getRpc<RpcOutbound>(name, subName, RpcType.Outbound);\r\n return rpc.deactivate2({});\r\n }\r\n\r\n /**\r\n * Request to shutdown the module.\r\n *\r\n * @param name the module name.\r\n * @param subName the sub name of rpc channel.\r\n * @param primary the primary window to affect router url.\r\n * @param force the forcible state.\r\n * @return Promise<RpcShutdownResult> the promise object of result.\r\n */\r\n public moduleShutdown(name: string, subName: string, primary: boolean, force: boolean): Promise<RpcShutdownResult> {\r\n const rpc = this.rpcManager.reconnectRpcOutbound(name, subName, primary);\r\n return rpc.shutdown({ force: force });\r\n }\r\n\r\n /**\r\n * Remove the module from the rpc channel.\r\n *\r\n * @param name the module name.\r\n * @param subName the sub name of rpc channel.\r\n */\r\n public moduleRemove(name: string, subName: string): void {\r\n this.rpcManager.removeRpcOutbound(name, subName);\r\n }\r\n\r\n /**\r\n * Get module version string.\r\n *\r\n * @param name the name of module.\r\n * @param subName the sub name of rpc channel.\r\n * @return string the RPC version of module.\r\n */\r\n public moduleVersion(name: string, subName: string): string {\r\n const rpc = <RpcOutbound>this.rpcManager.rpcChannel.getRpc(name, subName, RpcType.Outbound);\r\n return rpc && rpc.version;\r\n }\r\n\r\n /***************************************************************\r\n * Section for Module usage.\r\n ***************************************************************/\r\n\r\n /**\r\n * Register outbound handler. It accepts delay register in case of loading/initialization took a time for module.\r\n *\r\n * @param command the name of RPC Shell command.\r\n * @param handler the handler to handle Shell request.\r\n */\r\n public register(command: string, handler: (data: any) => Promise<any>): void;\r\n\r\n /**\r\n * Register outbound handler. It accepts delay register in case of loading/initialization took a time for module.\r\n *\r\n * @param command the enum ID of RPC Shell command.\r\n * @param handler the handler to handle Shell request.\r\n */\r\n public register(command: RpcOutboundCommands, handler: (data: any) => Promise<any>): void;\r\n public register(command: RpcOutboundCommands | string, handler: (data: any) => Promise<any>): void {\r\n if (typeof command === 'string') {\r\n const commandName: string = command;\r\n this.rpcManager.rpcInbound.register(commandName, handler);\r\n return;\r\n }\r\n\r\n const deferredData = <DeferredData<any, any>>this.deferredCollection[command];\r\n if (deferredData) {\r\n delete this.deferredCollection[command];\r\n handler(deferredData.data).then(deferredData.deferred.resolve, deferredData.deferred.reject);\r\n return;\r\n }\r\n\r\n if (command === RpcOutboundCommands.Init) {\r\n const modifiedHandler = (data: RpcInitDataInternal) => {\r\n // node context is used before passing request to handler.\r\n this.changeActiveState(true);\r\n const self = MsftSme.self();\r\n self.Init.entryPointType = data.entryPointType;\r\n self.Init.entryPointName = data.entryPointName;\r\n self.Init.sessionId = data.sessionId;\r\n self.Init.sessionExpiration = data.sessionExpiration;\r\n self.Init.performanceProfile = data.performanceProfile;\r\n self.Init.shellVersion = data.shellVersion;\r\n\r\n // default is 1.0.0 and Windows which indicate it's running legacy GW.\r\n self.Init.gatewayApiVersion = data.gatewayApiVersion ?? '1.0.0',\r\n self.Init.gatewayPlatform = data.gatewayPlatform ?? 'Windows';\r\n self.Environment.modules = data.modules;\r\n self.Init.connectivityLevel = data.connectivityLevel;\r\n self.Resources.lib = data.lib;\r\n self.Resources.moduleAssets = data.moduleAssets;\r\n\r\n if (!MsftSme.isNullOrUndefined(self.Resources.accessibilityMode)\r\n && !MsftSme.isNullOrUndefined(data.accessibilityMode)\r\n && CoreEnvironment.accessibilityManager) {\r\n self.Resources.accessibilityMode = data.accessibilityMode;\r\n CoreEnvironment.accessibilityManager.changeAccessibilityMode(self.Resources.accessibilityMode);\r\n }\r\n\r\n // ensure that global environment settings persist across origins\r\n if (!MsftSme.isNullOrUndefined(data.consoleDebug) && MsftSme.consoleDebug() !== data.consoleDebug) {\r\n MsftSme.consoleDebug(data.consoleDebug);\r\n }\r\n\r\n if (!MsftSme.isNullOrUndefined(data.sideLoad)) {\r\n const sideLoadKeys = Object.keys(MsftSme.sideLoad() || {});\r\n const dataSideLoadKeys = Object.keys(data.sideLoad || {});\r\n\r\n if (sideLoadKeys.length !== dataSideLoadKeys.length || sideLoadKeys.some(key => !!data.sideLoad[key])) {\r\n MsftSme.sideLoadReset();\r\n dataSideLoadKeys.forEach(k => MsftSme.sideLoad(k));\r\n }\r\n }\r\n\r\n if (!MsftSme.isNullOrUndefined(data.experiments)) {\r\n const experiments = MsftSme.experiments();\r\n if (experiments.length !== data.experiments.length || experiments.some((v, i) => v !== data.experiments[i])) {\r\n MsftSme.experiments(data.experiments);\r\n }\r\n }\r\n\r\n if (CoreEnvironment.assetManager && data.theme && data.assets) {\r\n CoreEnvironment.assetManager.loadAssets(data.theme, data.assets);\r\n }\r\n\r\n for (const item of data.modules) {\r\n // NOTES: the next 'if' block code can be removed only if all extensions adapted newer shell. (after 1.1114.0)\r\n if (!self.Init.shellVersion && item.name === 'msft.sme.shell-extensions') {\r\n // look for shell version if missing from older MSI/ShellUI.\r\n self.Init.shellVersion = item.version;\r\n }\r\n\r\n if (item.name === self.Init.moduleName) {\r\n self.Environment.version = item.version || self.Environment.version;\r\n }\r\n }\r\n\r\n const localeLoader = CoreEnvironment.moduleLoadLocale({ id: data.localeRegional || data.locale, neutral: data.locale });\r\n const passingData = <RpcInitData>{\r\n locale: data.locale,\r\n localeRegional: data.localeRegional,\r\n sessionId: data.sessionId\r\n };\r\n\r\n // update metaTags so sessionId is properly updated in telemetry\r\n SmeWebTelemetry.updateFromRpcInit({ 'wac-session-id': data.sessionId, 'wac-extension-version': self.Environment.version });\r\n\r\n return localeLoader\r\n .then(() => this.seekShell(RpcSeekMode.Create))\r\n .then(() => handler(passingData))\r\n .then(() => ({ version: rpcVersion }));\r\n };\r\n this.rpcManager.rpcInbound.register(RpcOutboundCommands[command], modifiedHandler);\r\n } else {\r\n this.rpcManager.rpcInbound.register(RpcOutboundCommands[command], handler);\r\n }\r\n }\r\n\r\n /**\r\n * Module report a failure.\r\n */\r\n public failed(data: any): Promise<void> {\r\n const rpc = this.rpcManager.rpcInbound;\r\n return rpc.failed(data);\r\n }\r\n\r\n /**\r\n * Seek shell frame.\r\n *\r\n * @param Promise<any> the promise object.\r\n */\r\n public seekShell(mode: RpcSeekMode): Promise<RpcSeekResult> {\r\n return this.rpcManager.seekShell(mode);\r\n }\r\n\r\n /**\r\n * Validate existing outbound connection and remove if it doesn't live anymore.\r\n *\r\n * @return number the count of removed outbound.\r\n */\r\n public validate(): number {\r\n let count = 0;\r\n const collection = this.rpcManager.getCurrentRpcOutbound();\r\n collection.forEach((rpc) => {\r\n if (!this.rpcManager.rpcChannel.validate(rpc)) {\r\n count++;\r\n }\r\n });\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Change the active status of rpc.\r\n */\r\n public changeActiveState(state: boolean): void {\r\n this.stateActiveInternal = state;\r\n this.stateChangedInternal.next(state);\r\n }\r\n\r\n /**\r\n * Create auto-failed timer promise.\r\n *\r\n * @param command the outbound command type.\r\n * @param timeoutMs the timeout milliseconds.\r\n * @param data the data context.\r\n * @return Promise<any> the promise.\r\n */\r\n private createTimerPromise<TData, TResult>(command: RpcOutboundCommands, timeoutMs: number, data: TData): Promise<TResult> {\r\n const deferred = NativeQ.defer<TResult>();\r\n this.deferredCollection[command] = <DeferredData<TData, TResult>>{ deferred: deferred, data: data };\r\n setTimeout(\r\n () => {\r\n const deferredData: DeferredData<TData, TResult> = this.deferredCollection[command];\r\n if (deferredData) {\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.RpcTimeout.message;\r\n deferredData.deferred.reject(message);\r\n delete this.deferredCollection[command];\r\n }\r\n },\r\n timeoutMs);\r\n return deferred.promise;\r\n }\r\n\r\n /**\r\n * Create promise that does not timeout.\r\n *\r\n * @param command the outbound type.\r\n * @param data the data context.\r\n * @return Promise<any> the promise.\r\n */\r\n private createPromise<TData, TResult>(command: RpcOutboundCommands, data: TData): Promise<any> {\r\n const deferred = NativeQ.defer<TResult>();\r\n this.deferredCollection[command] = <DeferredData<TData, TResult>>{ deferred: deferred, data: data };\r\n return deferred.promise;\r\n }\r\n\r\n /**\r\n * Process data pushing into next call of subject with deferred data type.\r\n *\r\n * @param command the inbound command type.\r\n * @param data the rpc data came from a module/iframe.\r\n * @return Promise the promise which receiver must settle within fixed waiting time (10 seconds)\r\n */\r\n private processNextForSubject<TData, TResult>(command: RpcInboundCommands, data: TData): Promise<TResult> {\r\n const subject = this.rpcSubjects[RpcInboundCommands[command]];\r\n if (subject.closed) {\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.RpcSubjectClosed.message;\r\n throw new Error(message.format(RpcInboundCommands[command]));\r\n }\r\n\r\n const deferredData = <DeferredData<TData, TResult>>{\r\n data: data,\r\n deferred: NativeQ.defer<TResult>()\r\n };\r\n subject.next(deferredData);\r\n return deferredData.deferred.promise;\r\n }\r\n}\r\n"]}