[Addon] Expose a module 'addonapi' for addons usage 17/215717/4
authorsurya.kumar7 <surya.kumar7@samsung.com>
Thu, 25 Jul 2019 12:34:20 +0000 (18:04 +0530)
committersurya.kumar7 <surya.kumar7@samsung.com>
Thu, 17 Oct 2019 09:34:28 +0000 (15:04 +0530)
Add-ons can call require on 'addonapi' to receive an object
from both browser & renderer & receives addon utility functions

Change-Id: I55baec1e57f37d7efec39cef8fbacf2aab1b32b8
Signed-off-by: surya.kumar7 <surya.kumar7@samsung.com>
wrt_app/addon/browser/addonapi.js [new file with mode: 0644]
wrt_app/addon/browser/module-list.js [new file with mode: 0644]
wrt_app/addon/browser/modules/messaging.js [new file with mode: 0644]
wrt_app/addon/browser/modules/options.js [new file with mode: 0644]
wrt_app/addon/browser/modules/window.js [new file with mode: 0644]
wrt_app/addon/renderer/addonapi.js [new file with mode: 0644]
wrt_app/addon/renderer/apreload.js [new file with mode: 0644]
wrt_app/addon/renderer/module-list.js [new file with mode: 0644]
wrt_app/addon/renderer/modules/messaging.js [new file with mode: 0644]
wrt_app/src/addon_manager.js
wrt_app/src/web_application.js

diff --git a/wrt_app/addon/browser/addonapi.js b/wrt_app/addon/browser/addonapi.js
new file mode 100644 (file)
index 0000000..4a90338
--- /dev/null
@@ -0,0 +1,20 @@
+'use strict';
+
+const moduleList = require('./module-list');
+
+const memoizedGetter = (getter) => {
+  let memoizedValue = null;
+
+  return () => {
+    if (memoizedValue === null) {
+      memoizedValue = getter();
+    }
+    return memoizedValue;
+  }
+}
+
+for (const module of moduleList) {
+  Object.defineProperty(exports, module.name, {
+    get: memoizedGetter(() => require(`./modules/${module.file}.js`))
+  });
+}
diff --git a/wrt_app/addon/browser/module-list.js b/wrt_app/addon/browser/module-list.js
new file mode 100644 (file)
index 0000000..b213e0a
--- /dev/null
@@ -0,0 +1,8 @@
+'use strict'
+
+// Browser side add-on modules, please sort alphabetically
+module.exports = [
+  { name: 'messaging', file: 'messaging' },
+  { name: 'options', file: 'options' },
+  { name: 'window', file: 'window' }
+]
diff --git a/wrt_app/addon/browser/modules/messaging.js b/wrt_app/addon/browser/modules/messaging.js
new file mode 100644 (file)
index 0000000..26511c7
--- /dev/null
@@ -0,0 +1,9 @@
+'use strict';
+
+const { ipcMain } = require('electron');
+
+module.exports = {
+  on: function (channel, listener) {
+    ipcMain.on(channel, listener);
+  }
+};
\ No newline at end of file
diff --git a/wrt_app/addon/browser/modules/options.js b/wrt_app/addon/browser/modules/options.js
new file mode 100644 (file)
index 0000000..75e0d51
--- /dev/null
@@ -0,0 +1,36 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+const REPO_PATH = path.join(require('os').homedir(), 'data/electron/runtime_addon/');
+const DB_FILE = '_db.json';
+
+module.exports = {
+  get: function (addon_name, key) {
+    const DB_PATH = REPO_PATH + addon_name + DB_FILE;
+    try {
+      const fileContents = fs.readFileSync(DB_PATH);
+      const jsonObject = JSON.parse(fileContents);
+      console.log(`read value: ${JSON.stringify(jsonObject)}`);
+      return jsonObject[key];
+    } catch (err) {
+      console.log(`An error has occurred: ${err}`);
+    }
+  },
+
+  set: function (addon_name, key, value) {
+    const DB_PATH = REPO_PATH + addon_name + DB_FILE;
+    try {
+      const fileContents = fs.readFileSync(DB_PATH);
+      let jsonObject = JSON.parse(fileContents);
+      console.log(`current value: ${JSON.stringify(jsonObject)}`);
+      jsonObject[key] = value;
+      console.log(`new value: ${JSON.stringify(jsonObject)}`);
+      const jsonString = JSON.stringify(jsonObject);
+      fs.writeFileSync(DB_PATH, jsonString);
+    } catch (err) {
+      console.log(`An error has occurred: ${err}`);
+    }
+  }
+}
\ No newline at end of file
diff --git a/wrt_app/addon/browser/modules/window.js b/wrt_app/addon/browser/modules/window.js
new file mode 100644 (file)
index 0000000..c7a92f2
--- /dev/null
@@ -0,0 +1,20 @@
+'use strict';
+
+const { dialog, TopLevelWindow } = require('electron');
+
+module.exports = {
+  loadURL: function (winId, url) {
+    let window = TopLevelWindow.fromId(winId);
+    window.loadURL(url);
+  },
+
+  showMessageBox: function (winId, options) {
+    let window = TopLevelWindow.fromId(winId);
+    dialog.showMessageBox(window, options, null);
+  },
+
+  show: function (winId) {
+    let window = TopLevelWindow.fromId(winId);
+    window.show();
+  }
+}
\ No newline at end of file
diff --git a/wrt_app/addon/renderer/addonapi.js b/wrt_app/addon/renderer/addonapi.js
new file mode 100644 (file)
index 0000000..4a90338
--- /dev/null
@@ -0,0 +1,20 @@
+'use strict';
+
+const moduleList = require('./module-list');
+
+const memoizedGetter = (getter) => {
+  let memoizedValue = null;
+
+  return () => {
+    if (memoizedValue === null) {
+      memoizedValue = getter();
+    }
+    return memoizedValue;
+  }
+}
+
+for (const module of moduleList) {
+  Object.defineProperty(exports, module.name, {
+    get: memoizedGetter(() => require(`./modules/${module.file}.js`))
+  });
+}
diff --git a/wrt_app/addon/renderer/apreload.js b/wrt_app/addon/renderer/apreload.js
new file mode 100644 (file)
index 0000000..ebb0d73
--- /dev/null
@@ -0,0 +1,12 @@
+'use strict';
+
+const ADDONS_PATH = require('path').join(__dirname, 'addonapi.js');
+const Module = require('module');
+const originalResolveFilename = Module._resolveFilename;
+Module._resolveFilename = function (request, parent, isMain) {
+    if (request === 'addonapi') {
+        return ADDONS_PATH;
+    } else {
+        return originalResolveFilename(request, parent, isMain);
+    }
+}
\ No newline at end of file
diff --git a/wrt_app/addon/renderer/module-list.js b/wrt_app/addon/renderer/module-list.js
new file mode 100644 (file)
index 0000000..c65f538
--- /dev/null
@@ -0,0 +1,6 @@
+'use strict';
+
+// Renderer side add-on modules, please sort alphabetically
+module.exports = [
+  { name: 'messaging', file: 'messaging' }
+];
diff --git a/wrt_app/addon/renderer/modules/messaging.js b/wrt_app/addon/renderer/modules/messaging.js
new file mode 100644 (file)
index 0000000..40fe684
--- /dev/null
@@ -0,0 +1,13 @@
+'use strict';
+
+const { ipcRenderer } = require('electron');
+
+module.exports = {
+  on: function (channel, listener) {
+    ipcRenderer.on(channel, listener);
+  },
+
+  send: function (...args) {
+    ipcRenderer.send(args);
+  }
+}
\ No newline at end of file
index 7bfb7f14d81311f2d283eb0587d87af2bdbffbdb..aedebf469fdf899de5c985db8ab77bfd40be0e10 100644 (file)
@@ -22,6 +22,7 @@ const ADN_PATH =
           path.join(require('os').homedir(), 'data/electron/runtime_addon');
 const MANIFEST_FILE = 'manifest.json';
 const ADDONS_DB_FILE = 'addons_db.json';
+const ADDONS_PATH = path.join(__dirname, '..', 'addon', 'browser', 'addonapi.js');
 
 // A set of predefined events for addons
 let EventList = [
@@ -45,6 +46,19 @@ class AddonManager {
         this.addons_list_ = null;
         this.addons_ = null;
         this.evt_emitter_ = null;
+        this.registerAPIModule();
+    }
+
+    registerAPIModule() {
+        const Module = require('module');
+        const originalResolveFilename = Module._resolveFilename;
+        Module._resolveFilename = function (request, parent, isMain) {
+            if (request === 'addonapi') {
+                return ADDONS_PATH;
+            } else {
+                return originalResolveFilename(request, parent, isMain);
+            }
+        }
     }
 
     loadJsonDB(db_path) {
index 085239e303ee32e416b004c36e0f9032f20bbf52..8f6ae69b04fb37068a4c6a729690bc0ce0b2fc3b 100755 (executable)
@@ -21,6 +21,7 @@ const WAS_EVENT = require('./was_event');
 const wrt = require('../browser/wrt');
 const WRTWebContents = require('../browser/wrt_web_contents');
 const WRTWindow = require('../browser/wrt_window');
+const PRELOAD_PATH = require('path').join(__dirname, '..', 'addon', 'renderer', 'apreload.js');
 
 class WebApplication {
     constructor(options) {
@@ -199,7 +200,8 @@ class WebApplication {
             show: false,
             webPreferences: {
                 nodeIntegration: options.isAddonAvailable,
-                nodeIntegrationInWorker: false
+                nodeIntegrationInWorker: false,
+                preload: (options.isAddonAvailable) ? PRELOAD_PATH : undefined
             },
             webContents: WRTWebContents.create(),
             'web-preferences': {