[Tizen 7.5 Migration][Service] Only apply tizen.alarm.getAll() in daemon mode
[platform/framework/web/wrtjs.git] / wrt_app / service / service_manager.ts
index b11e12a..4209af3 100644 (file)
@@ -5,34 +5,77 @@ import * as XWalkExtension from '../common/wrt_xwalk_extension';
 interface WorkerMap {
   [id: string]: any;
 }
+
+interface MessageObserver {
+  [id: string]: Set<string>;
+}
+
 let workers: WorkerMap = {};
+let dyingWorkerQueue: WorkerMap = {};
+let messageObservers: MessageObserver = {};
 
 Object.defineProperty(global, 'serviceType', {
   value: wrt.getServiceModel(),
   writable: false
 });
 
+function checkDyingWorker() {
+  let dyingWorkers = Object.keys(dyingWorkerQueue);
+  if (dyingWorkers.length) {
+    let workerId = dyingWorkers[0];
+    if (dyingWorkerQueue[workerId] === 'will-terminate') {
+      dyingWorkerQueue[workerId] = 'terminated';
+      workers[workerId].terminate();
+    }
+  }
+}
+
+function IsDyingWorker(id: string) {
+  let dyingWorkers = Object.keys(dyingWorkerQueue);
+  if (dyingWorkers.length && dyingWorkerQueue[id]) {
+    return ((dyingWorkerQueue[id] === 'will-terminate') ||
+            (dyingWorkerQueue[id] === 'terminated'))
+  }
+  return false;
+}
+
 function createWorker(id: string, startService: string, filename: string) {
   if (workers[id]) {
     workers[id].postMessage({ type: 'wake' });
     return;
   }
 
+  wrt.tv?.serviceMount(id);
   workers[id] = new Worker(startService, {
     workerData: {
       id,
       filename
     }
   });
-  workers[id].on('message', (message: string) => {
-    if (message === 'will-terminate') {
-      workers[id].terminate();
+  workers[id].on('message', (message: any) => {
+    switch (message.type) {
+      case 'will-terminate':
+        delete messageObservers[id];
+        dyingWorkerQueue[id] = 'will-terminate';
+        checkDyingWorker();
+        break;
+      case 'register-message':
+        if (!messageObservers[id]) {
+          messageObservers[id] = new Set();
+        }
+        messageObservers[id].add(message.listener);
+        break;
+      default:
+        break;
     }
   });
   workers[id].on('exit', (code: number) => {
+    wrt.tv?.serviceUmount(id);
+    delete dyingWorkerQueue[id];
     delete workers[id];
     let runningServices = Object.keys(workers);
-    console.debug(`exit code(${code}), remain services(${runningServices})`);
+    console.debug(`${id} terminated, remain services(${runningServices})`);
+    checkDyingWorker();
   });
 }
 
@@ -45,25 +88,31 @@ function terminateWorker(id: string, delay: number) {
   workers[id].postMessage({ type: 'stop', delay });
 }
 
-let initializeExtensionOnMain = () => {
-  initializeExtensionOnMain = () => {};
+let initializeExtensionOnMain = (id: string) => {
+  initializeExtensionOnMain = (id: string) => {};
   XWalkExtension.initialize();
   // This is workaround solution to make webapis's singleton worker, which has
   // same smack label with pid's.
   // It must be handled ahead of dropThreadPrivilege()
   // Otherwise, smack violation might hanppen from 'libdbuspolicy'.
   global.tizen.systeminfo.getPropertyValue("CPU", () => { }, () => { });
-}
-
-export function startService(id: string, filename: string) {
-  console.debug(`startService - ${id}`);
-  initializeExtensionOnMain();
-  if (global['serviceType'] === 'STANDALONE') {
+  if (global['serviceType'] !== 'STANDALONE') {
+    global.tizen.alarm.getAll();
+  } else {
     let ids = id.split(':');
     let serviceId = ids[0];
     let packageId = serviceId.split('.')[0];
     wrt.security?.dropThreadPrivilege(packageId, serviceId);
   }
+}
+
+export function startService(id: string, filename: string) {
+  if(IsDyingWorker(id)) {
+    console.debug(`startService - ${id} is in stop status, skip start`);
+    return;
+  }
+  console.debug(`startService - ${id}`);
+  initializeExtensionOnMain(id);
   let startService = `${__dirname}/service_runner.js`;
   createWorker(id, startService, filename);
 }
@@ -86,4 +135,16 @@ export function handleBuiltinService(serviceId: string, serviceName: string) {
     let startService = `${__dirname}/../service/builtins/${serviceName}.js`;
     createWorker(serviceId, startService, '');
   }
+}
+
+export function notifyMessage(listener: string, data: string) {
+  for (const id in messageObservers) {
+    if (messageObservers[id].has(listener)) {
+      console.debug(`notify message - ${listener}`);
+      if (workers[id]) {
+        const notification = { listener, data };
+        workers[id].postMessage({ type: 'notify-message', notification });
+      }
+    }
+  }
 }
\ No newline at end of file