From 60e67fd0666d6d539f49583545b5e6e943fab7bd Mon Sep 17 00:00:00 2001 From: "hyunduk.kim" Date: Sun, 30 Jun 2019 22:18:21 -0700 Subject: [PATCH] Initial code to handle lifecycles and events in addons This provides the invocation of predefined methods for lifecycles and events - prelanuch : invoking prelaunch() in an addon when app-control is emitted - suspend : invoking suspend() in an addon when suspend is emitted - resume : invoking resume() in an addon when resume is emitted - quit : invoking quit() in an addon when before-quit is emitted - arrowup : invoking arrowup() in an addon when arrowup is pressed - arrowdown : invoking arrowdown() in an addon when arrowdown is pressed It's only an initial code and focused on the logic to call each method. Change-Id: I04c5976dd88fabb2ccdfcf96e0d444ed296acbe4 Signed-off-by: hyunduk.kim --- wrt_app/src/addon_manager.js | 49 ++++++++++++++++++++++++ wrt_app/src/runtime.js | 50 ++++++++++++++++++++++++- wrt_app/src/web_application.js | 85 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 180 insertions(+), 4 deletions(-) diff --git a/wrt_app/src/addon_manager.js b/wrt_app/src/addon_manager.js index 7c7c449..d3efeca 100644 --- a/wrt_app/src/addon_manager.js +++ b/wrt_app/src/addon_manager.js @@ -33,6 +33,12 @@ class AddonManager { this.addons_list_ = null; this.addons_ = null; this.addons_API_ = null; + this.prelaunch_path = null; + this.resume_path = null; + this.suspend_path = null; + this.quit_path = null; + this.arrowup_path = null; + this.arrowdown_path = null; } printAPIs() { @@ -164,6 +170,44 @@ class AddonManager { return true; } + registerLifecycles(lifecycles, path) { + if (!lifecycles) { + console.log('lifecycle is not declared'); + return; + } + if (lifecycles.prelaunch) { + this.prelaunch_path = path; + console.log('prelaunch operation path :' + this.prelaunch_path); + } + if (lifecycles.resume) { + this.resume_path = path; + console.log('resume override path :' + this.resume_path); + } + if (lifecycles.suspend) { + this.suspend_path = path; + console.log('suspend override path :' + this.suspend_path); + } + if (lifecycles.quit) { + this.quit_path = path; + console.log('quit operation path :' + this.quit_path); + } + } + + registerEvents(events, path) { + if (!events) { + console.log('event is not declared'); + return; + } + if (events.arrowup) { + this.arrowup_path = path; + console.log('arrowup operation path :' + this.arrowup_path); + } + if (events.arrowdown) { + this.arrowdown_path = path; + console.log('arrowdown operation path :' + this.arrowdown_path); + } + } + build() { // 0. load addons_list_ from JSON DB this.loadJsonDB(); @@ -223,6 +267,11 @@ class AddonManager { addons[type][manifest_obj.name] = addon.path; } } + + let addon_path = path.join(addon.path, manifest_obj.name) + '.js'; + this.registerLifecycles(manifest_obj.lifecycle, addon_path); + this.registerEvents(manifest_obj.event, addon_path); + console.log('addons[' + type + '][' + manifest_obj.name + '] = ' + addons[type][manifest_obj.name] + ' registered'); } catch (e) { console.error('AddonManager.build error - ' + e); diff --git a/wrt_app/src/runtime.js b/wrt_app/src/runtime.js index 02af0d8..36e0eb1 100644 --- a/wrt_app/src/runtime.js +++ b/wrt_app/src/runtime.js @@ -31,10 +31,23 @@ class Runtime { this.isLaunched = false; this.debug_mode = false; this.need_inspector = false; + this.webContents = null; + this.allowQuit = false; var _this = this; app.on('before-quit', function(event) { console.log('before-quit'); + if (!wrt.isElectronApp()) { + if (_this.addonManager.quit_path && !_this.allowQuit) { + event.preventDefault(); + let timeout = _this.webApplication.quit(_this.addonManager.quit_path); + _this.allowQuit = true; + if (timeout >= 0) + setTimeout(function() { + app.quit(); + }, timeout, null); + } + } }); app.on('will-quit', function(event) { console.log('will-quit'); @@ -68,6 +81,15 @@ class Runtime { app.on('will-finish-launching', function(event) { console.log('will-finish-launching'); }); + app.on('web-contents-created', function(event, webContents) { + console.log('web-contents-created'); + _this.webContents = webContents; + _this.webContents.on('before-input-event', function(event, input) { + if (_this.isLaunched && _this.webApplication) { + _this.handleKeyEvents(input.key); + } + }); + }); app.once('ready', function(event) { console.log('ready'); _this.addonManager = new AddonManager(); @@ -103,6 +125,7 @@ class Runtime { options.launchMode = appControl.getData('http://samsung.com/appcontrol/data/launch_mode'); _this.webApplication = new WebApplication(options); _this.webApplication.mainWindow.loadURL(src); + _this.webApplication.prelaunch(_this.addonManager.prelaunch_path, src); } else { console.log('Handling app-control event'); if (_this.webApplication.preloadState == 'readyToShow') { @@ -150,11 +173,11 @@ class Runtime { }); wrt.on('suspend', function() { console.log('suspend'); - _this.webApplication.suspend(); + _this.webApplication.suspend(_this.addonManager.suspend_path); }); wrt.on('resume', function() { console.log('resume'); - _this.webApplication.resume(); + _this.webApplication.resume(_this.addonManager.resume_path); }); wrt.on('terminate', function() { console.log('terminate'); @@ -199,5 +222,28 @@ class Runtime { } appControl.reply(data); } + handleKeyEvents(key) { + let path = null; + let _this = this; + + console.log(key + ' is pressed'); + switch(key) { + case "ArrowUp": + case "Up": + path = _this.addonManager.arrowup_path; + break; + case "ArrowDown": + case "Down": + path = _this.addonManager.arrowdown_path; + break; + default: + console.log('No handler for the key ' + key); + break; + } + console.log('Path for ' + key + ' : ' + path); + if (path) { + _this.webApplication.keyEvent(key, path); + } + } } module.exports = Runtime; diff --git a/wrt_app/src/web_application.js b/wrt_app/src/web_application.js index 77e9f63..0688643 100755 --- a/wrt_app/src/web_application.js +++ b/wrt_app/src/web_application.js @@ -243,8 +243,18 @@ class WebApplication { } }); } - suspend() { + suspend(path) { console.log('WebApplication : suspend'); + if (path != null) { + let addon = require(path); + console.log('addon for suspend is ' + path); + if (addon.suspend) { + console.log('addon for suspend is found'); + addon.suspend(this.mainWindow.id, path); + } else { + console.log('addon for suspend is NOT found'); + } + } this.suspended = true; if (this.isTerminating) { console.log('App has been terminated; return'); @@ -262,11 +272,21 @@ class WebApplication { } this.windowList[this.windowList.length - 1].hide(); } - resume() { + resume(path) { console.log('WebApplication : resume'); this.suspended = false; if (!this.firstRendered) { console.log('WebApplication : resume firstRendered is false'); + if (path != null) { + let addon = require(path); + console.log('addon for resume is ' + path); + if (addon.resume) { + console.log('addon for resume is found'); + addon.resume(this.mainWindow.id, path); + } else { + console.log('addon for resume is NOT found'); + } + } return; } WRTWindow.getAllWindows().forEach((window) => { @@ -278,6 +298,21 @@ class WebApplication { terminate() { this.isTerminating = true; } + quit(path) { + console.log('WebApplication : quit'); + let timeout = -1; + if (path != null) { + let addon = require(path); + console.log('addon for quit is ' + path); + if (addon.quit) { + console.log('addon for quit is found'); + timeout = addon.quit(this.mainWindow.id, path); + } else { + console.log('addon for quit is NOT found'); + } + } + return timeout; + } sendAppControlEvent() { const kAppControlEventScript = '(function(){' + @@ -309,5 +344,51 @@ class WebApplication { window.destroy(); }); } + keyEvent(key, path) { + console.log('WebApplication : keyEvent'); + if (!path) { + console.log('no path for event hook exists'); + return; + } + let addon = require(path); + console.log('event is hooked for ' + path); + switch(key) { + case "ArrowUp": + case "Up": + if (addon.arrowup) { + console.log('arrowup is found'); + addon.arrowup(this.mainWindow.id); + } else { + console.log('arrowup is NOT found'); + } + break; + case "ArrowDown": + case "Down": + if (addon.arrowdown) { + console.log('arrowdown is found'); + addon.arrowdown(this.mainWindow.id); + } else { + console.log('arrowdown is NOT found'); + } + break; + default: + console.log('No handler for ' + key); + break; + } + } + prelaunch(path, origURL) { + console.log('WebApplication : prelaunch'); + if (path != null) { + let addon = require(path); + console.log('addon for additional runtime is ' + path); + console.log('prelaunch : org URL : ' + origURL); + if (addon.prelaunch) { + console.log('prelaunch is found'); + addon.prelaunch(this.mainWindow.id, origURL); + } else { + console.log('prelaunch is NOT found'); + } + } + } } module.exports = WebApplication; -- 2.7.4