[DeviceHome] Upgrade to v1.0.8 20/263220/1 submit/tizen/20210830.004712
authorYoungsoo Choi <kenshin.choi@samsung.com>
Mon, 30 Aug 2021 00:02:45 +0000 (17:02 -0700)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Mon, 30 Aug 2021 00:05:07 +0000 (17:05 -0700)
- Send package ID to remote client
- Don'y use hard-coded package ID
- Update webclip icon on remote client when webclip is installed
- Fix bugs for sending messages

Change-Id: I8086ff1d13c046e5049904375655197f34832d4b
Signed-off-by: Youngsoo Choi <kenshin.choi@samsung.com>
device_home/service/app_proxy.js
device_home/service/app_router.js
device_home/service/relay-server.js
device_home/service/service.js

index a27fb27..1cd814c 100755 (executable)
@@ -66,7 +66,7 @@ module.exports = function (app, port) {
                 appRouters.push({
                     path: path,
                     name: name,
-                    router: new AppRouter(app, path)
+                    router: new AppRouter(app, path, appId, pkgId)
                 });
             }
             console.log('[GlobalWebServer] appProxy.post ', path, action);
index 4aba0a3..b95b198 100755 (executable)
@@ -8,7 +8,7 @@ const platform_app_path = is_tv ? '/opt/usr/apps' : '/opt/usr/globalapps';
 const platform_shared_path = '/shared/res/client';
 
 class AppRouter {
-    constructor(app, app_path) {
+    constructor(app, app_path, appId, pkgId) {
         const appRouter = express.Router();
         const client_path = path.join(platform_app_path, app_path, platform_shared_path);
         console.log(`${TAG} static client path : ${client_path}`);
@@ -18,6 +18,8 @@ class AppRouter {
             console.log(`${TAG} req.baseUrl : ${req.baseUrl}`);
             const urlParam = require('./service').getUrlParam();
             let urlObj = url.parse(urlParam, true).query;
+            urlObj.appId = appId;
+            urlObj.pkgId = pkgId;
             let url_format = {
                 pathname: 'client.html',
                 query: urlObj
index f8ea8ad..3bd650d 100755 (executable)
@@ -10,6 +10,7 @@ const TAG_HOST = `${TAG}[Host]`;
 const TAG_CLIENT = `${TAG}[Client]`;
 const TO_ALL = 100;
 
+let wsServer = undefined;
 let receiver = {};
 let sender = {};
 let remoteClients = {};
@@ -65,6 +66,8 @@ var OnReceived = function (msg) {
             return;
         }
         const id = msg.id;
+        const secure = msg.secure;
+        msg = JSON.stringify(msg);
         if (id === -1) {
             console.log(`${TAG_HOST}[OnReceived] Handle message only on relay server`);
             // Do what need to handle in relay server only
@@ -75,14 +78,12 @@ var OnReceived = function (msg) {
             console.log(`${TAG_HOST}[OnReceived] Send message to all web sockets`);
             console.log(`${TAG_HOST}[OnReceived] remoteClients length : ${remoteClients[pkgId].length}`);
             for (let client of remoteClients[pkgId]) {
-                if (msg.secure) {
-                    msg = encrypt(JSON.stringify(msg), client, pkgId, globalClientPublicKeys);
+                if (secure) {
+                    msg = encrypt(msg, client, pkgId, globalClientPublicKeys);
                     if (msg === false || msg === null) {
                         console.log(`${TAG_HOST}[OnReceived] Failed to encrypt message!`);
                         return;
                     }
-                } else {
-                    msg = JSON.stringify(msg);
                 }
                 console.log(`${TAG_HOST}[OnReceived] msg : ${msg}`);
                 client.emit('d2d_message', msg);
@@ -90,14 +91,12 @@ var OnReceived = function (msg) {
         } else {
             console.log(`${TAG_HOST}[OnReceived] Send message to a web socket #${id}`);
             if (id < remoteClients[pkgId].length) {
-                if (msg.secure) {
-                    msg = encrypt(JSON.stringify(msg), remoteClients[pkgId][id], pkgId, globalClientPublicKeys);
+                if (secure) {
+                    msg = encrypt(msg, remoteClients[pkgId][id], pkgId, globalClientPublicKeys);
                     if (msg === false || msg === null) {
                         console.log(`${TAG_HOST}[OnReceived] Failed to encrypt message!`);
                         return;
                     }
-                } else {
-                    msg = JSON.stringify(msg);
                 }
                 console.log(`${TAG_HOST}[OnReceived] msg : ${msg}`);
                 remoteClients[pkgId][id].emit('d2d_message', msg);
@@ -252,13 +251,19 @@ var addConnection = function(wsServer, pkgId, sessionMiddleware, clientPublicKey
         }
     });
 }
-var RelayServer = function(httpserver, dataApps, sessionMiddleware, clientPublicKeys) {
-    const wsServer = io.listen(httpserver, {
-        log: true,
-        origins: '*:*'
-    });
-    for (var j = 0; j < dataApps.length; j++) {
-        addConnection(wsServer, dataApps[j].d2dApp.pkgId, sessionMiddleware, clientPublicKeys);
+var RelayServer = function(httpserver, dataApps, sessionMiddleware, clientPublicKeys, pkgId) {
+    if (wsServer === undefined) {
+        wsServer = io.listen(httpserver, {
+            log: true,
+            origins: '*:*'
+        });
+    }
+    if (pkgId === undefined) {
+        for (var j = 0; j < dataApps.length; j++) {
+            addConnection(wsServer, dataApps[j].d2dApp.pkgId, sessionMiddleware, clientPublicKeys);
+        }
+    } else {
+        addConnection(wsServer, pkgId, sessionMiddleware, clientPublicKeys);
     }
 };
 
index 69b47ff..9997cb9 100755 (executable)
@@ -1,13 +1,13 @@
-"use strict";
+'use strict';
 
 const express = require('express');
 const http = require('http');
-const path = require("path");
+const path = require('path');
 const relayServer = require('./relay-server.js');
 const session = require('express-session');
 const cookieParser = require('cookie-parser');
 const EventEmitter = require('events');
-const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
+const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
 const crypto = require('crypto');
 const { Security } = require('./security.js');
 const JSEncryptLib = require('./jsencrypt');
@@ -59,10 +59,10 @@ function addD2Ddata(pkgId, appId, appName, iconPath) {
   let metaAppID = '';
   let metaDataArray = tizen.application.getAppMetaData(appId);
   metaDataArray = metaDataArray.filter(function(metaData) {
-    if (metaData.key !== "d2dservice")
+    if (metaData.key !== 'd2dservice')
       return false;
 
-    if (metaData.value !== "enable")
+    if (metaData.value !== 'enable')
       metaAppID = metaData.value;
     return true;
   });
@@ -113,86 +113,105 @@ function promiseGetAppList() {
   })
 }
 
-function getWebclipsManifestByApp(app, callback) {
-  var fileHandle,
-    filePath = path.join(app.path, WEBCLIP_DIRECTORY, WEBCLIP_MANIFEST),
-    data,
-    skipMainDir = false;
-
-  app.webclips = [];
-  console.log(`${TAG} webclip path : ${filePath}`);
-  try {
-    fileHandle = tizen.filesystem.openFile(filePath, "r");
-  } catch (err) {
-    skipMainDir = true;
-    console.log(`${TAG} tizen.filesystem.openFile (error): ${filePath} ${err}`);
-    // check subdirectories
-    tizen.filesystem.listDirectory(path.join(app.path, WEBCLIP_DIRECTORY), function (dirs) {
+function checkWebclipSubDirectories(app, data, callback) {
+  return new Promise(resolve => {
+    tizen.filesystem.listDirectory(path.join(app.path, WEBCLIP_DIRECTORY), function(dirs) {
       dirs.forEach(function (directory) {
-        filePath = path.join(app.path, WEBCLIP_DIRECTORY, directory, WEBCLIP_MANIFEST);
-        fileHandle = tizen.filesystem.openFile(filePath, "r");
+        const filePath = path.join(app.path, WEBCLIP_DIRECTORY, directory, WEBCLIP_MANIFEST);
+        console.log(`${TAG} webclip path : ${filePath}`);
+        const fileHandle = tizen.filesystem.openFile(filePath, 'r');
 
         if (fileHandle) {
           try {
             data = fileHandle.readString();
-            data = data.replace(/\n/g, "");
+            data = data.replace(/\n/g, '');
             data = JSON.parse(data);
 
             app.webclips.push({
               manifest: data,
               path: path.join(app.path, WEBCLIP_DIRECTORY, directory),
             });
-          } catch (error) {
-            console.log("[GlobalWebServer] fileHandle.readString (error): ", error);
+          } catch (err) {
+            console.log(`${TAG} fileHandle.readString directory (error): ${err}`);
           }
-
           fileHandle.close();
         }
       });
-      if (typeof callback === "function") {
+      if (typeof callback === 'function') {
         callback();
       }
+      resolve(true);
+    }, function(err) {
+      console.log(`${TAG} ${err}`);
+      resolve(false);
     });
-  }
+  });
+}
 
-  if (fileHandle && !skipMainDir) {
-    try {
-      data = fileHandle.readString();
-      data = data.replace(/\n/g, "");
-      data = JSON.parse(data);
+function getWebclipManifestsByApp(app, callback) {
+  return new Promise(async resolve => {
+    const filePath = path.join(app.path, WEBCLIP_DIRECTORY, WEBCLIP_MANIFEST);
+    console.log(`${TAG} webclip path : ${filePath}`);
+    let data = '';
+    let fileHandle = undefined;
+    let skipMainDir = false;
+    app.webclips = [];
 
-      app.webclips.push({
-        manifest: data,
-        path: path.join(app.path, WEBCLIP_DIRECTORY)
-      });
+    try {
+      fileHandle = tizen.filesystem.openFile(filePath, 'r');
     } catch (err) {
-      console.log(`${TAG} fileHandle.readString (error): ${err}`);
+      skipMainDir = true;
+      console.log(`${TAG} No manifest in main directory : ${err}`);
+      // check subdirectories
+      console.log(`${TAG} Check subdirectories`);
+      await checkWebclipSubDirectories(app, data, callback);
     }
-    fileHandle.close();
 
-    if (typeof callback === "function") {
-      callback();
+    if (fileHandle && !skipMainDir) {
+      try {
+        data = fileHandle.readString();
+        data = data.replace(/\n/g, '');
+        data = JSON.parse(data);
+
+        app.webclips.push({
+          manifest: data,
+          path: path.join(app.path, WEBCLIP_DIRECTORY)
+        });
+      } catch (err) {
+        console.log(`${TAG} fileHandle.readString (error): ${err}`);
+      }
+      fileHandle.close();
+
+      if (typeof callback === 'function') {
+        callback();
+      }
     }
-  }
+    resolve(true);
+  });
 }
 
 function getWebclipsManifest() {
   dataApps.forEach(
-    getWebclipsManifestByApp
+    getWebclipManifestsByApp
   );
 }
 
 function setPackageInfoEventListener() {
   const packageEventCallback = {
-    oninstalled: function(packageInfo) {
+    oninstalled: async function(packageInfo) {
       console.log(`${TAG} The package ${packageInfo.name} is installed`);
       const app = addD2Ddata(packageInfo.id, packageInfo.appIds[0], packageInfo.name, packageInfo.iconPath);
       if (app.path !== undefined) {
-        getWebclipsManifestByApp(app, function () {
-          evtEmit.emit("updateapplist", "message", dataApps);
+        // only for webclip
+        await getWebclipManifestsByApp(app, function () {
+          console.log(`${TAG} Webclip has been updated`);
         });
+        console.log(`${TAG} Emit app list`);
+        // for both companion and webclip
+        evtEmit.emit('updateapplist', 'message', dataApps);
+        relayServer(httpserver, dataApps, sessionMiddleware, clientPublicKeys, packageInfo.id);
       } else {
-        evtEmit.emit("updateapplist", "message", dataApps);
+        evtEmit.emit('updateapplist', 'message', dataApps);
       }
     },
     onupdated: function(packageInfo) {
@@ -201,7 +220,7 @@ function setPackageInfoEventListener() {
     onuninstalled: function(packageId) {
       console.log(`${TAG} The package ${packageId} is uninstalled`);
       removeD2Ddata(packageId);
-      evtEmit.emit("updateapplist", "message", dataApps);
+      evtEmit.emit('updateapplist', 'message', dataApps);
     }
   };
   tizen.package.setPackageInfoEventListener(packageEventCallback);
@@ -317,11 +336,11 @@ async function displayPincode(req) {
   // Generate RSA keys
   await security.awaitKeyPair(req);
   // Show pincode popup
-  webapis.postPlainNotification("Input Pincode: ", req.session.pincode, 10);
+  webapis.postPlainNotification('Input Pincode: ', req.session.pincode, 10);
 }
 
 function getIp(rawIp) {
-  return rawIp.slice(rawIp.lastIndexOf(":") + 1);
+  return rawIp.slice(rawIp.lastIndexOf(':') + 1);
 }
 
 var HTTPserverStart = function() {
@@ -441,7 +460,7 @@ var HTTPserverStart = function() {
     console.log(`${TAG} get(/updateWebclip)`);
     const apps = getWebClipsList();
     const result = {
-      type: "full",
+      type: 'full',
       data: {
         apps: apps
       }
@@ -463,26 +482,26 @@ var HTTPserverStart = function() {
     urlParam = req.originalUrl;
 
     if (!DEMO_MODE) {
-      res.redirect("/pincode/pincode.html");
+      res.redirect('/pincode/pincode.html');
     } else {
       console.log(`${TAG} Set session ip and RSA keys in WT mode`);
       req.session.ip = getIp(req.socket.remoteAddress);
       await security.awaitKeyPair(req);
       if (req.query.roomId !== undefined) {
         // FIXME: Remove app logic here
-        res.render("client/invited.html");
+        res.render('client/invited.html');
       } else if (req.query.pageUrl !== undefined) {
         if (typeof webapis.mde !== 'undefined')
           webapis.mde.launchBrowserFromUrl(req.query.pageUrl);
       } else {
         // Device home
-        res.render("client/client.html");
+        res.render('client/client.html');
       }
     }
   });
 
   app.get('/d2dIcon/*', (req, res) => {
-    let fullPath = req.originalUrl.replace("d2dIcon", platform_app_path);
+    let fullPath = req.originalUrl.replace('d2dIcon', platform_app_path);
     res.sendFile(fullPath);
   });
 
@@ -496,8 +515,8 @@ var HTTPserverStart = function() {
       'Cache-Control': 'no-cache',
       'Connection': 'keep-alive'
     });
-    evtEmit.on("updateapplist", (event, data) => {
-      res.write("event: " + String(event) + "\n" + "data: " + JSON.stringify(data) + "\n\n");
+    evtEmit.on('updateapplist', (event, data) => {
+      res.write('event: ' + String(event) + '\n' + 'data: ' + JSON.stringify(data) + '\n\n');
     });
   });
 
@@ -530,7 +549,7 @@ var HTTPserverStart = function() {
   app.post('/d2d', (req, res) => {
     if (req.session.ip !== undefined) {
       console.log(`${TAG} client.html`);
-      res.render("client/client.html");
+      res.render('client/client.html');
     } else {
       console.log(`${TAG} no client.html`);
       res.redirect(401, PUBLIC_DOMAIN);
@@ -540,7 +559,7 @@ var HTTPserverStart = function() {
   // receive data or cmd to app on device
   app.post('/app', (req, res) => {
     res.send({
-      result: "ok"
+      result: 'ok'
     });
   });
 
@@ -597,7 +616,7 @@ module.exports.onStop = function() {
     console.log(`${TAG} Server Terminated`);
   }
   unsetPackageInfoEventListener();
-  evtEmit.off("updateapplist");
+  evtEmit.off('updateapplist');
   console.log(`${TAG} onStop is called in DNS Resolver`);
 };