Merge "[Service][UI] Expose primitives and standard objects" into tizen_5.5 accepted/tizen/5.5/unified/20191120.034626 submit/tizen_5.5/20191113.071758 submit/tizen_5.5/20191114.074818 submit/tizen_5.5/20191115.025402 submit/tizen_5.5/20191118.004004
authorjaekuk lee <juku1999@samsung.com>
Wed, 13 Nov 2019 04:44:49 +0000 (04:44 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Wed, 13 Nov 2019 04:44:49 +0000 (04:44 +0000)
wrt_app/service/plugins.json [new file with mode: 0644]
wrt_app/service/tizen_extension.js [new file with mode: 0644]
wrt_app/service/wrt_service_extension.js [new file with mode: 0644]
wrt_app/src/runtime.js
wrt_app/src/web_application.js

diff --git a/wrt_app/service/plugins.json b/wrt_app/service/plugins.json
new file mode 100644 (file)
index 0000000..ba82e28
--- /dev/null
@@ -0,0 +1,52 @@
+[
+  {
+    "name":"tizen.filesystem",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_filesystem.so",
+    "entry_points": []
+  },
+  {
+    "name":"tizen.messageport",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_messageport.so",
+    "entry_points": []
+  },
+  {
+    "name":"tizen",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen.so",
+    "entry_points": []
+  },
+  {
+    "name":"tizen.datacontrol",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_datacontrol.so",
+    "entry_points": []
+  },
+  {
+    "name":"tizen.application",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_application.so",
+    "entry_points": ["tizen.ApplicationControl","tizen.ApplicationControlData"]
+  },
+  {
+    "name":"tizen.time",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_time.so",
+    "entry_points": ["tizen.TZDate","tizen.TimeDuration"]
+  },
+  {
+    "name":"xwalk",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_utils.so",
+    "entry_points": []
+  },
+  {
+    "name":"tizen.systeminfo",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_systeminfo.so",
+    "entry_points": []
+  },
+  {
+    "name":"tizen.package",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_package.so",
+    "entry_points": []
+  },
+  {
+    "name":"tizen.alarm",
+    "lib":"/usr/lib/tizen-extensions-crosswalk/libtizen_alarm.so",
+    "entry_points": ["tizen.AlarmRelative","tizen.AlarmAbsolute"]
+  }
+]
diff --git a/wrt_app/service/tizen_extension.js b/wrt_app/service/tizen_extension.js
new file mode 100644 (file)
index 0000000..6e80497
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+(function() {
+const extension = require('./wrt_service_extension');
+const wrt = require('../browser/wrt');
+var window = global;
+var api_ = {};
+var extensions_ = {};
+var runtime_variables_ = {'runtime_name': 'wrt-service'};
+
+var ExtensionLoader = function() {
+  let plugins = require('./plugins.json');
+  extension.initialize(runtime_variables_);
+
+  var extensions = extension.getExtensions();
+  for (var i = 0; i < extensions.length; i++) {
+    extensions[i].loaded = false;
+    for (var idx in plugins) {
+      if (extensions[i].name === plugins[idx].name) {
+        console.log("ExtensionLoader name " + extensions[i].name);
+        extensions_[extensions[i].name] = extensions[i];
+      }
+    }
+  }
+  for (var name in extensions_) {
+    if (!extensions_[name].use_trampoline) {
+      this.load(extensions_[name]);
+    }
+  }
+  for (var name in extensions_) {
+    if (extensions_[name].use_trampoline) {
+      this.installTrampoline(extensions_[name]);
+    }
+  }
+};
+
+ExtensionLoader.prototype = {
+  /**
+   * Creates namespace for 'name' in given object.
+   * Eg. this.createNamespace(GLOBAL, 'tizen.contact') will create:
+   * GLOBAL.tizen.contact = {}
+   *
+   * @param {Object} object
+   * @param {String} name
+   */
+  createNamespace: function(object, name) {
+    var obj = object;
+    var arr = name.split('.');
+    for (var i = 0; i < arr.length; i++) {
+      obj[arr[i]] = obj[arr[i]] || {};
+      obj = obj[arr[i]];
+    }
+  },
+  exposeApi: function (ext) {
+    var i, entry_points, entry_point, tmp, parent_name, base_name;
+
+    // additional entry points are installed in GLOBAL context by eval()
+    // so we need to move it to protected api_ object first
+    entry_points = [...new Set(ext.entry_points)];
+    for (i = 0; i < entry_points.length; i++) {
+      entry_point = entry_points[i];
+      tmp = entry_point.split('.');
+      parent_name = tmp[0];
+      base_name = tmp[tmp.length - 1];
+
+      api_[parent_name][base_name] = GLOBAL[parent_name][base_name];
+      delete GLOBAL[parent_name][base_name];
+    }
+
+    entry_points.push(ext.name);
+
+    for (i = 0; i < entry_points.length; i++) {
+      entry_point = entry_points[i];
+      tmp = entry_point.split('.');
+      parent_name = tmp[0];
+      base_name = tmp[tmp.length - 1];
+
+      Object.defineProperty(GLOBAL[parent_name], base_name, {
+        get: function (parent_name, base_name) {
+          return function () {
+              return api_[parent_name][base_name];
+          }
+        }(parent_name, base_name),
+        configurable: false,
+        enumerable: true
+      });
+    }
+  },
+
+  /**
+   * @param {Object} ext
+   */
+  load: function(ext) {
+    if (ext.loaded) {
+      return;
+    }
+    ext.loadInstance();
+
+    ext.loaded = true;
+
+    this.createNamespace(api_, ext.name);
+    this.createNamespace(GLOBAL, ext.name);
+
+    var api = (ext.use_trampoline) ? api_ : GLOBAL;
+
+    var jscode =
+      '(function(extension) {' +
+      '  extension.internal = {};' +
+      '  extension.internal.sendSyncMessage = extension.sendSyncMessage;' +
+      '  delete extension.sendSyncMessage;' +
+      '  var exports = {}; ' +
+      '  (function() {\'use strict\'; ' + ext.jsapi + '})();' +
+      '  api.' + ext.name + ' = exports; ' +
+      '});';
+
+    try {
+      var func = eval(jscode);
+      func({
+        postMessage: function(msg) {
+          return ext.postMessage(msg);
+        },
+        sendSyncMessage: function(msg) {
+          return ext.sendSyncMessage(msg);
+        },
+        setMessageListener: function(fn) {
+          return ext.setMessageListener(fn);
+        },
+        sendRuntimeMessage: function(type, data) {
+          return runtimeMessageHandler(type, data);
+        },
+        sendRuntimeSyncMessage: function(type, data) {
+          return runtimeMessageHandler(type, data);
+        },
+        sendRuntimeAsyncMessage: function(type, data, callback) {
+          return runtimeMessageHandler(type, data, callback);
+        },
+        postData: function(msg, chunk) {
+          return ext.postData(msg, chunk);
+        },
+        sendSyncData: function(msg, chunk) {
+          return ext.sendSyncData(msg, chunk);
+        },
+        setDataListener: function(fn) {
+          return ext.setDataListener(fn);
+        },
+        receiveChunkData: function(id, type) {
+          return ext.receiveChunkData(id, type);
+        }
+      });
+
+      if (ext.use_trampoline) {
+        this.exposeApi(ext);
+      }
+    } catch (err) {
+      console.log('Error loading extension "' + ext.name + '": ' + err.message);
+    }
+  },
+
+  /**
+   * This is used to defer extension loading to it's first usage.
+   * Eg. First access to tizen.contact will load extension's 'jsapi' through eval().
+   *
+   * @param {Object} ext
+   */
+  installTrampoline: function(ext) {
+    var entry_points = [...new Set(ext.entry_points)];
+    entry_points.push(ext.name);
+    for (var i = 0; i < entry_points.length; i++) {
+      var tmp = entry_points[i].split('.');
+      var parent_name = tmp[0];
+      var base_name = tmp[tmp.length - 1];
+
+      this.createNamespace(GLOBAL, entry_points[i]);
+
+      Object.defineProperty(GLOBAL[parent_name], base_name, {
+        get: function (parent_name, base_name) {
+          return function() {
+            try {
+              this.deleteTrampoline(ext);
+              this.load(ext);
+              return api_[parent_name][base_name];
+            } catch (e) {
+              console.log(e.stack);
+            }
+          }.bind(this);
+        }.call(this, parent_name, base_name),
+        enumerable: true
+      });
+    }
+  },
+
+  deleteTrampoline: function(ext) {
+    var entry_points = [...new Set(ext.entry_points)];
+    entry_points.push(ext.name);
+
+    for (var i = 0; i < entry_points.length; i++) {
+      var tmp = entry_points[i].split('.');
+      var parent_name = tmp[0];
+      var base_name = tmp[tmp.length - 1];
+      delete GLOBAL[parent_name][base_name];
+    }
+  }
+};
+
+new ExtensionLoader();
+})();
diff --git a/wrt_app/service/wrt_service_extension.js b/wrt_app/service/wrt_service_extension.js
new file mode 100644 (file)
index 0000000..8207706
--- /dev/null
@@ -0,0 +1,4 @@
+require('../common/exception_handling');
+const wrt_service_extension = process.binding('wrt_service_extension')
+
+module.exports = wrt_service_extension;
index 7cf447b..bb98db3 100644 (file)
@@ -21,6 +21,7 @@ const AddonManager = require('./addon_manager');
 const {app, ipcMain} = require('electron');
 const IPC_MESSAGE = require('./ipc_message');
 const TimerManager = require('../service/timer_manager');
+const TizenExtension = require('../service/tizen_extension');
 const WAS_EVENT = require('./was_event');
 const WebApplication = require('./web_application');
 
@@ -207,6 +208,7 @@ class Runtime {
                         console: console,
                         module: new Module,
                         require: require,
+                        tizen: tizen,
                     };
                     for(let key in global) {
                         _this.sandbox[app_id][key] = global[key];
index 4a2d804..289f238 100755 (executable)
@@ -55,8 +55,7 @@ class WebApplication {
         this.loadFinished = false;
         this.runningStatus = 'none';
         this.isTVProfile = (wrt.getPlatformType() === "product_tv");
-        this.defaultBackgroundColor = (this.isTVProfile
-            || (wrt.getPlatformType() === "product_wearable") ? '#000' : '#FFF');
+        this.defaultBackgroundColor = (this.isTVProfile ? '#000' : '#FFF');
         this.defaultTransparent = (this.isTVProfile ? true : false);
         this.addonEmitter = null;