From 05fa491405a2c70ee695c89d06817197dcc5bab6 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Tue, 29 Sep 2020 11:47:49 +0900 Subject: [PATCH 01/16] Remove wrt.tv.flushCookie() flushCookie() will be called on WRTCookieManager's dtor. flushStorageData() is applied for all profile. Related chromium-efl patch: https://review.tizen.org/gerrit/245001/ Change-Id: Ic339b7d639c76dd5829c1a8f0ba0bd1d24941823 --- wrt_app/src/web_application.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wrt_app/src/web_application.ts b/wrt_app/src/web_application.ts index 61bbfd7..4310ed4 100644 --- a/wrt_app/src/web_application.ts +++ b/wrt_app/src/web_application.ts @@ -398,10 +398,7 @@ Then you can get profile log from the initial loading.`; private flushData() { console.log('WebApplication : FlushData'); - if (wrt.tv) { - wrt.tv.flushCookie(); - this.windowList.forEach((window) => window.webContents.session.flushStorageData()); - } + this.windowList.forEach((window) => window.webContents.session.flushStorageData()); } sendAppControlEvent() { -- 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 02/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 03/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 04/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 05/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 06/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 d75ae6696e935369ebe7c7c8fe3406438b73fc97 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Wed, 21 Oct 2020 15:21:48 +0900 Subject: [PATCH 07/16] [TV] Remove unnecessary code clearDeadMount() was removed from https://review.tizen.org/gerrit/245799/ Change-Id: I56d6198754962d24131b318ddb986e96f355ceac Signed-off-by: DongHyun Song --- wrt_app/src/runtime.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wrt_app/src/runtime.ts b/wrt_app/src/runtime.ts index 02a15b6..0f81a53 100644 --- a/wrt_app/src/runtime.ts +++ b/wrt_app/src/runtime.ts @@ -71,10 +71,7 @@ class Runtime { XWalkExtension.initialize(); XWalkExtension.preventCleanup(); } - if (wrt.tv) { - wrt.tv.importCertificate(''); - wrt.tv.clearDeadMount(); - } + wrt.tv?.importCertificate(''); }); wrt.on('app-control', (event, appControl) => { console.log('app-control'); -- 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 08/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 09/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 From ada818484187c865d14400baa1b6a4308478f2cb Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 12 Oct 2020 17:32:23 +0900 Subject: [PATCH 10/16] [TV] Bring cancelDialogs() forward to before-quit With below refactor patch, https://review.tizen.org/gerrit/245417/ Defered timing of closing windows, Sometimes, JS exception is coming due to access of destroyed Object at wrt.tv.cancelDialogs(this.mainWindow.webContents); Change-Id: I207c890cb84e6aaec8ed13316c39b80dd2e6cd3c Signed-off-by: DongHyun Song --- wrt_app/src/web_application.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wrt_app/src/web_application.ts b/wrt_app/src/web_application.ts index 3e5a683..3795a2a 100644 --- a/wrt_app/src/web_application.ts +++ b/wrt_app/src/web_application.ts @@ -381,22 +381,22 @@ Then you can get profile log from the initial loading.`; finalize() { console.log('WebApplication : finalize'); + this.flushData(); + this.windowList.forEach((window) => window.removeAllListeners()); + } + + quit() { + console.log('WebApplication : quit'); + addonManager.emit('lcQuit', this.mainWindow.id); if (wrt.tv) { this.inspectorSrc = ''; wrt.tv.cancelDialogs(this.mainWindow.webContents); } - this.flushData(); if (this.debugPort) { console.log('stop inspector server'); this.debugPort = 0; wrt.stopInspectorServer(); } - this.windowList.forEach((window) => window.removeAllListeners()); - } - - quit() { - console.log('WebApplication : quit'); - addonManager.emit('lcQuit', this.mainWindow.id); this.inQuit = true; if (!this.suspended) this.suspend(); -- 2.7.4 From 4c869fc6fd8fd46090a6919ee53b69df7283f353 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 26 Oct 2020 19:07:57 +0900 Subject: [PATCH 11/16] Refactor suspend sequence To guarantee unload* events, suspend() should be deffered after closing windows. Related patch: https://review.tizen.org/gerrit/246015/ https://review.tizen.org/gerrit/245417/ Change-Id: Id13a275b64e75f985e0115eee6771e3c29dd9cd9 Signed-off-by: DongHyun Song --- wrt_app/src/web_application.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wrt_app/src/web_application.ts b/wrt_app/src/web_application.ts index 3795a2a..5a57298 100644 --- a/wrt_app/src/web_application.ts +++ b/wrt_app/src/web_application.ts @@ -345,14 +345,14 @@ Then you can get profile log from the initial loading.`; } suspend() { - if (this.suspended) + if (this.suspended || this.inQuit) 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() || this.inQuit) { + if (!this.backgroundRunnable()) { if (!this.multitaskingSupport) { // FIXME : terminate app after visibilitychange event handling setTimeout(() => { @@ -383,6 +383,9 @@ Then you can get profile log from the initial loading.`; console.log('WebApplication : finalize'); this.flushData(); this.windowList.forEach((window) => window.removeAllListeners()); + this.inQuit = false; + if (!this.suspended) + this.suspend(); } quit() { @@ -398,8 +401,6 @@ Then you can get profile log from the initial loading.`; wrt.stopInspectorServer(); } this.inQuit = true; - if (!this.suspended) - this.suspend(); } private flushData() { -- 2.7.4 From cba0131267602c7f4830ebb3e083b9da77308a1e Mon Sep 17 00:00:00 2001 From: SangYong Park Date: Thu, 29 Oct 2020 14:41:08 +0900 Subject: [PATCH 12/16] Apply electron v10 Change module path for electron v10 Change-Id: I7f9bc61b2d4b614a10b245a8071bee55a0928bfd Signed-off-by: SangYong Park --- wrt_app/browser/init.ts | 2 +- wrt_app/browser/wrt_web_contents.ts | 6 +++--- wrt_app/renderer/init.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wrt_app/browser/init.ts b/wrt_app/browser/init.ts index c3b9a54..6bec418 100755 --- a/wrt_app/browser/init.ts +++ b/wrt_app/browser/init.ts @@ -16,4 +16,4 @@ import '../common/init'; import { wrt } from './wrt'; -import (wrt.getElectronPath() + '/browser/init'); +import 'electron/js2c/browser_init'; diff --git a/wrt_app/browser/wrt_web_contents.ts b/wrt_app/browser/wrt_web_contents.ts index 0b35873..38ab268 100644 --- a/wrt_app/browser/wrt_web_contents.ts +++ b/wrt_app/browser/wrt_web_contents.ts @@ -16,10 +16,10 @@ const binding: NativeWRTjs.WRTWebContentsBinding = process.wrtBinding('wrt_web_contents'); const { WRTWebContents } = binding; -const { WebContents: AtomWebContents } = process.wrtBinding('atom_browser_web_contents'); +const { WebContents: ElectronWebContents } = process.wrtBinding('electron_browser_web_contents'); -const parent = AtomWebContents.prototype; -AtomWebContents.prototype = WRTWebContents.prototype; +const parent = ElectronWebContents.prototype; +ElectronWebContents.prototype = WRTWebContents.prototype; Object.setPrototypeOf(WRTWebContents.prototype, parent); diff --git a/wrt_app/renderer/init.ts b/wrt_app/renderer/init.ts index f53c5d1..4451573 100755 --- a/wrt_app/renderer/init.ts +++ b/wrt_app/renderer/init.ts @@ -16,4 +16,4 @@ import '../common/init'; import { wrtRenderer } from './wrt_renderer'; -import (wrtRenderer.getElectronPath() + '/renderer/init'); +import 'electron/js2c/renderer_init'; -- 2.7.4 From 26ba0912aac78eb121373cfe30cd803c96093fd3 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Fri, 6 Nov 2020 09:48:12 +0900 Subject: [PATCH 13/16] [Service] Terminate worker more gracefully process.exit() in node worker will call Worker::Exit(), which stop the thread asyncronously. So WorkerThreadData is released later after worker's exit event. worker.terminate() in main thread will call Worker::StopThread(), which processes Worker::JoinThread() as well as Worker::Exit(). JoinThread() can defer parent's exit() call after worker's gone. Change-Id: Iad6bd2d64f158e7d6734500a7ab0623d75ad630f Signed-off-by: DongHyun Song (cherry picked from commit 480b6888ff5a0e9fd5983788fc4a98d97e32e217) --- wrt_app/common/service_manager.ts | 5 +++++ wrt_app/common/service_runner.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index b48f2d4..a6ab24a 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -25,6 +25,11 @@ function createWorker(id: string, startService: string, filename: string) { filename } }); + workers[id].on('message', (message: string) => { + if (message === 'will-terminate') { + workers[id].terminate(); + } + }); workers[id].on('exit', (code: number) => { delete workers[id]; let runningServices = Object.keys(workers).length; diff --git a/wrt_app/common/service_runner.ts b/wrt_app/common/service_runner.ts index c3c8306..3e4b39e 100644 --- a/wrt_app/common/service_runner.ts +++ b/wrt_app/common/service_runner.ts @@ -102,7 +102,7 @@ function run() { stop(id); setTimeout(() => { XWalkExtension.cleanup(); - process.exit() + parentPort?.postMessage("will-terminate"); }, message.delay); } }); -- 2.7.4 From 27e18430914b56249e3bf8290170067004d65d3c Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Sun, 8 Nov 2020 20:12:31 +0900 Subject: [PATCH 14/16] [Service] Terminate node without process.exit() Node process will be terminated by uv handleres release instead of process.exit(). Related patch: https://review.tizen.org/gerrit/247203/ Change-Id: I24824ed1cc7ed9c055502d29a9008d27fedd3031 Signed-off-by: DongHyun Song (cherry picked from commit 9153d03dc5406e4e7017edcacdd81fa176d6490d) --- wrt_app/common/service_manager.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index b48f2d4..8fcb2e2 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -29,9 +29,6 @@ function createWorker(id: string, startService: string, filename: string) { 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); - } }); } -- 2.7.4 From b6973a288994391aa43574138f81fa5faae7153c Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Fri, 6 Nov 2020 16:55:37 +0900 Subject: [PATCH 15/16] [Service] Prevent multiple calls of wrt.stopService() In case of RakutenTV app, it calls tizen.application...exit() twice. Of course WRTServiceManager::Remove() will skip stopService at the second time, this patch can skip stopService() sequence more early time. Change-Id: I65fdfb13f28834e4093f6be7888054e6aec7162b Signed-off-by: DongHyun Song (cherry picked from commit 9b0419b99033485731a603ac1bb96d1cc87ea7ee) --- wrt_app/common/service_runner.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wrt_app/common/service_runner.ts b/wrt_app/common/service_runner.ts index c3c8306..7825b02 100644 --- a/wrt_app/common/service_runner.ts +++ b/wrt_app/common/service_runner.ts @@ -34,7 +34,8 @@ function registerExtensionResolver(id: string) { } } -function requestStopService(id: string) { +let requestStopService = (id: string) => { + requestStopService = (id: string) => {}; setTimeout(() => wrt.stopService(id), 500); } -- 2.7.4 From dbae941c9eacebe10473e557fc7f181880e4f0f6 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 16 Nov 2020 14:10:57 +0900 Subject: [PATCH 16/16] [Service] Changes 'DAEMON' to 'GLOBAL' 'global' wrt-service is more common name than 'daemon' Related chromium-efl patch: https://review.tizen.org/gerrit/247741/ Change-Id: I9139832bc0cf4d2ce6a6b916c1e98ba984e4e5ed Signed-off-by: DongHyun Song --- wrt_app/common/service_runner.ts | 2 +- wrt_app/common/wrt_xwalk_extension.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wrt_app/common/service_runner.ts b/wrt_app/common/service_runner.ts index 3118d89..e8b912d 100644 --- a/wrt_app/common/service_runner.ts +++ b/wrt_app/common/service_runner.ts @@ -14,7 +14,7 @@ function isServiceApplication() { } function isGlobalService() { - return global['serviceType'] === 'DAEMON'; + return global['serviceType'] === 'GLOBAL'; } function registerExtensionResolver(id: string) { diff --git a/wrt_app/common/wrt_xwalk_extension.ts b/wrt_app/common/wrt_xwalk_extension.ts index f7ba13d..1204a81 100644 --- a/wrt_app/common/wrt_xwalk_extension.ts +++ b/wrt_app/common/wrt_xwalk_extension.ts @@ -118,7 +118,7 @@ class XWalkExtension { var api = (ext.use_trampoline) ? api_ : global; var extension_api = ext.jsapi; - if (global.serviceType === 'DAEMON' && ext.name === 'xwalk') { + if (global.serviceType === 'GLOBAL' && ext.name === 'xwalk') { console.log(`Delete freeze exports.utils for override method`); extension_api = extension_api.replace('Object.freeze(exports.utils);', ''); extension_api = extension_api.replace('Object.freeze(Utils.prototype);', ''); -- 2.7.4