From 2a4193c066ef648844cc47c7212378589fe96bef Mon Sep 17 00:00:00 2001 From: liwei Date: Tue, 29 Sep 2020 13:44:54 +0800 Subject: [PATCH 01/16] [Service] Add service type in node worker Add service type in node worker, otherwise value of "global.serviceType" is 'undefined', service app in global service cannot work well. Change-Id: I39fadd30c14b89f20b1bf817fe4d9db46f65eb44 Signed-off-by: liwei --- wrt_app/common/service_runner.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wrt_app/common/service_runner.ts b/wrt_app/common/service_runner.ts index 286297a..43681b5 100644 --- a/wrt_app/common/service_runner.ts +++ b/wrt_app/common/service_runner.ts @@ -4,6 +4,8 @@ import { DeviceAPIRouter } from '../service/device_api_router'; import { isMainThread, parentPort, workerData } from 'worker_threads'; import { wrt } from '../browser/wrt'; +global.serviceType = wrt.getServiceModel(); + function isServiceApplication() { return global.serviceType !== 'UI'; } -- 2.7.4 From 3078f777fd86b985ab96a9c806bc8f3291740320 Mon Sep 17 00:00:00 2001 From: "k2.nagaraju" Date: Wed, 30 Sep 2020 17:10:30 +0530 Subject: [PATCH 02/16] [service] Add notification xwalk extension support for service app. For alarm service webtct notification xwalk extension support is needed. updated the entry points for notification extension. Change-Id: If4857b74a5929e03c6738858e8a3a9098af90c22 Signed-off-by: k2.nagaraju --- packaging/plugins.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packaging/plugins.json b/packaging/plugins.json index 26d4f0a..7838bf7 100644 --- a/packaging/plugins.json +++ b/packaging/plugins.json @@ -74,5 +74,10 @@ "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_iotcon.so", "entry_points": ["tizen.IotconOption","tizen.Query","tizen.QueryFilter", "tizen.Representation","tizen.Response","tizen.State"] + }, + { + "name":"tizen.notification", + "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_notification.so", + "entry_points": ["tizen.StatusNotification","tizen.UserNotification", "tizen.NotificationDetailInfo"] } ] -- 2.7.4 From 962847b68a93c171a4348d0f14cbdbf2848d5a8e Mon Sep 17 00:00:00 2001 From: "k2.nagaraju" Date: Thu, 1 Oct 2020 22:52:13 +0530 Subject: [PATCH 03/16] [Service] Update app_id based on input received. If passed parameter is |false| or |undefined| then also |app_id| is updated as current app id. which is causing failure in application webtct failure. Change-Id: Id4ba0c2ea5068620c422585311cfc65ed81ad6c8 Signed-off-by: k2.nagaraju --- wrt_app/service/device_api_router.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 42a57f3..5bdb1ed 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -124,34 +124,38 @@ export class DeviceAPIRouter { } // tizen.application.getAppInfo() this.funcGetAppInfo = global.tizen.application.getAppInfo; - global.tizen.application.getAppInfo = (app_id?: string) => { - console.log(`Routing - getAppInfo()`); - if (!app_id) + global.tizen.application.getAppInfo = (...args: any[]) => { + let app_id = args[0]; + if (!args.length || args[0] === null) app_id = this.getServiceId(); + console.log(`Routing - getAppInfo()`); return this.funcGetAppInfo(app_id); } // tizen.application.getAppCerts() this.funcGetAppcerts = global.tizen.application.getAppCerts; - global.tizen.application.getAppCerts = (app_id?: string) => { - console.log(`Routing - getAppCerts()`); - if (!app_id) + global.tizen.application.getAppCerts = (...args: any[]) => { + let app_id = args[0]; + if (!args.length || args[0] === null) app_id = this.getServiceId(); + console.log(`Routing - getAppCerts() ` + app_id); return this.funcGetAppcerts(app_id); } // tizen.application.getAppSharedURI() this.funcGetSharedUri = global.tizen.application.getAppSharedURI; - global.tizen.application.getAppSharedURI = (app_id?: string) => { - console.log(`Routing - getAppSharedURI()`); - if (!app_id) + global.tizen.application.getAppSharedURI = (...args: any[]) => { + let app_id = args[0]; + if (!args.length || args[0] === null) app_id = this.getServiceId(); + console.log(`Routing - getAppSharedURI()`); return this.funcGetSharedUri(app_id); } // tizen.application.getAppMetaData() this.funcGetMetadata = global.tizen.application.getAppMetaData; - global.tizen.application.getAppMetaData = (app_id?: string) => { - console.log(`Routing - getAppMetaData()`); - if (!app_id) + global.tizen.application.getAppMetaData = (...args: any[]) => { + let app_id = args[0]; + if (!args.length || args[0] === null) app_id = this.getServiceId(); + console.log(`Routing - getAppMetaData()`); return this.funcGetMetadata(app_id); } } -- 2.7.4 From 2b011acf4a65ec8b940605ddeb53cc3709f2009d Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 28 Sep 2020 15:32:06 +0900 Subject: [PATCH 04/16] [Service] Apply node worker for standalone model This change is implemented for 1) unify source code with global model 2) isolate v8 variable scope from main thread - standalone service application cannot get main global variable of service_manaer / service_runner There is no noticeable memory increase with node worker. Change-Id: I7bb4576026ce326a3903987c537810093db028b4 Signed-off-by: DongHyun Song --- wrt_app/common/service_manager.ts | 33 +++++++-------------------------- wrt_app/service/main.ts | 3 --- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index 3038364..c4b2940 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -5,16 +5,11 @@ interface WorkerMap { [id: string]: any; } let workers: WorkerMap = {}; -let runner: any; global.serviceType = wrt.getServiceModel(); -function isStandalone() { - return global.serviceType === 'STANDALONE'; -} - -function isGlobalService() { - return global.serviceType === 'DAEMON'; +function isServiceApplication() { + return global.serviceType !== 'UI'; } function createWorker(id: string, startService: string, filename: string) { @@ -37,7 +32,7 @@ function terminateWorker(id: string, delay: number) { delete workers[id]; let runningServices = Object.keys(workers).length; console.log('Running services : ' + runningServices); - if (runningServices === 0 && isGlobalService()) { + if (runningServices === 0 && isServiceApplication()) { process.exit(); } } @@ -46,29 +41,15 @@ function terminateWorker(id: string, delay: number) { export function startService(id: string, filename: string) { console.log(`startService - ${id}`); - if (isStandalone()) { - runner = require('../common/service_runner'); - runner.start(id, filename); - } else { - if (isMainThread) { - let startService = `${__dirname}/service_runner.js`; - createWorker(id, startService, filename); - } + if (isMainThread) { + let startService = `${__dirname}/service_runner.js`; + createWorker(id, startService, filename); } } export function stopService(id: string) { console.log(`stopService - ${id}`); - if (isStandalone()) { - if (!runner) { - console.log('runner instance is null in standalone mode'); - return; - } - runner.stop(id); - setTimeout(() => process.exit(), 500); - } else { - terminateWorker(id, 500); - } + terminateWorker(id, 500); } export function handleBuiltinService(serviceId: string, serviceName: string) { diff --git a/wrt_app/service/main.ts b/wrt_app/service/main.ts index b0c371a..c64591e 100755 --- a/wrt_app/service/main.ts +++ b/wrt_app/service/main.ts @@ -27,9 +27,6 @@ wrt.on('start-service', (event: any, internal_id: string) => { wrt.on('stop-service', (event: any, internal_id: string) => { ServiceManager.stopService(internal_id); - if (wrt.getServiceModel() === 'STANDALONE') { - setTimeout(() => {process.exit()}, 10); - } }); wrt.on('builtin-service', (event: any, internal_id: string, service_name: string) => { -- 2.7.4 From 8d65e05cc5e16bc8dbf7e3c388c2a4939869b5c8 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Mon, 5 Oct 2020 03:41:42 -0700 Subject: [PATCH 05/16] [Service] Let UI service use web app privileges The UI service has used web app privileges because it resides in Web Runtime browser thread. This resolves following error: >> TypeError: wrt_1.wrt.getPrivileges is not a function Change-Id: I3258513a88b4ae34604ee41b57ac56828656b3ae Signed-off-by: Youngsoo Choi --- wrt_app/service/device_api_router.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 5bdb1ed..09bb5af 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -22,10 +22,11 @@ export class DeviceAPIRouter { this.serviceId = ids[0]; this.callerAppId = ids[1] ?? ''; this.packageId = this.serviceId.split('.')[0]; - this.permissions = wrt.getPrivileges(this.id); + this.permissions = []; this.initWebapis(); if (isGlobal) { + this.permissions = wrt.getPrivileges(this.id); this.refineApplicationApis(); this.refinePackageApis(); this.refineFilesystemApis() -- 2.7.4 From f4e898db8745fd155bce9a03aa9f1bbdc4688d45 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Tue, 6 Oct 2020 02:32:50 -0700 Subject: [PATCH 06/16] [Service] Make application.getAppContext work This makes service app have its own service app id from application.getAppContext(), not 'org.tizen.chromium-efl.wrt-service'. Change-Id: I7378802cc61ea42e2b79559e0d83526d7da665dd Signed-off-by: Youngsoo Choi --- wrt_app/service/device_api_router.ts | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 09bb5af..5c39392 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -6,6 +6,7 @@ export class DeviceAPIRouter { funcRequestedAppcontrol: any; funcGetAppInfo: any; funcGetAppcerts: any; + funcGetContext: any; funcGetSharedUri: any; funcGetMetadata: any; funcGetPackageInfo: any; @@ -105,6 +106,10 @@ export class DeviceAPIRouter { return global.webapis.getPackageId(); } + hasNoneOrNull(...args: any[]) { + return !args.length || null === args[0]; + } + refineApplicationApis() { // tizen.application.getCurrentApplication() this.funcCurrentApplication = global.tizen.application.getCurrentApplication; @@ -127,7 +132,7 @@ export class DeviceAPIRouter { this.funcGetAppInfo = global.tizen.application.getAppInfo; global.tizen.application.getAppInfo = (...args: any[]) => { let app_id = args[0]; - if (!args.length || args[0] === null) + if (this.hasNoneOrNull(args)) app_id = this.getServiceId(); console.log(`Routing - getAppInfo()`); return this.funcGetAppInfo(app_id); @@ -136,16 +141,28 @@ export class DeviceAPIRouter { this.funcGetAppcerts = global.tizen.application.getAppCerts; global.tizen.application.getAppCerts = (...args: any[]) => { let app_id = args[0]; - if (!args.length || args[0] === null) + if (this.hasNoneOrNull(args)) app_id = this.getServiceId(); console.log(`Routing - getAppCerts() ` + app_id); return this.funcGetAppcerts(app_id); } + // tizen.application.getAppContext() + this.funcGetContext = global.tizen.application.getAppContext; + global.tizen.application.getAppContext = (...args: any[]) => { + console.log(`Routing - getAppContext()`); + if (this.hasNoneOrNull(args)) { + const context = {"id": this.funcGetContext().id, "appId": this.getServiceId()}; + Object.defineProperty(context, 'appId', { writable: false }); + Object.defineProperty(context, 'id', { writable: false }); + return context; + } + return this.funcGetContext(args[0]); + } // tizen.application.getAppSharedURI() this.funcGetSharedUri = global.tizen.application.getAppSharedURI; global.tizen.application.getAppSharedURI = (...args: any[]) => { let app_id = args[0]; - if (!args.length || args[0] === null) + if (this.hasNoneOrNull(args)) app_id = this.getServiceId(); console.log(`Routing - getAppSharedURI()`); return this.funcGetSharedUri(app_id); @@ -154,7 +171,7 @@ export class DeviceAPIRouter { this.funcGetMetadata = global.tizen.application.getAppMetaData; global.tizen.application.getAppMetaData = (...args: any[]) => { let app_id = args[0]; - if (!args.length || args[0] === null) + if (this.hasNoneOrNull(args)) app_id = this.getServiceId(); console.log(`Routing - getAppMetaData()`); return this.funcGetMetadata(app_id); @@ -166,7 +183,7 @@ export class DeviceAPIRouter { this.funcGetPackageInfo = global.tizen.package.getPackageInfo; global.tizen.package.getPackageInfo = (...args: any[]) => { let package_id = args[0]; - if (!args.length || args[0] === null) + if (this.hasNoneOrNull(args)) package_id = this.getPackageId(); console.log(`Routing - getPackageInfo() : ${package_id}`); return this.funcGetPackageInfo(package_id); -- 2.7.4 From 01d19cab2e3a12bea61796dcadbddb6092ccc5cc Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Wed, 7 Oct 2020 01:08:49 -0700 Subject: [PATCH 07/16] fixup! [Service] Make application.getAppContext work This changes arguments with array. Change-Id: I4f729b560b581a94c6f2ce1a914baf0bece55038 Signed-off-by: Youngsoo Choi --- wrt_app/service/device_api_router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 5c39392..a9cbdde 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -106,7 +106,7 @@ export class DeviceAPIRouter { return global.webapis.getPackageId(); } - hasNoneOrNull(...args: any[]) { + hasNoneOrNull(args: any[]) { return !args.length || null === args[0]; } -- 2.7.4 From de7f2584aaeca8fa264bd539a5be2cb938fe83d9 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Wed, 7 Oct 2020 21:43:49 -0700 Subject: [PATCH 08/16] [Service] Make application.getCurrentApplication work The appInfo.id of application.getCurrentApplication() should be its own service id, not 'org.tizen.chromium-efl.wrt-service'. The object returned from application.getCurrentApplication() is non re-writable. So, new object is needed to modify the id. Btw, broadcast APIs need to have daemon id because they are working on app id of current process. Change-Id: I71a62f9dc0bccd68fa7e2b9269a2543e651ec64a Signed-off-by: Youngsoo Choi --- wrt_app/service/device_api_router.ts | 42 +++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index a9cbdde..4ccf2ef 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -117,7 +117,41 @@ export class DeviceAPIRouter { console.log(`Routing - getCurrentApplication() : ${this.getServiceId()}`); if (this.currentApplication) return this.currentApplication; - this.currentApplication = this.funcCurrentApplication(); + this.currentApplication = {}; + const originCurrentApplication = this.funcCurrentApplication(); + for (let key in originCurrentApplication) { + if (key === 'appInfo') { + this.currentApplication.appInfo = {}; + for (let key in originCurrentApplication.appInfo) { + if (key === 'id') { + this.currentApplication.appInfo[key] = this.getServiceId(); + } else { + this.currentApplication.appInfo[key] = originCurrentApplication.appInfo[key]; + } + } + } else { + if (key === 'broadcastEvent' || key === 'broadcastTrustedEvent') { + this.currentApplication[key] = originCurrentApplication[key].bind(originCurrentApplication); + } else { + this.currentApplication[key] = originCurrentApplication[key]; + } + } + } + Object.defineProperties(this.currentApplication.appInfo, { + categories: { writable: false, enumerable: true }, + iconPath: { writable: false, enumerable: true }, + id: { writable: false, enumerable: true }, + installDate: { writable: false, enumerable: true }, + name: { writable: false, enumerable: true }, + packageId: { writable: false, enumerable: true }, + show: { writable: false, enumerable: true }, + size: { enumerable: true }, + version: { writable: false, enumerable: true } + }); + Object.defineProperties(this.currentApplication, { + appInfo: { writable: false, enumerable: true }, + contextId: { writable: false, enumerable: true } + }); // tizen.application.getCurrentApplication().getRequestedAppControl() this.funcRequestedAppcontrol = this.currentApplication.getRequestedAppControl; this.currentApplication.getRequestedAppControl = () => { @@ -152,8 +186,10 @@ export class DeviceAPIRouter { console.log(`Routing - getAppContext()`); if (this.hasNoneOrNull(args)) { const context = {"id": this.funcGetContext().id, "appId": this.getServiceId()}; - Object.defineProperty(context, 'appId', { writable: false }); - Object.defineProperty(context, 'id', { writable: false }); + Object.defineProperties(context, { + appId: { writable: false, enumerable: true }, + id: { writable: false, enumerable: true } + }); return context; } return this.funcGetContext(args[0]); -- 2.7.4 From dd79b18738cdb66f003a5195e78b5ff03248e27e Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Tue, 13 Oct 2020 10:20:10 +0900 Subject: [PATCH 09/16] [Service] Refactor stop service sequence When service application needs to terminate by tizen://exit, it should call wrt.stopService(id). However, it is called in worker thread with standalone model, WRTServiceManager::Remove() will be handled in worker thread, not main thread. then, uv loop sometimes makes abort() or get SIGSEGV. Then, wrt.stopService(id) should be called in main thread side. Change-Id: I103bf8f38111db984bb22d0af56c05456851b681 Signed-off-by: DongHyun Song --- wrt_app/common/service_manager.ts | 15 ++++++++++++--- wrt_app/common/service_runner.ts | 11 ++++++++--- wrt_app/service/builtins/wasm_builder.ts | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index c4b2940..beb3d6e 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -43,7 +43,13 @@ export function startService(id: string, filename: string) { console.log(`startService - ${id}`); if (isMainThread) { let startService = `${__dirname}/service_runner.js`; - createWorker(id, startService, filename); + let worker = createWorker(id, startService, filename); + worker.on('message', (message: any) => { + if (message.type === 'stop') { + console.log(`${id} will shutdown after ${message.delay}ms`); + setTimeout(() => wrt.stopService(id), message.delay); + } + }); } } @@ -64,8 +70,11 @@ export function handleBuiltinService(serviceId: string, serviceName: string) { console.log(`Builtin service is ${serviceName}`); let startService = `${__dirname}/../service/builtins/${serviceName}.js`; let worker = createWorker(serviceId, startService, ''); - worker.on('stop', () => { - terminateWorker(serviceId, 0); + worker.on('message', (message: any) => { + if (message.type === 'stop') { + console.log(`${serviceName} built-in service will be stopped`); + terminateWorker(serviceId, message.delay); + } }); } } diff --git a/wrt_app/common/service_runner.ts b/wrt_app/common/service_runner.ts index 43681b5..c86829c 100644 --- a/wrt_app/common/service_runner.ts +++ b/wrt_app/common/service_runner.ts @@ -31,13 +31,18 @@ function registerExtensionResolver(id: string) { } } +function requestStopService(delay: number) { + if (parentPort) { + parentPort.postMessage({type: 'stop', delay: delay}); + } +} + let app: any = null; export function start(id: string, filename: string) { XWalkExtension.initialize(); XWalkExtension.setRuntimeMessageHandler((type, data) => { if (type === 'tizen://exit') { - console.log(`${id} will be closed by ${type}`); - setTimeout(() => wrt.stopService(id), 500); + requestStopService(500); } }); @@ -66,7 +71,7 @@ export function start(id: string, filename: string) { } } catch (e) { console.log(`exception on start: ${e}`); - setTimeout(() => wrt.stopService(id), 500); + requestStopService(500); } } diff --git a/wrt_app/service/builtins/wasm_builder.ts b/wrt_app/service/builtins/wasm_builder.ts index 7ec30a3..6f6c5b1 100644 --- a/wrt_app/service/builtins/wasm_builder.ts +++ b/wrt_app/service/builtins/wasm_builder.ts @@ -26,7 +26,7 @@ export function run(app_id: string) { compileWasmForCaching(file_path); }); if (parentPort) { - parentPort.postMessage('stop'); + parentPort.postMessage({type: 'stop', delay: 0}); } } -- 2.7.4 From 12ff1412f2c81ffce556a1ad5756d42996434898 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Tue, 13 Oct 2020 08:14:25 +0000 Subject: [PATCH 10/16] Revert "[Service] Refactor stop service sequence" This reverts commit dd79b18738cdb66f003a5195e78b5ff03248e27e. Change-Id: If6ff1a847e9aeed86faf9fd9fc014971c339096f --- wrt_app/common/service_manager.ts | 15 +++------------ wrt_app/common/service_runner.ts | 11 +++-------- wrt_app/service/builtins/wasm_builder.ts | 2 +- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index beb3d6e..c4b2940 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -43,13 +43,7 @@ export function startService(id: string, filename: string) { console.log(`startService - ${id}`); if (isMainThread) { let startService = `${__dirname}/service_runner.js`; - let worker = createWorker(id, startService, filename); - worker.on('message', (message: any) => { - if (message.type === 'stop') { - console.log(`${id} will shutdown after ${message.delay}ms`); - setTimeout(() => wrt.stopService(id), message.delay); - } - }); + createWorker(id, startService, filename); } } @@ -70,11 +64,8 @@ export function handleBuiltinService(serviceId: string, serviceName: string) { console.log(`Builtin service is ${serviceName}`); let startService = `${__dirname}/../service/builtins/${serviceName}.js`; let worker = createWorker(serviceId, startService, ''); - worker.on('message', (message: any) => { - if (message.type === 'stop') { - console.log(`${serviceName} built-in service will be stopped`); - terminateWorker(serviceId, message.delay); - } + worker.on('stop', () => { + terminateWorker(serviceId, 0); }); } } diff --git a/wrt_app/common/service_runner.ts b/wrt_app/common/service_runner.ts index c86829c..43681b5 100644 --- a/wrt_app/common/service_runner.ts +++ b/wrt_app/common/service_runner.ts @@ -31,18 +31,13 @@ function registerExtensionResolver(id: string) { } } -function requestStopService(delay: number) { - if (parentPort) { - parentPort.postMessage({type: 'stop', delay: delay}); - } -} - let app: any = null; export function start(id: string, filename: string) { XWalkExtension.initialize(); XWalkExtension.setRuntimeMessageHandler((type, data) => { if (type === 'tizen://exit') { - requestStopService(500); + console.log(`${id} will be closed by ${type}`); + setTimeout(() => wrt.stopService(id), 500); } }); @@ -71,7 +66,7 @@ export function start(id: string, filename: string) { } } catch (e) { console.log(`exception on start: ${e}`); - requestStopService(500); + setTimeout(() => wrt.stopService(id), 500); } } diff --git a/wrt_app/service/builtins/wasm_builder.ts b/wrt_app/service/builtins/wasm_builder.ts index 6f6c5b1..7ec30a3 100644 --- a/wrt_app/service/builtins/wasm_builder.ts +++ b/wrt_app/service/builtins/wasm_builder.ts @@ -26,7 +26,7 @@ export function run(app_id: string) { compileWasmForCaching(file_path); }); if (parentPort) { - parentPort.postMessage({type: 'stop', delay: 0}); + parentPort.postMessage('stop'); } } -- 2.7.4 From a3646fe3fdc71541b00cf057feb2a8a46e346f48 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Tue, 13 Oct 2020 08:14:52 +0000 Subject: [PATCH 11/16] Revert "[Service] Apply node worker for standalone model" This reverts commit 2b011acf4a65ec8b940605ddeb53cc3709f2009d. Change-Id: I4203e460734b8befd84a2286663ae6c41a7b3232 --- wrt_app/common/service_manager.ts | 33 ++++++++++++++++++++++++++------- wrt_app/service/main.ts | 3 +++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index c4b2940..3038364 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -5,11 +5,16 @@ interface WorkerMap { [id: string]: any; } let workers: WorkerMap = {}; +let runner: any; global.serviceType = wrt.getServiceModel(); -function isServiceApplication() { - return global.serviceType !== 'UI'; +function isStandalone() { + return global.serviceType === 'STANDALONE'; +} + +function isGlobalService() { + return global.serviceType === 'DAEMON'; } function createWorker(id: string, startService: string, filename: string) { @@ -32,7 +37,7 @@ function terminateWorker(id: string, delay: number) { delete workers[id]; let runningServices = Object.keys(workers).length; console.log('Running services : ' + runningServices); - if (runningServices === 0 && isServiceApplication()) { + if (runningServices === 0 && isGlobalService()) { process.exit(); } } @@ -41,15 +46,29 @@ function terminateWorker(id: string, delay: number) { export function startService(id: string, filename: string) { console.log(`startService - ${id}`); - if (isMainThread) { - let startService = `${__dirname}/service_runner.js`; - createWorker(id, startService, filename); + if (isStandalone()) { + runner = require('../common/service_runner'); + runner.start(id, filename); + } else { + if (isMainThread) { + let startService = `${__dirname}/service_runner.js`; + createWorker(id, startService, filename); + } } } export function stopService(id: string) { console.log(`stopService - ${id}`); - terminateWorker(id, 500); + if (isStandalone()) { + if (!runner) { + console.log('runner instance is null in standalone mode'); + return; + } + runner.stop(id); + setTimeout(() => process.exit(), 500); + } else { + terminateWorker(id, 500); + } } export function handleBuiltinService(serviceId: string, serviceName: string) { diff --git a/wrt_app/service/main.ts b/wrt_app/service/main.ts index c64591e..b0c371a 100755 --- a/wrt_app/service/main.ts +++ b/wrt_app/service/main.ts @@ -27,6 +27,9 @@ wrt.on('start-service', (event: any, internal_id: string) => { wrt.on('stop-service', (event: any, internal_id: string) => { ServiceManager.stopService(internal_id); + if (wrt.getServiceModel() === 'STANDALONE') { + setTimeout(() => {process.exit()}, 10); + } }); wrt.on('builtin-service', (event: any, internal_id: string, service_name: string) => { -- 2.7.4 From 8b7fec189a3c571f4b56ff318b51c7f18cd21651 Mon Sep 17 00:00:00 2001 From: liwei Date: Mon, 28 Sep 2020 15:35:21 +0800 Subject: [PATCH 12/16] [Service][TV] Support more webapis.productinfo Support webapis.productinfo.is8KPanelSupported() / isUHDAModel() / getSmartTVServerType() / isWallModel() Native Patch: https://review.tizen.org/gerrit/244962/ Change-Id: Icdd34cf44338a8d5b92bfad1c98cd96b07309b4a Signed-off-by: liwei --- wrt_app/service/device_api_router.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 4ccf2ef..8884fb3 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -87,8 +87,26 @@ export class DeviceAPIRouter { }, getSmartTVServerVersion: () => { return getCachedValue('getSmartTVServerVersion'); + }, + getSmartTVServerType: () => { + return Number(getCachedValue('getSmartTVServerType')); + }, + isWallModel: () => { + return (getCachedValue('isWallModel') === 'true'); + }, + isUHDAModel: () => { + return (getCachedValue('isUHDAModel') === 'true'); + }, + is8KPanelSupported: () => { + return (getCachedValue('is8KPanelSupported') === 'true'); } }; + + global.webapis.productinfo.ProductInfoSiServerType = { + SI_TYPE_OPERATIING_SERVER: 0, + SI_TYPE_DEVELOPMENT_SERVER: 1, + SI_TYPE_DEVELOPING_SERVER: 2 + }; } } -- 2.7.4 From 25de0d7b52383ecec883b6b88be004d269edf2ed Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Mon, 19 Oct 2020 05:11:03 -0700 Subject: [PATCH 13/16] [Service] Make appInfo writable In follwing sample code, The appInfo needs to be writable with application information having app id 'TCT_APPCONTROL_APPID' as TC expected. > var app = tizen.application.getCurrentApplication(); > app.appInfo = > tizen.application.getAppInfo(application_common.TCT_APPCONTROL_APPID); Change-Id: I6d89d5d1c0d9c241cebc5ff92b15167c890f1a55 Signed-off-by: Youngsoo Choi --- wrt_app/service/device_api_router.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 4ccf2ef..546c3a4 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -149,7 +149,7 @@ export class DeviceAPIRouter { version: { writable: false, enumerable: true } }); Object.defineProperties(this.currentApplication, { - appInfo: { writable: false, enumerable: true }, + appInfo: { enumerable: true }, contextId: { writable: false, enumerable: true } }); // tizen.application.getCurrentApplication().getRequestedAppControl() @@ -168,7 +168,7 @@ export class DeviceAPIRouter { let app_id = args[0]; if (this.hasNoneOrNull(args)) app_id = this.getServiceId(); - console.log(`Routing - getAppInfo()`); + console.log(`Routing - getAppInfo(${app_id})`); return this.funcGetAppInfo(app_id); } // tizen.application.getAppCerts() -- 2.7.4 From bc1291eeb6f7ae34a867faf97b04e01ed05e1233 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Tue, 13 Oct 2020 19:03:27 +0900 Subject: [PATCH 14/16] [Service][Reland] Apply node worker for standalone model This patch includes below, 1) unify source code with global model. 2) isolate v8 variable scope from main thread. - standalone service application cannot get main global variable. of service_manaer / service_runner 3) refactor handling message with node worker. 4) refactor termination sequence of node worker more gracefully. - process.exit() is invoked by worker side - parent handles on('exit') for clean-up Additionally, there is no noticeable memory increase with node worker. References: https://review.tizen.org/gerrit/244938/ https://review.tizen.org/gerrit/245591/ Change-Id: Ie9c17b373a69585ca755e39c4ab56243406821a2 Signed-off-by: DongHyun Song --- wrt_app/common/service_manager.ts | 77 ++++++++++++-------------------- wrt_app/common/service_runner.ts | 30 ++++++++----- wrt_app/service/builtins/wasm_builder.ts | 22 +++++---- wrt_app/service/main.ts | 6 +-- 4 files changed, 60 insertions(+), 75 deletions(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index 3038364..b48f2d4 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -5,25 +5,34 @@ interface WorkerMap { [id: string]: any; } let workers: WorkerMap = {}; -let runner: any; -global.serviceType = wrt.getServiceModel(); +Object.defineProperty(global, 'serviceType', { + value: wrt.getServiceModel(), + writable: false +}); -function isStandalone() { - return global.serviceType === 'STANDALONE'; -} - -function isGlobalService() { - return global.serviceType === 'DAEMON'; +function isServiceApplication() { + return global['serviceType'] !== 'UI'; } function createWorker(id: string, startService: string, filename: string) { - return workers[id] ?? (workers[id] = new Worker(startService, { + if (workers[id]) + return; + + workers[id] = new Worker(startService, { workerData: { id, filename } - })); + }); + workers[id].on('exit', (code: number) => { + delete workers[id]; + let runningServices = Object.keys(workers).length; + console.log(`exit code(${code}), remain services(${runningServices})`); + if (runningServices === 0 && isServiceApplication()) { + setTimeout(() => process.exit(), 500); + } + }); } function terminateWorker(id: string, delay: number) { @@ -31,44 +40,19 @@ function terminateWorker(id: string, delay: number) { console.log(`This worker is already terminated. ${id}`); return; } - workers[id].postMessage('stopService'); - let terminate = () => { - workers[id].terminate(); - delete workers[id]; - let runningServices = Object.keys(workers).length; - console.log('Running services : ' + runningServices); - if (runningServices === 0 && isGlobalService()) { - process.exit(); - } - } - setTimeout(() => terminate(), delay); + console.log(`${id} will shutdown after ${delay}ms`); + workers[id].postMessage({ type: 'stop', delay }); } export function startService(id: string, filename: string) { console.log(`startService - ${id}`); - if (isStandalone()) { - runner = require('../common/service_runner'); - runner.start(id, filename); - } else { - if (isMainThread) { - let startService = `${__dirname}/service_runner.js`; - createWorker(id, startService, filename); - } - } + let startService = `${__dirname}/service_runner.js`; + createWorker(id, startService, filename); } export function stopService(id: string) { console.log(`stopService - ${id}`); - if (isStandalone()) { - if (!runner) { - console.log('runner instance is null in standalone mode'); - return; - } - runner.stop(id); - setTimeout(() => process.exit(), 500); - } else { - terminateWorker(id, 500); - } + terminateWorker(id, 500); } export function handleBuiltinService(serviceId: string, serviceName: string) { @@ -77,15 +61,10 @@ export function handleBuiltinService(serviceId: string, serviceName: string) { } let need_stop = (serviceName.substr(0, 5) === 'stop_'); if (need_stop) { - terminateWorker(serviceId, 0); + workers[serviceId].terminate(); } else { - if (isMainThread) { - console.log(`Builtin service is ${serviceName}`); - let startService = `${__dirname}/../service/builtins/${serviceName}.js`; - let worker = createWorker(serviceId, startService, ''); - worker.on('stop', () => { - terminateWorker(serviceId, 0); - }); - } + console.log(`Builtin service is ${serviceName}`); + let startService = `${__dirname}/../service/builtins/${serviceName}.js`; + createWorker(serviceId, startService, ''); } } \ No newline at end of file diff --git a/wrt_app/common/service_runner.ts b/wrt_app/common/service_runner.ts index 43681b5..c3c8306 100644 --- a/wrt_app/common/service_runner.ts +++ b/wrt_app/common/service_runner.ts @@ -4,14 +4,17 @@ import { DeviceAPIRouter } from '../service/device_api_router'; import { isMainThread, parentPort, workerData } from 'worker_threads'; import { wrt } from '../browser/wrt'; -global.serviceType = wrt.getServiceModel(); +Object.defineProperty(global, 'serviceType', { + value: wrt.getServiceModel(), + writable: false +}); function isServiceApplication() { - return global.serviceType !== 'UI'; + return global['serviceType'] !== 'UI'; } function isGlobalService() { - return global.serviceType === 'DAEMON'; + return global['serviceType'] === 'DAEMON'; } function registerExtensionResolver(id: string) { @@ -31,17 +34,21 @@ function registerExtensionResolver(id: string) { } } +function requestStopService(id: string) { + setTimeout(() => wrt.stopService(id), 500); +} + let app: any = null; export function start(id: string, filename: string) { XWalkExtension.initialize(); XWalkExtension.setRuntimeMessageHandler((type, data) => { if (type === 'tizen://exit') { console.log(`${id} will be closed by ${type}`); - setTimeout(() => wrt.stopService(id), 500); + requestStopService(id); } }); - console.log(`serviceType : ${global.serviceType}`) + console.log(`serviceType : ${global['serviceType']}`) new DeviceAPIRouter(id, isGlobalService()); if (isServiceApplication()) { @@ -66,7 +73,7 @@ export function start(id: string, filename: string) { } } catch (e) { console.log(`exception on start: ${e}`); - setTimeout(() => wrt.stopService(id), 500); + requestStopService(id); } } @@ -89,11 +96,14 @@ function run() { if (!parentPort) return; - parentPort.on('message', (msg) => { - console.log(`message received : ${msg}`); - if (msg === 'stopService') { + parentPort.on('message', (message) => { + console.log(`Received message type : ${message.type}`); + if (message.type === 'stop') { stop(id); - XWalkExtension.cleanup(); + setTimeout(() => { + XWalkExtension.cleanup(); + process.exit() + }, message.delay); } }); } diff --git a/wrt_app/service/builtins/wasm_builder.ts b/wrt_app/service/builtins/wasm_builder.ts index 7ec30a3..54177d0 100644 --- a/wrt_app/service/builtins/wasm_builder.ts +++ b/wrt_app/service/builtins/wasm_builder.ts @@ -3,12 +3,14 @@ import { isMainThread, parentPort, workerData } from 'worker_threads'; import { wrt } from '../../browser/wrt'; import * as fs from 'fs'; -async function compileWasmForCaching(file_path: string) { - console.log(`Requesting WASM compilation for building a cache, file_path:(${file_path})`); +function compileWasmForCaching(files: string[]) { try { - let source = fs.readFileSync(file_path); - let file = new Uint8Array(source); - await WebAssembly.compile(file); + files.forEach(async file_path => { + console.log(`Requesting WASM compilation for building a cache, file_path:(${file_path})`); + let source = fs.readFileSync(file_path); + let file = new Uint8Array(source); + await WebAssembly.compile(file); + }); } catch (e) { console.error(`An error occurred while compiling a wasm module. error:(${e})`); } @@ -21,13 +23,9 @@ export function run(app_id: string) { tv.setDiskCache(app_id); let files = tv.getWasmFiles(app_id); console.log(files); - files.forEach((file_path: string) => { - tv.delayShutdown(); - compileWasmForCaching(file_path); - }); - if (parentPort) { - parentPort.postMessage('stop'); - } + tv.delayShutdown(); + compileWasmForCaching(files); + process.exit(); } if (!isMainThread) { diff --git a/wrt_app/service/main.ts b/wrt_app/service/main.ts index b0c371a..6e6c222 100755 --- a/wrt_app/service/main.ts +++ b/wrt_app/service/main.ts @@ -21,15 +21,13 @@ import { wrt } from '../browser/wrt'; import * as ServiceManager from '../common/service_manager'; wrt.on('start-service', (event: any, internal_id: string) => { - console.log('start service app : ' + internal_id); + console.log(`start service app : ${internal_id}`); ServiceManager.startService(internal_id, ''); }); wrt.on('stop-service', (event: any, internal_id: string) => { + console.log(`stop service app : ${internal_id}`); ServiceManager.stopService(internal_id); - if (wrt.getServiceModel() === 'STANDALONE') { - setTimeout(() => {process.exit()}, 10); - } }); wrt.on('builtin-service', (event: any, internal_id: string, service_name: string) => { -- 2.7.4 From f4efaad9398a07f2d1716a806fdc7d8a6578d196 Mon Sep 17 00:00:00 2001 From: "k2.nagaraju" Date: Mon, 19 Oct 2020 21:05:06 +0530 Subject: [PATCH 15/16] [Service] Exception is throwing if argument length is 0 Calling |resolveVirtualRoot| with |0| parameter throwing exception, which is causing failure in service filesystem webtct. Change-Id: I5e8d54f916d408145331066b31f7432ad7a3be55 Signed-off-by: k2.nagaraju --- wrt_app/service/device_api_router.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 4ccf2ef..7d08190 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -228,9 +228,11 @@ export class DeviceAPIRouter { injectVirtualRootResolver(func: Function) { return (...args: any[]) => { - console.log(args); - args[0] = wrt.resolveVirtualRoot(this.getServiceId(), args[0]); - console.log(args[0]); + console.log('arguments : ' + args); + if (args.length && !(args[0] === null || args[0] === undefined)) { + args[0] = wrt.resolveVirtualRoot(this.getServiceId(), args[0]); + console.log('updated argument[0] : ' + args[0]); + } return func.apply(global.tizen.filesystem, args); } } @@ -239,7 +241,6 @@ export class DeviceAPIRouter { global.tizen.filesystem.resolve = this.injectVirtualRootResolver(global.tizen.filesystem.resolve); global.tizen.filesystem.listDirectory = this.injectVirtualRootResolver(global.tizen.filesystem.listDirectory); global.tizen.filesystem.createDirectory = this.injectVirtualRootResolver(global.tizen.filesystem.createDirectory); - global.tizen.filesystem.createDirectory = this.injectVirtualRootResolver(global.tizen.filesystem.createDirectory); global.tizen.filesystem.deleteDirectory = this.injectVirtualRootResolver(global.tizen.filesystem.deleteDirectory); global.tizen.filesystem.openFile = this.injectVirtualRootResolver(global.tizen.filesystem.openFile); global.tizen.filesystem.deleteFile = this.injectVirtualRootResolver(global.tizen.filesystem.deleteFile); -- 2.7.4 From ba115a874e610dc86953a45ef7da2b0627412e46 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Thu, 22 Oct 2020 14:15:08 +0900 Subject: [PATCH 16/16] Refactor suspend sequence 1) Bring forward suspend time when before-quit. ** When OnTerminate is coming first earlier than OnPause, 'quit' makes this.webApplication as undefined, then wrt.on('suspend'...) will be skipped. This means that With normal termination sequence, suspending might be not handled. 2) Even though background runnable app, when app is in quitting, enable suspend sequence for right termination sequence. Change-Id: Ie40f650ea317d6f198f9c1c1aa07c9bc6867b693 Signed-off-by: DongHyun Song --- wrt_app/src/web_application.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wrt_app/src/web_application.ts b/wrt_app/src/web_application.ts index 61bbfd7..3e5a683 100644 --- a/wrt_app/src/web_application.ts +++ b/wrt_app/src/web_application.ts @@ -44,6 +44,7 @@ export class WebApplication { runningStatus = 'none'; suspended = false; windowList: Electron.BrowserWindow[] = []; + inQuit = false; constructor(options: RuntimeOption) { if (options.launchMode == 'backgroundAtStartup') { @@ -344,12 +345,14 @@ Then you can get profile log from the initial loading.`; } suspend() { + if (this.suspended) + return; console.log('WebApplication : suspend'); addonManager.emit('lcSuspend', this.mainWindow.id); this.suspended = true; this.windowList[this.windowList.length - 1].hide(); this.flushData(); - if (!this.backgroundRunnable()) { + if (!this.backgroundRunnable() || this.inQuit) { if (!this.multitaskingSupport) { // FIXME : terminate app after visibilitychange event handling setTimeout(() => { @@ -394,6 +397,9 @@ Then you can get profile log from the initial loading.`; quit() { console.log('WebApplication : quit'); addonManager.emit('lcQuit', this.mainWindow.id); + this.inQuit = true; + if (!this.suspended) + this.suspend(); } private flushData() { -- 2.7.4