2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 var JSON_ = xwalk.JSON;
18 var validator_ = xwalk.utils.validator;
19 var types_ = validator_.Types;
20 var type_ = xwalk.utils.type;
21 var converter_ = xwalk.utils.converter;
22 var privUtils_ = xwalk.utils;
28 extension.setMessageListener(function(json) {
29 var msg = JSON_.parse(json);
30 var listeners = callbacks[msg['local_port_id']];
33 privUtils_.log('Listeners length:' + listeners.length);
35 if (!msg.hasOwnProperty('remotePort')) rmp = null;
36 else rmp = new RemoteMessagePort(msg.remotePort, msg.remoteAppId, msg.trusted);
37 for (var i = 0; i < listeners.length; i++) {
41 }.bind(null, listeners[i][0]),
47 function nextCallbackId() {
52 UnknownError: WebAPIException.UNKNOWN_ERR,
53 TypeMismatchError: WebAPIException.TYPE_MISMATCH_ERR,
54 InvalidValuesError: WebAPIException.INVALID_VALUES_ERR,
55 IOError: WebAPIException.IO_ERR,
56 ServiceNotAvailableError: WebAPIException.SERVICE_NOT_AVAILABLE_ERR,
57 SecurityError: WebAPIException.SECURITY_ERR,
58 NetworkError: WebAPIException.NETWORK_ERR,
59 NotSupportedError: WebAPIException.NOT_SUPPORTED_ERR,
60 NotFoundError: WebAPIException.NOT_FOUND_ERR,
61 InvalidAccessError: WebAPIException.INVALID_ACCESS_ERR,
62 AbortError: WebAPIException.ABORT_ERR,
63 QuotaExceededError: WebAPIException.QUOTA_EXCEEDED_ERR
66 function callNative(cmd, args) {
67 var json = { cmd: cmd, args: args };
68 var argjson = JSON_.stringify(json);
69 var resultString = extension.internal.sendSyncMessage(argjson);
70 var result = JSON_.parse(resultString);
72 if (typeof result !== 'object') {
73 throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
76 if (result['status'] == 'success') {
77 if (result['result']) {
78 return result['result'];
81 } else if (result['status'] == 'error') {
82 var err = result['error'];
84 if (ExceptionMap[err.name]) {
85 throw new WebAPIException(ExceptionMap[err.name], err.message);
87 throw new WebAPIException(WebAPIException.UNKNOWN_ERR, err.message);
94 function callNativeWithCallback(cmd, args, callback) {
96 var id = nextCallbackId();
97 args['callbackId'] = id;
98 callbacks[id] = callback;
101 return callNative(cmd, args);
104 function SetReadOnlyProperty(obj, n, v) {
105 Object.defineProperty(obj, n, { value: v, writable: false });
108 function MessagePortManager() {
109 // constructor of MessagePortManager
112 MessagePortManager.prototype.requestLocalMessagePort = function(localMessagePortName) {
113 var args = validator_.validateArgs(arguments, [
114 { name: 'localMessagePortName', type: types_.STRING }
117 if ('' === args.localMessagePortName) {
118 throw new WebAPIException(
119 WebAPIException.INVALID_VALUES_ERR,
120 'Port name cannot be empty.'
126 localMessagePortName: args.localMessagePortName
130 localPortId = callNative(
131 'MessagePortManager_requestLocalMessagePort',
138 var returnObject = new LocalMessagePort(args.localMessagePortName, false);
139 ports[nativeParam.localMessagePortName] = localPortId;
144 MessagePortManager.prototype.requestTrustedLocalMessagePort = function(
147 var args = validator_.validateArgs(arguments, [
148 { name: 'localMessagePortName', type: types_.STRING }
151 if ('' === args.localMessagePortName) {
152 throw new WebAPIException(
153 WebAPIException.INVALID_VALUES_ERR,
154 'Port name cannot be empty.'
159 localMessagePortName: args.localMessagePortName
163 var localPortId = callNative(
164 'MessagePortManager_requestTrustedLocalMessagePort',
171 var returnObject = new LocalMessagePort(args.localMessagePortName, true);
172 ports[nativeParam.localMessagePortName] = localPortId;
177 MessagePortManager.prototype.requestRemoteMessagePort = function(
179 remoteMessagePortName
181 var args = validator_.validateArgs(arguments, [
182 { name: 'appId', type: types_.STRING },
183 { name: 'remoteMessagePortName', type: types_.STRING }
188 remoteMessagePortName: args.remoteMessagePortName
192 var syncResult = callNative(
193 'MessagePortManager_requestRemoteMessagePort',
200 var returnObject = new RemoteMessagePort(
201 args.remoteMessagePortName,
209 MessagePortManager.prototype.requestTrustedRemoteMessagePort = function(
211 remoteMessagePortName
213 var args = validator_.validateArgs(arguments, [
214 { name: 'appId', type: types_.STRING },
215 { name: 'remoteMessagePortName', type: types_.STRING }
220 remoteMessagePortName: args.remoteMessagePortName
224 var syncResult = callNative(
225 'MessagePortManager_requestTrustedRemoteMessagePort',
232 var returnObject = new RemoteMessagePort(
233 args.remoteMessagePortName,
241 function LocalMessagePort(messagePortName, isTrusted) {
242 Object.defineProperties(this, {
243 messagePortName: { value: messagePortName, writable: false, enumerable: true },
244 isTrusted: { value: !!isTrusted, writable: false, enumerable: true }
248 LocalMessagePort.prototype.addMessagePortListener = function(listener) {
249 var args = validator_.validateArgs(arguments, [
250 { name: 'listener', type: types_.FUNCTION, nullable: false }
253 var portId = ports[this.messagePortName];
255 if (!callbacks.hasOwnProperty(portId)) callbacks[portId] = [];
258 callbacks[portId].push([listener, callbackId]);
263 LocalMessagePort.prototype.removeMessagePortListener = function(watchId) {
264 var args = validator_.validateArgs(arguments, [
265 { name: 'watchId', type: types_.LONG, nullable: false, optional: false }
269 var listeners = callbacks[ports[this.messagePortName]];
271 for (var key in listeners) {
272 var listenerId = listeners[key][1];
273 if (watchId == listenerId) {
279 if (typeof toDelete === 'undefined')
280 throw new WebAPIException(
281 WebAPIException.NOT_FOUND_ERR,
282 'The port of the target application is not found.'
285 listeners.splice(toDelete, 1);
288 function RemoteMessagePort(messagePortName, appId, isTrusted) {
289 Object.defineProperties(this, {
290 messagePortName: { value: messagePortName, writable: false },
291 appId: { value: appId, writable: false },
292 isTrusted: { value: !!isTrusted, writable: false }
296 function _isOctet(valArray) {
297 for (var i = 0; i < valArray.length; i++) {
298 if (valArray[i] < 0 || valArray[i] > 255) {
305 RemoteMessagePort.prototype.sendMessage = function() {
306 var args = validator_.validateArgs(arguments, [
307 { name: 'data', type: types_.ARRAY },
309 name: 'localMessagePort',
310 type: types_.PLATFORM_OBJECT,
313 values: LocalMessagePort
317 var filtered_data = new Array(args.data.length);
318 var unique_data_key = {};
319 var data_length = args.data.length;
320 for (var i = 0; i < data_length; i++) {
321 if (!args.data[i].hasOwnProperty('key')) {
322 throw new WebAPIException(
323 WebAPIException.INVALID_VALUES_ERR,
324 'MessagePortDataItem should contain \'key\' property.'
327 var key = args.data[i].key;
329 throw new WebAPIException(
330 WebAPIException.INVALID_VALUES_ERR,
331 'Property \'key\' should not be empty.'
334 if (true === unique_data_key[key]) {
335 throw new WebAPIException(
336 WebAPIException.INVALID_VALUES_ERR,
337 'Property \'key\' should not be duplicated.'
340 var value = args.data[i].value;
341 if (type_.isString(value)) {
342 filtered_data[i] = { key: key, value: value, valueType: 'stringValueType' };
343 } else if (type_.isArray(value)) {
344 var arrayMember = value[0];
345 if (type_.isString(arrayMember)) {
346 for (var j = 1; j < value.length; j++) {
347 if (!type_.isString(value[j])) {
348 throw new WebAPIException(
349 WebAPIException.INVALID_VALUES_ERR,
350 'Invalid array value'
357 valueType: 'stringArrayValueType'
359 } else if (!type_.isArray(arrayMember)) {
360 if (!_isOctet(value)) {
361 throw new WebAPIException(
362 WebAPIException.INVALID_VALUES_ERR,
363 'Data is not octet array'
369 valueType: 'byteStreamValueType'
372 for (var j = 0; j < value.length; j++) {
373 if (!_isOctet(value[j])) {
374 throw new WebAPIException(
375 WebAPIException.INVALID_VALUES_ERR,
376 'Data is not octet array'
383 valueType: 'byteStreamArrayValueType'
387 // convert any other value to string -> backward compatibility
390 value: converter_.toString(value),
391 valueType: 'stringValueType'
394 unique_data_key[key] = true;
399 messagePortName: this.messagePortName,
401 trusted: this.isTrusted,
402 local_port_id: args.localMessagePort
403 ? ports[args.localMessagePort.messagePortName]
407 var syncResult = callNative('RemoteMessagePort_sendMessage', nativeParam);
410 exports = new MessagePortManager();