From 9153d03dc5406e4e7017edcacdd81fa176d6490d Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Sun, 8 Nov 2020 20:12:31 +0900 Subject: [PATCH 01/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 --- 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 a6ab24a..757688b 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -34,9 +34,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 9b0419b99033485731a603ac1bb96d1cc87ea7ee Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Fri, 6 Nov 2020 16:55:37 +0900 Subject: [PATCH 02/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 --- 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 2624f12..1112196 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 e278331e59d36fe032029f22f5076dced1084a4a Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Fri, 6 Nov 2020 09:39:03 +0900 Subject: [PATCH 03/16] [Service][VD] Apply main thread with standalone model With standalone model of service application, this patch will apply main thread service_runner to solve crash problems of node worker. Change-Id: I5fb69368a4bae36ac11d465200b2cd0a42e6c3a1 Signed-off-by: DongHyun Song --- wrt_app/common/service_manager.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/wrt_app/common/service_manager.ts b/wrt_app/common/service_manager.ts index 757688b..14f0a87 100644 --- a/wrt_app/common/service_manager.ts +++ b/wrt_app/common/service_manager.ts @@ -5,14 +5,15 @@ interface WorkerMap { [id: string]: any; } let workers: WorkerMap = {}; +let runner: any; Object.defineProperty(global, 'serviceType', { value: wrt.getServiceModel(), writable: false }); -function isServiceApplication() { - return global['serviceType'] !== 'UI'; +function isStandalone() { + return global['serviceType'] === 'STANDALONE'; } function createWorker(id: string, startService: string, filename: string) { @@ -48,13 +49,26 @@ function terminateWorker(id: string, delay: number) { export function startService(id: string, filename: string) { console.log(`startService - ${id}`); - let startService = `${__dirname}/service_runner.js`; - createWorker(id, startService, filename); + if (isStandalone()) { + runner = require('../common/service_runner'); + runner.start(id, filename); + } else { + 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); + } else { + terminateWorker(id, 500); + } } export function handleBuiltinService(serviceId: string, serviceName: string) { -- 2.7.4 From d55cc7de0b1ddb97a0eb533558fd51edb382763f Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Tue, 13 Oct 2020 02:35:00 -0700 Subject: [PATCH 04/16] [Service] Add edge orchestration interface This provides initial edge orchestration interface. Change-Id: I44df11d7769e9ed692790cd9efd6735a97de94c5 Signed-off-by: Youngsoo Choi --- wrt_app/service/device_api_router.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index 7cb70cb..a7e3563 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -52,9 +52,34 @@ export class DeviceAPIRouter { global.webapis.getPackageId = () => { return this.packageId; } + this.initEdgeWebapis(); this.initProductWebapis(); } + initEdgeWebapis() { + if (wrt['edge'] && !global.webapis.edge) { + let edge = wrt.edge as NativeWRTjs.EdgeExtension; + global.webapis.edge = { + orchestrationGetDevicelist: (service_name: string, exec_type: string) => { + return edge.orchestrationGetDevicelist(service_name, exec_type); + }, + orchestrationReadCapability: (ip: string) => { + return edge.orchestrationReadCapability(ip); + }, + orchestrationRequestService: (app_name: string, self_select: boolean, exec_type: string, exec_parameter: string) => { + return edge.orchestrationRequestService(app_name, self_select, exec_type, exec_parameter); + }, + orchestrationRequestServiceOnDevice: (app_name: string, self_select: boolean, exec_type: string, exec_parameter: string, ip: string) => { + return edge.orchestrationRequestServiceOnDevice(app_name, self_select, exec_type, exec_parameter, ip); + }, + orchestrationWriteCapability: (json: string) => { + return edge.orchestrationWriteCapability(json); + }, + } + Object.defineProperty(global.webapis, 'edge', { writable: false, enumerable: true }); + } + } + initProductWebapis() { // for TV profile if (wrt.tv && !global.webapis.productinfo) { -- 2.7.4 From bb337f18e199a5777a2000bc57372487c967fd35 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 2 Nov 2020 16:55:24 +0900 Subject: [PATCH 05/16] [Service] Refactor unload xwalk extension unloadInstance() is introduced for optimizing memory on global model. But with irregular crash problems on UvTaskRunner's OnTimeout function, it try to access xwalk instance after deleted. This patch will remove calling unloadInstance() API. Unloading xwalk extension will be refactored below patch. Related patch: https://review.tizen.org/gerrit/246586/ Change-Id: Ie6a74b815680f02530fd2553427d03bf1634d612 Signed-off-by: DongHyun Song (cherry picked from commit f93dfc53d1b8626d3204c41113d86497b90f7ad3) --- wrt_app/common/wrt_xwalk_extension.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/wrt_app/common/wrt_xwalk_extension.ts b/wrt_app/common/wrt_xwalk_extension.ts index f7ba13d..23106e6 100644 --- a/wrt_app/common/wrt_xwalk_extension.ts +++ b/wrt_app/common/wrt_xwalk_extension.ts @@ -220,9 +220,6 @@ export const setRuntimeMessageHandler = (handler: (type: string, data?: string, } export let cleanup = () => { - for (var name in extensions_) { - extensions_[name].unloadInstance(); - } delete global.tizen; instance = undefined; } -- 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 06/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 07/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 08/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 56f177237067a99f1b074dfe065847021e2567fd Mon Sep 17 00:00:00 2001 From: SangYong Park Date: Thu, 12 Nov 2020 15:04:33 +0900 Subject: [PATCH 09/16] Remove unnecessary cookie api Related patch: https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/247660/ Change-Id: Ic5dc532cd2ce99df148398ad052e508e1e4fcdf4 Signed-off-by: SangYong Park --- wrt_app/src/runtime.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/wrt_app/src/runtime.ts b/wrt_app/src/runtime.ts index 0f81a53..42687a8 100644 --- a/wrt_app/src/runtime.ts +++ b/wrt_app/src/runtime.ts @@ -55,8 +55,6 @@ class Runtime { }); app.on('web-contents-created', (event, webContents) => { console.log('web-contents-created'); - if (wrt.tv) - this.setCookiePath(); webContents.on('before-input-event', (event, input) => { if (this.isLaunched && this.webApplication) this.handleKeyEvents(input.key); @@ -163,7 +161,6 @@ class Runtime { this.webApplication.sendAppControlEvent(); } } - this.setCookiePath(); this.launchInspector(appControl); }); wrt.on('suspend', () => { @@ -232,14 +229,6 @@ class Runtime { return (bundleDebug || this.inspectorEnabledByVconf); } - private setCookiePath() { - this.setCookiePath = () => {}; // call once - console.log('setCookiePath'); - - // FIX ME : It must be supplemented to set a specific path - wrt.setCookiePath(); - } - private handleKeyEvents(key: string) { let valid = false; console.log(key + ' is pressed'); -- 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 10/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 From fdeb7353ba0fcdb884fecc9983c01107ee25753f Mon Sep 17 00:00:00 2001 From: "jaekuk, lee" Date: Tue, 17 Nov 2020 17:52:55 +0900 Subject: [PATCH 11/16] Don't display splash screen in background mode When launching app in backgroundAtStartup launchMode, prevent splash screen from being displayed. Change-Id: I416fce778e5a001df5a6da855959c88d42ac19f4 Signed-off-by: jaekuk, lee --- wrt_app/src/web_application.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 wrt_app/src/web_application.ts diff --git a/wrt_app/src/web_application.ts b/wrt_app/src/web_application.ts old mode 100644 new mode 100755 index 430a593..8888289 --- a/wrt_app/src/web_application.ts +++ b/wrt_app/src/web_application.ts @@ -285,7 +285,7 @@ export class WebApplication { this.suspended = false; if (this.showTimer) clearTimeout(this.showTimer); - let splashShown = firstLaunch && wrt.showSplashScreen(); + let splashShown = this.preloadStatus !== 'preload' && firstLaunch && wrt.showSplashScreen(); if (!splashShown && !wrt.tv) { this.showTimer = setTimeout(() => { if (!this.suspended) { -- 2.7.4 From 40e496ec570bbf6b9398438261e414cab84e763b Mon Sep 17 00:00:00 2001 From: Surya Kumar Date: Tue, 24 Nov 2020 12:51:23 +0530 Subject: [PATCH 12/16] [M85] Suppress a macOS hack present in electron to gain webview focus A hack used by electron meant for macOS & extended for other platforms contingently is causing behavior difference from XWALK. Since that's the only consumer of 'load-url', removed all event listeners. Focus will anyway be gained by WebContents on their respective show() calls. Fixes P200228-07034 & P200113-07900. Reference: https://review.tizen.org/gerrit/226898 Change-Id: Ife2e6fd54c146596becd5cd00fb86797a9dc6cae Signed-off-by: Surya Kumar --- wrt_app/browser/wrt_window.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wrt_app/browser/wrt_window.ts b/wrt_app/browser/wrt_window.ts index 41c1690..2ac5a14 100644 --- a/wrt_app/browser/wrt_window.ts +++ b/wrt_app/browser/wrt_window.ts @@ -23,6 +23,9 @@ Object.setPrototypeOf(WRTWindow.prototype, BrowserWindow.prototype); WRTWindow.prototype._init = function () { (BrowserWindow.prototype as any)._init.call(this); + // This removes a macOS specific hack present in electron + // that causes side effects on Tizen + this.webContents.removeAllListeners('load-url'); if (typeof this.setup === 'function') this.setup(); this.constructor = BrowserWindow; -- 2.7.4 From 3b05de4cf0d609e050aa961f32458dd93cd163df Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Mon, 30 Nov 2020 22:24:21 -0800 Subject: [PATCH 13/16] Revert "[Service] Add edge orchestration interface" This reverts commit d55cc7de0b1ddb97a0eb533558fd51edb382763f. The edge interface is not ready yet on M85 chromium-efl. Change-Id: I1dfd008b4e6ebb4594aa7791ee2c5a58e43589a6 Signed-off-by: Youngsoo Choi --- wrt_app/service/device_api_router.ts | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/wrt_app/service/device_api_router.ts b/wrt_app/service/device_api_router.ts index a7e3563..7cb70cb 100644 --- a/wrt_app/service/device_api_router.ts +++ b/wrt_app/service/device_api_router.ts @@ -52,34 +52,9 @@ export class DeviceAPIRouter { global.webapis.getPackageId = () => { return this.packageId; } - this.initEdgeWebapis(); this.initProductWebapis(); } - initEdgeWebapis() { - if (wrt['edge'] && !global.webapis.edge) { - let edge = wrt.edge as NativeWRTjs.EdgeExtension; - global.webapis.edge = { - orchestrationGetDevicelist: (service_name: string, exec_type: string) => { - return edge.orchestrationGetDevicelist(service_name, exec_type); - }, - orchestrationReadCapability: (ip: string) => { - return edge.orchestrationReadCapability(ip); - }, - orchestrationRequestService: (app_name: string, self_select: boolean, exec_type: string, exec_parameter: string) => { - return edge.orchestrationRequestService(app_name, self_select, exec_type, exec_parameter); - }, - orchestrationRequestServiceOnDevice: (app_name: string, self_select: boolean, exec_type: string, exec_parameter: string, ip: string) => { - return edge.orchestrationRequestServiceOnDevice(app_name, self_select, exec_type, exec_parameter, ip); - }, - orchestrationWriteCapability: (json: string) => { - return edge.orchestrationWriteCapability(json); - }, - } - Object.defineProperty(global.webapis, 'edge', { writable: false, enumerable: true }); - } - } - initProductWebapis() { // for TV profile if (wrt.tv && !global.webapis.productinfo) { -- 2.7.4 From cd6ebb4c5cceb62d2487af854dc9902d1b7b031d Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 23 Nov 2020 07:12:06 +0900 Subject: [PATCH 14/16] Refactor disk cache setting and appcontrol data Delete codes will be handled in native code side Related patch: https://review.tizen.org/gerrit/248127/ Change-Id: I596fce437f43664c4fd17eff959375d46ff7b776 Signed-off-by: DongHyun Song --- wrt_app/src/runtime.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wrt_app/src/runtime.ts b/wrt_app/src/runtime.ts index 3717d43..185c63a 100644 --- a/wrt_app/src/runtime.ts +++ b/wrt_app/src/runtime.ts @@ -105,10 +105,6 @@ class Runtime { this.webApplication.inspectorSrc = src; src = "about:blank"; } - let useDiskCache = appControl.getData('USE_DISKCACHE'); - let halfWindowOption = appControl.getData('http://samsung.com/appcontrol/data/half_window_support'); - wrt.tv.setDiskCache(useDiskCache); - wrt.tv.handleAppControlData(launchMode, halfWindowOption); } this.webApplication.mainWindow.loadURL(src); this.webApplication.prelaunch(src); -- 2.7.4 From 08c4701f9f2e5a5f69a4bb257d846bf013fddcbd Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Wed, 2 Dec 2020 16:54:15 +0900 Subject: [PATCH 15/16] Make same function name with its event name 1) Rename functions same as its event name 2) Add blank line among functions. Change-Id: Ide74634ec37060572862e3983a953a54151a6fa5 Signed-off-by: DongHyun Song --- wrt_app/src/runtime.ts | 44 ++++++++++++++++++++++++++++-------------- wrt_app/src/web_application.ts | 38 ++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/wrt_app/src/runtime.ts b/wrt_app/src/runtime.ts index 3717d43..94f9e99 100644 --- a/wrt_app/src/runtime.ts +++ b/wrt_app/src/runtime.ts @@ -27,21 +27,24 @@ class Runtime { inspectorEnabledByVconf = false; constructor() { - app.on('before-quit', (event) => { + app.on('before-quit', (event: any) => { console.log('before-quit'); - this.webApplication?.quit(); + this.webApplication?.beforeQuit(); }); - app.on('will-quit', (event) => { + + app.on('will-quit', (event: any) => { console.log('will-quit'); addonManager.deactivateAll(); }); - app.on('quit', (event) => { + + app.on('quit', (event: any) => { console.log('quit'); if (this.webApplication) { - this.webApplication.finalize(); + this.webApplication.quit(); this.webApplication = undefined; } }); + app.on('browser-window-created', () => { console.log('browser-window-created'); if (!this.isLaunched) { @@ -49,18 +52,21 @@ class Runtime { this.isLaunched = true; } }); + app.on('window-all-closed', () => { console.log('window-all-closed'); app.quit(); }); - app.on('web-contents-created', (event, webContents) => { + + app.on('web-contents-created', (event: any, webContents: any) => { console.log('web-contents-created'); - webContents.on('before-input-event', (event, input) => { + webContents.on('before-input-event', (event: any, input: any) => { if (this.isLaunched && this.webApplication) this.handleKeyEvents(input.key); }); }); - app.once('ready', (event) => { + + app.once('ready', (event: any) => { console.log('ready'); let addonAvailable = addonManager.build(); console.log("addonBuild : " + addonAvailable); @@ -71,7 +77,8 @@ class Runtime { } wrt.tv?.importCertificate(''); }); - wrt.on('app-control', (event, appControl) => { + + wrt.on('app-control', (event: any, appControl: any) => { console.log('app-control'); let loadInfo = appControl.getLoadInfo(); let src = loadInfo.getSrc(); @@ -166,19 +173,23 @@ class Runtime { } this.launchInspector(appControl); }); + wrt.on('suspend', () => { console.log('suspend'); this.webApplication?.suspend(); }); + wrt.on('resume', () => { console.log('resume'); this.webApplication?.resume(); }); + wrt.on('low-memory', () => { console.log('low-memory'); this.webApplication?.lowMemory(); }); - wrt.on('message', (event, type, params) => { + + wrt.on('message', (event: any, type: string, params: string[]) => { console.log('message type(' + type + ') params : ' + params); const app_id = params[0]; if (type === 'startService') { @@ -189,21 +200,26 @@ class Runtime { event.preventDefault(); } }); + wrt.on('ambient-tick', () => { this.webApplication?.ambientTick(); }); - wrt.on('ambient-changed', (event, ambient_mode) => { + + wrt.on('ambient-changed', (event: any, ambient_mode: boolean) => { console.log('ambient-changed , ambient_mode:' + ambient_mode); this.webApplication?.ambientChanged(ambient_mode); }); - wrt.on('addon-installed', (event, path) => { + + wrt.on('addon-installed', (event: any, path: string) => { console.log('addon-installed at ' + path); addonManager.checkAddon(path); }); - wrt.on('addon-uninstalled', (event, id) => { + + wrt.on('addon-uninstalled', (event: any, id: string) => { console.log('addon-unistalled named ' + id); }); - wrt.on('wgt-checking-done', (event) => { + + wrt.on('wgt-checking-done', (event: any) => { console.log('wgt-checking-done'); addonManager.updateDB(); }); diff --git a/wrt_app/src/web_application.ts b/wrt_app/src/web_application.ts index 8888289..ce20833 100755 --- a/wrt_app/src/web_application.ts +++ b/wrt_app/src/web_application.ts @@ -74,7 +74,7 @@ export class WebApplication { } private setupEventListener(options: RuntimeOption) { - app.on('browser-window-created', (event, window) => { + app.on('browser-window-created', (event: any, window: any) => { if (this.windowList.length > 0) this.windowList[this.windowList.length - 1].hide(); this.windowList.push(window); @@ -88,12 +88,14 @@ export class WebApplication { this.windowList[this.windowList.length - 1].show(); }); }); - app.on('web-contents-created', (event, webContents) => { + + app.on('web-contents-created', (event: any, webContents: any) => { webContents.on('crashed', function() { console.error('webContents crashed'); app.exit(100); }); - webContents.session.setPermissionRequestHandler((webContents, permission, callback) => { + + webContents.session.setPermissionRequestHandler((webContents: any, permission: string, callback: any) => { console.log(`handlePermissionRequests for ${permission}`); if (permission === 'notifications') { if (!this.notificationPermissionMap) @@ -127,7 +129,8 @@ export class WebApplication { } }); }); - app.on('certificate-error', (event, webContents, url, error, certificate, callback) => { + + app.on('certificate-error', (event: any, webContents: any, url: string, error: string, certificate: any, callback: any) => { console.log('A certificate error has occurred'); event.preventDefault(); if (certificate.data) { @@ -140,7 +143,8 @@ export class WebApplication { callback(false); } }); - app.on('login', (event, webContents, request, authInfo, callback) => { + + app.on('login', (event: any, webContents: any, request: any, authInfo: any, callback: any) => { console.log(`Login info is required, isproxy: ${authInfo.isProxy}`); event.preventDefault(); let usrname = ''; @@ -165,9 +169,10 @@ export class WebApplication { wrt.handleAuthRequest(id, webContents); } }); + if (this.accessiblePath) { console.log(`accessiblePath: ${this.accessiblePath}`); - protocol.interceptFileProtocol('file', (request, callback) => { + protocol.interceptFileProtocol('file', (request: any, callback: any) => { if (request.url) { let parsed_info = new URL(request.url); let access_path = parsed_info.host + decodeURI(parsed_info.pathname); @@ -190,11 +195,12 @@ export class WebApplication { console.log('request url is empty'); (callback as any)(403); } - }, (error) => { + }, (error: Error) => { console.log(error); }); } - wrt.on('permission-response', (event, id, result) => { + + wrt.on('permission-response', (event: any, id: number, result: boolean) => { console.log(`permission-response for ${id} is ${result}`); let callback = this.pendingCallbacks.get(id); if (typeof callback === 'function') { @@ -203,7 +209,8 @@ export class WebApplication { this.pendingCallbacks.delete(id); } }); - wrt.on('auth-response', (event, id, submit, user, password) => { + + wrt.on('auth-response', (event: any, id: number, submit: boolean, user: string, password: string) => { let callback = this.pendingCallbacks.get(id); if (typeof callback === 'function') { console.log('calling auth response callback'); @@ -214,7 +221,8 @@ export class WebApplication { this.pendingCallbacks.delete(id); } }); - wrt.on('app-status-changed', (event, status) => { + + wrt.on('app-status-changed', (event: any, status: string) => { console.log(`runningStatus: ${status}, ${this.loadFinished}`); if (!wrt.tv) return; @@ -258,10 +266,12 @@ export class WebApplication { } this.show(); }); + this.mainWindow.webContents.on('did-start-loading', () => { console.log('webContents did-start-loading'); this.loadFinished = false; }); + this.mainWindow.webContents.on('did-finish-load', () => { console.log('webContents did-finish-load'); this.loadFinished = true; @@ -379,8 +389,8 @@ Then you can get profile log from the initial loading.`; this.windowList[this.windowList.length - 1].show(); } - finalize() { - console.log('WebApplication : finalize'); + quit() { + console.log('WebApplication : quit'); this.flushData(); this.windowList.forEach((window) => window.removeAllListeners()); this.inQuit = false; @@ -388,8 +398,8 @@ Then you can get profile log from the initial loading.`; this.suspend(); } - quit() { - console.log('WebApplication : quit'); + beforeQuit() { + console.log('WebApplication : beforeQuit'); addonManager.emit('lcQuit', this.mainWindow.id); if (wrt.tv) { this.inspectorSrc = ''; -- 2.7.4 From 943c25bda3bd3c48c94efd61d85182018292f54d Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Wed, 2 Dec 2020 17:14:35 +0900 Subject: [PATCH 16/16] Refactor app-control event to improve readability 1) Split into small functions by their roles. 2) Move functions to proper class - most of them are located in WebApplication Change-Id: Ibd03eb6b6ef29c197266b7b9d51393134c06c375 Signed-off-by: DongHyun Song --- wrt_app/src/runtime.ts | 127 ++++++++++++++--------------------------- wrt_app/src/web_application.ts | 86 +++++++++++++++++++++++++--- 2 files changed, 120 insertions(+), 93 deletions(-) diff --git a/wrt_app/src/runtime.ts b/wrt_app/src/runtime.ts index 8857abd..8687822 100644 --- a/wrt_app/src/runtime.ts +++ b/wrt_app/src/runtime.ts @@ -80,92 +80,16 @@ class Runtime { wrt.on('app-control', (event: any, appControl: any) => { console.log('app-control'); - let loadInfo = appControl.getLoadInfo(); - let src = loadInfo.getSrc(); - if (wrt.isElectronApp()) { - console.log('Electron App launch'); - const Module = require('module'); - Module.globalPaths.push(wrt.getAppPath()); - let filePath = src[7] === '/' ? src.substr(8) : src.substr(7); // strip "file://" - let pkgJson = require(filePath); - let pos = filePath.lastIndexOf('/'); - - let mainJsPath = (pos !== -1 ? filePath.substr(0, pos + 1) : '') + - (pkgJson.main || 'index.js'); - console.log('loading path:', mainJsPath); - Module._load(mainJsPath, Module, true); - app.emit('ready'); + this.handleAppControlForElectronApp(appControl); + return; + } + console.log('Tizen Web App launch'); + if (!this.webApplication) { + this.createWebApplicationAndLoadUrl(appControl); } else { - console.log('Tizen Web App launch'); - let launchMode = appControl.getData('http://samsung.com/appcontrol/data/launch_mode'); - if (!this.webApplication) { - console.log('Creating WebApplication'); - let options: RuntimeOption = { - isAddonAvailable: addonManager.isAddonAvailable(), - launchMode: launchMode - } - this.webApplication = new WebApplication(options); - if (wrt.tv) { - this.inspectorEnabledByVconf = wrt.tv.needUseInspector(); - if (this.inspectorEnabledByVconf && launchMode != 'backgroundExecution') { - this.webApplication.inspectorSrc = src; - src = "about:blank"; - } - } - this.webApplication.mainWindow.loadURL(src); - this.webApplication.prelaunch(src); - if (wrt.da) { - this.webApplication.mainWindow.emit('ready-to-show'); - } - } else { - console.log('Handling app-control event'); - if (this.webApplication.preloadStatus == 'readyToShow') { - this.webApplication.show(); - } else { - if (launchMode != 'backgroundAtStartup') - this.webApplication.preloadStatus = 'none'; - } - - let skipReload = appControl.getData('SkipReload'); - if (skipReload == 'Yes') { - console.log('skipping reload'); - // TODO : Need to care this situation and decide to pass the addon event emitter to resume() - this.webApplication.resume(); - return; - } - - let reload = loadInfo.getReload() || this.webApplication.isAlwaysReload; - if (!reload) { - let originalUrl = this.webApplication.mainWindow.webContents.getURL(); - if (wrt.tv) { - console.log(`appcontrol src = ${src}, original url = ${originalUrl}`); - if (src && originalUrl) { - let appcontrolUrl = (new URL(src)).href; - let oldUrl = (new URL(originalUrl)).href; - console.log(`appcontrolUrl = ${appcontrolUrl}, oldUrl = ${oldUrl}`); - // FIXME(dh81.song) - // Below case it must be distinguishable for known cases - // from 'file:///index.htmlx' to 'file:///index.html' - if (appcontrolUrl !== oldUrl.substr(0, appcontrolUrl.length)) - reload = true; - } else { - reload = true; - } - } else if (src !== originalUrl) { - reload = true; - } - } - // handle http://tizen.org/appcontrol/operation/main operation specially. - // only menu-screen app can send launch request with main operation. - // in this case, web app should have to resume web app not reset. - if (reload && appControl.getOperation() == 'http://tizen.org/appcontrol/operation/main') - reload = false; - if (reload) - this.webApplication.handleAppControlReload(src); - else - this.webApplication.sendAppControlEvent(); - } + console.log('Handling app-control event'); + this.webApplication.handleAppControlEvent(appControl); } this.launchInspector(appControl); }); @@ -225,6 +149,41 @@ class Runtime { wrt.getInstalledPkg(); } + private handleAppControlForElectronApp(appControl: any) { + console.log('Electron App launch'); + let src = appControl.getLoadInfo().getSrc(); + const Module = require('module'); + Module.globalPaths.push(wrt.getAppPath()); + let filePath = src[7] === '/' ? src.substr(8) : src.substr(7); // strip "file://" + let pkgJson = require(filePath); + let pos = filePath.lastIndexOf('/'); + + let mainJsPath = (pos !== -1 ? filePath.substr(0, pos + 1) : '') + + (pkgJson.main || 'index.js'); + console.log('loading path:', mainJsPath); + Module._load(mainJsPath, Module, true); + app.emit('ready'); + } + + private createWebApplicationAndLoadUrl(appControl: any) { + console.log('Creating WebApplication'); + let launchMode = appControl.getData('http://samsung.com/appcontrol/data/launch_mode'); + let src = appControl.getLoadInfo().getSrc(); + let options: RuntimeOption = { + isAddonAvailable: addonManager.isAddonAvailable(), + launchMode: launchMode + } + this.webApplication = new WebApplication(options); + if (wrt.tv) { + this.inspectorEnabledByVconf = wrt.tv.needUseInspector(); + if (this.inspectorEnabledByVconf && launchMode != 'backgroundExecution') { + this.webApplication.inspectorSrc = src; + src = "about:blank"; + } + } + this.webApplication.loadUrl(src); + } + private launchInspector(appControl: NativeWRTjs.AppControl) { this.launchInspector = (param) => {}; // call once console.log('launchInspector'); diff --git a/wrt_app/src/web_application.ts b/wrt_app/src/web_application.ts index ce20833..147ff8e 100755 --- a/wrt_app/src/web_application.ts +++ b/wrt_app/src/web_application.ts @@ -27,7 +27,6 @@ export class WebApplication { backgroundExecution: boolean; defaultBackgroundColor: string; defaultTransparent: boolean; - isAlwaysReload: boolean; mainWindow: Electron.BrowserWindow; multitaskingSupport: boolean; notificationPermissionMap?: Map; @@ -60,7 +59,6 @@ export class WebApplication { this.backgroundExecution = false; } this.accessiblePath = wrt.tv?.getAccessiblePath(); - this.isAlwaysReload = (wrt.tv ? wrt.tv.isAlwaysReload() : false); this.multitaskingSupport = (wrt.tv ? wrt.tv.getMultitaskingSupport() : true); this.defaultBackgroundColor = (wrt.tv ? '#0000' : ((wrt.getPlatformType() === "product_wearable") ? '#000' : '#FFF')); @@ -312,13 +310,6 @@ export class WebApplication { return this.backgroundSupport || this.backgroundExecution; } - handleAppControlReload(url: string) { - console.log('WebApplication : handleAppControlReload'); - this.closeWindows(); - this.initDisplayDelay(false); - this.mainWindow.loadURL(url); - } - private suspendByStatus() { if (this.preloadStatus === 'readyToShow' || this.preloadStatus === 'preload' || @@ -354,6 +345,40 @@ Then you can get profile log from the initial loading.`; } } + handleAppControlEvent(appControl: any) { + let launchMode = appControl.getData('http://samsung.com/appcontrol/data/launch_mode'); + this.handlePreloadState(launchMode); + + let skipReload = appControl.getData('SkipReload'); + if (skipReload == 'Yes') { + console.log('skipping reload'); + // TODO : Need to care this situation and decide to pass the addon event emitter to resume() + this.resume(); + return; + } + + let loadInfo = appControl.getLoadInfo(); + let src = loadInfo.getSrc(); + let reload = loadInfo.getReload() || this.needReload(src); + // handle http://tizen.org/appcontrol/operation/main operation specially. + // only menu-screen app can send launch request with main operation. + // in this case, web app should have to resume web app not reset. + if (reload && appControl.getOperation() == 'http://tizen.org/appcontrol/operation/main') + reload = false; + if (reload) + this.handleAppControlReload(src); + else + this.sendAppControlEvent(); + } + + loadUrl(src: string) { + this.mainWindow.loadURL(src); + this.prelaunch(src); + if (wrt.da) { + this.mainWindow.emit('ready-to-show'); + } + } + suspend() { if (this.suspended || this.inQuit) return; @@ -413,6 +438,49 @@ Then you can get profile log from the initial loading.`; this.inQuit = true; } + private needReload(src: string) { + let isAlwaysReload = (wrt.tv ? wrt.tv.isAlwaysReload() : false); + if (isAlwaysReload) { + return true; + } + let reload = false; + let originalUrl = this.mainWindow.webContents.getURL(); + if (wrt.tv) { + console.log(`appcontrol src = ${src}, original url = ${originalUrl}`); + if (src && originalUrl) { + let appcontrolUrl = (new URL(src)).href; + let oldUrl = (new URL(originalUrl)).href; + console.log(`appcontrolUrl = ${appcontrolUrl}, oldUrl = ${oldUrl}`); + // FIXME(dh81.song) + // Below case it must be distinguishable for known cases + // from 'file:///index.htmlx' to 'file:///index.html' + if (appcontrolUrl !== oldUrl.substr(0, appcontrolUrl.length)) + reload = true; + } else { + reload = true; + } + } else if (src !== originalUrl) { + reload = true; + } + return reload; + } + + private handleAppControlReload(url: string) { + console.log('WebApplication : handleAppControlReload'); + this.closeWindows(); + this.initDisplayDelay(false); + this.mainWindow.loadURL(url); + } + + private handlePreloadState(launchMode: string) { + if (this.preloadStatus == 'readyToShow') { + this.show(); + } else { + if (launchMode != 'backgroundAtStartup') + this.preloadStatus = 'none'; + } + } + private flushData() { console.log('WebApplication : FlushData'); this.windowList.forEach((window) => window.webContents.session.flushStorageData()); -- 2.7.4