1 const Module = require('module');
2 import { TimerManager } from '../service/timer_manager';
3 import * as XWalkExtension from './wrt_xwalk_extension';
4 import * as vm from 'vm';
5 import { wrt } from '../browser/wrt';
6 import { DeviceAPIRouter } from '../service/device_api_router';
9 [id: string]: vm.Context;
12 interface ContextOption {
16 let sandbox: ContextMap = {};
17 let internal_handler: ContextOption = {};
18 let service_type: string = wrt.getServiceModel?.() ?? 'UI';
20 function requestStopService(id: string) {
21 console.log(`${id} will be closed`);
22 setTimeout(() => wrt.stopService(id), 500);
25 function callFunctionInContext(name: string, id: string) {
27 const script = `if (typeof ${name} === 'function') { ${name}(); }`;
28 vm.runInContext(script, sandbox[id]);
30 console.log(`${name} has exception: ${e}`);
32 requestStopService(id);
37 export function startService(id: string, filename?: string) {
38 if (sandbox[id] === undefined) {
39 XWalkExtension.initialize();
40 XWalkExtension.setRuntimeMessageHandler((type, data) => {
41 if (type === 'tizen://exit') {
42 requestStopService(id);
50 webapis: wrt.tv ? global.webapis : global.webapis = {},
52 sandbox[id].module.exports.onStop = () => {
53 callFunctionInContext('module.exports.onExit', id);
55 let ids = id.split(':');
56 let caller_app_id = ids[1] ?? '';
57 sandbox[id].webapis.getCallerAppId = () => {
60 let service_id = ids[0];
61 sandbox[id].webapis.getServiceId = () => {
64 sandbox[id].webapis.getPackageId = () => {
65 let app_info = global.tizen.application.getAppInfo(service_id);
67 return app_info.packageId;
68 return ids[0].split('.')[0];
71 if (service_type !== 'UI') {
72 const permissions = wrt.getPrivileges(id);
73 console.log(`permissions : ${permissions}`);
74 const AccessControlManager = require('../service/access_control_manager');
75 AccessControlManager.initialize(permissions, sandbox[id]);
77 for (let key in global)
78 sandbox[id][key] = global[key];
80 internal_handler[id] = {};
81 internal_handler[id].timer_manager = new TimerManager();
82 const timer_api = internal_handler[id].timer_manager.getTimerAPI();
83 for (let key in timer_api)
84 sandbox[id][key] = timer_api[key];
86 let object_list = [ 'Error', 'EvalError', 'RangeError', 'ReferenceError',
87 'SyntaxError', 'TypeError', 'URIError', 'Number', 'BigInt', 'Math', 'Date',
88 'String', 'RegExp', 'Array', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray',
89 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array', 'Float32Array',
90 'Float64Array', 'BigInt64Array', 'BigUint64Array', 'Map', 'Set', 'WeakMap',
91 'WeakSet', 'ArrayBuffer', 'DataView', 'JSON', 'Promise', 'Reflect', 'Proxy',
92 'Intl', 'WebAssembly', 'Boolean', 'Function', 'Object', 'Symbol' ];
93 for (let prop of object_list)
94 sandbox[id][prop] = global[prop];
96 let options: ContextOption = {};
98 if (service_type !== 'UI') {
99 options.filename = id;
101 let extension_resolver = function (module: any, file_path: string) {
102 console.log(`resolved path: ${file_path}`);
103 let content = (wrt.tv as NativeWRTjs.TVExtension).decryptFile(id, file_path);
106 if (content.charCodeAt(0) === 0xFEFF)
107 content = content.slice(1);
108 module._compile(content, file_path);
111 sandbox[id].require.extensions['.js.spm'] = extension_resolver;
112 sandbox[id].require.extensions['.spm'] = extension_resolver;
114 filename = wrt.getStartServiceFile(id);
115 console.log(`start global service file: ${filename}`);
117 code = `const app = require('${filename}')`;
118 if (service_type === 'DAEMON') {
119 internal_handler[id].deivce_api_router = new DeviceAPIRouter(sandbox[id]);
121 vm.runInNewContext(code, sandbox[id], options);
124 if (sandbox[id]['started'] === undefined) {
125 sandbox[id]['started'] = true;
126 sandbox[id]['stopped'] = undefined;
127 callFunctionInContext('app.onStart', id);
128 if (service_type !== 'UI')
129 wrt.finishStartingService(id);
131 console.log(id + ' service has been started.');
133 callFunctionInContext('app.onRequest', id);
136 export function stopService(id: string) {
137 console.log('stopService')
138 if (sandbox[id]['stopped']) {
139 console.log(id + ' service has been already stopped.');
143 sandbox[id]['stopped'] = true;
144 sandbox[id]['started'] = undefined;
145 callFunctionInContext('app.onStop', id);
147 internal_handler[id].timer_manager.releaseRemainingTimers();
148 for (let key in sandbox[id])
149 delete sandbox[id][key];
151 for (let key in internal_handler[id])
152 delete internal_handler[id][key];
153 delete internal_handler[id];
155 if (Object.keys(sandbox).length === 0)
156 XWalkExtension.cleanup();