[Service][UI] Release all remaining timers when stopService is called 33/215433/6
authorYoungsoo Choi <kenshin.choi@samsung.com>
Mon, 7 Oct 2019 05:40:08 +0000 (22:40 -0700)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Thu, 10 Oct 2019 09:01:34 +0000 (02:01 -0700)
The remaining timers by developer mistakes should be released
by ui service framework when stopService is called.

This provides overrided setInterval, clearInterval, setTimeout,
and clearTimeout to manage timer reference count and handlers.

Change-Id: I0470a8e696646efa33c63fca7627819ad2d7f893
Signed-off-by: Youngsoo Choi <kenshin.choi@samsung.com>
wrt_app/service/timer_manager.js [new file with mode: 0644]
wrt_app/src/runtime.js

diff --git a/wrt_app/service/timer_manager.js b/wrt_app/service/timer_manager.js
new file mode 100644 (file)
index 0000000..1f04a72
--- /dev/null
@@ -0,0 +1,40 @@
+class TimerManager {
+  constructor() {
+    this.interval_handlers = [];
+    this.timeout_handlers = [];
+    // Prevent contaminating global APIs
+    this.timer_api = {};
+    const _this = this;
+
+    this.timer_api.clearInterval = function(handler) {
+      const index = Object.keys(_this.interval_handlers)[Object.values(_this.interval_handlers).indexOf(handler)]
+      clearInterval(_this.interval_handlers.splice(index, 1)[0]);
+    }
+    this.timer_api.clearTimeout = function(handler) {
+      const index = Object.keys(_this.timeout_handlers)[Object.values(_this.timeout_handlers).indexOf(handler)]
+      clearTimeout(_this.timeout_handlers.splice(index, 1)[0]);
+    }
+    this.timer_api.setInterval = function(func, delay) {
+      _this.interval_handlers.push(setInterval(func, delay));
+    }
+    this.timer_api.setTimeout = function(func, delay) {
+      _this.timeout_handlers.push(setTimeout(func, delay));
+    }
+  }
+  getTimerAPI() {
+    return this.timer_api;
+  }
+  releaseRemainingTimers() {
+    console.log('Remaining interval(s) : ' + this.interval_handlers.length);
+    for (let index in this.interval_handlers) {
+      const handler = this.interval_handlers.splice(index, 1)[0];
+      clearInterval(handler);
+    }
+    console.log('Remaining timer(s) : ' + this.timeout_handlers.length);
+    for (let index in this.timeout_handlers) {
+      const handler = this.timeout_handlers.splice(index, 1)[0];
+      clearTimeout(handler);
+    }
+  }
+}
+module.exports = TimerManager;
index b00e397..6130fcd 100755 (executable)
@@ -20,6 +20,7 @@ const wrt = require('../browser/wrt');  // Load first for log
 const AddonManager = require('./addon_manager');
 const {app, ipcMain} = require('electron');
 const IPC_MESSAGE = require('./ipc_message');
+const TimerManager = require('../service/timer_manager');
 const WAS_EVENT = require('./was_event');
 const WebApplication = require('./web_application');
 
@@ -196,6 +197,11 @@ class Runtime {
                     for(let key in global) {
                         _this.sandbox[app_id][key] = global[key];
                     }
+                    _this.sandbox[app_id]['timer_manager'] = new TimerManager();
+                    const timer_api = _this.sandbox[app_id]['timer_manager'].getTimerAPI();
+                    for(let key in timer_api) {
+                        _this.sandbox[app_id][key] = timer_api[key];
+                    }
                     let options = {};
                     let code = fs.readFileSync(params[1]);
                     vm.runInNewContext(code, _this.sandbox[app_id], options);
@@ -215,6 +221,7 @@ class Runtime {
                     _this.sandbox[app_id]['started'] = undefined;
                     const stop_callback_string = 'if (module.exports.onStop !== undefined) { module.exports.onStop(); }';
                     vm.runInContext(stop_callback_string, _this.sandbox[app_id]);
+                    _this.sandbox[app_id]['timer_manager'].releaseRemainingTimers();
                     _this.sandbox[app_id] = undefined;
                 } else {
                     console.log('UI service has been stopped.');