1 // Copyright (c) 2014 Intel Corporation. All rights reserved.
2 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
6 //Object xwalk.JSON - guaranteed to not being modified by the application programmer
7 var JSON_ = {stringify: JSON.stringify, parse: JSON.parse};
11 var _enableJsLogs = false;
14 if (typeof window != 'undefined') {
17 else if (typeof global != 'undefined') {
22 * @deprecated Used only by validateArguments()
24 var signature_to_type = {
32 var DateConverter = function() {};
34 DateConverter.prototype.toTZDate = function(v, isAllDay) {
35 if (typeof v === 'number') {
42 if (!(v instanceof _global.Object)) {
47 return new tizen.TZDate(v.year, v.month - 1, v.day,
48 null, null, null, null, v.timezone || null);
50 return new tizen.TZDate(new Date(v.UTCTimestamp * 1000));
54 DateConverter.prototype.fromTZDate = function(v) {
55 if (!tizen.TZDate || !(v instanceof tizen.TZDate)) {
60 year: v.getFullYear(),
63 timezone: v.getTimezone(),
64 UTCTimestamp: v._utcTimestamp / 1000
69 var _dateConverter = new DateConverter();
75 * Cynara(since tizen 3.0) only support native privilege.
76 * simply web privilege convert native privilege for checking access.
79 ACCOUNT_READ: 'http://tizen.org/privilege/account.read',
80 ACCOUNT_WRITE: 'http://tizen.org/privilege/account.write',
81 ALARM: 'http://tizen.org/privilege/alarm.get',
82 APPLICATION_INFO: 'http://tizen.org/privilege/application.info',
83 APPLICATION_LAUNCH: 'http://tizen.org/privilege/application.launch',
84 APPMANAGER_CERTIFICATE: 'http://tizen.org/privilege/appmanager.certificate',
85 APPMANAGER_KILL: 'http://tizen.org/privilege/appmanager.kill',
86 BLUETOOTH_ADMIN: 'http://tizen.org/privilege/bluetooth.admin',
87 BLUETOOTH_GAP: 'http://tizen.org/privilege/bluetooth.gap',
88 BLUETOOTH_HEALTH: 'http://tizen.org/privilege/bluetooth.health',
89 BLUETOOTH_SPP: 'http://tizen.org/privilege/bluetooth.spp',
90 BLUETOOTHMANAGER: 'http://tizen.org/privilege/bluetoothmanager',
91 BLUETOOTH: 'http://tizen.org/privilege/bluetooth',
92 BOOKMARK_READ: 'http://tizen.org/privilege/bookmark.read',
93 BOOKMARK_WRITE: 'http://tizen.org/privilege/bookmark.write',
94 CALENDAR_READ: 'http://tizen.org/privilege/calendar.read',
95 CALENDAR_WRITE: 'http://tizen.org/privilege/calendar.write',
96 CALLHISTORY_READ: 'http://tizen.org/privilege/callhistory.read',
97 CALLHISTORY_WRITE: 'http://tizen.org/privilege/callhistory.write',
98 CONTACT_READ: 'http://tizen.org/privilege/contact.read',
99 CONTACT_WRITE: 'http://tizen.org/privilege/contact.write',
100 CONTENT_READ: 'http://tizen.org/privilege/content.write',
101 CONTENT_WRITE: 'http://tizen.org/privilege/content.write',
102 DATACONTROL_CONSUMER: 'http://tizen.org/privilege/datacontrol.consumer',
103 DATASYNC: 'http://tizen.org/privilege/datasync',
104 DOWNLOAD: 'http://tizen.org/privilege/download',
105 FILESYSTEM_READ: 'http://tizen.org/privilege/filesystem.read',
106 FILESYSTEM_WRITE: 'http://tizen.org/privilege/filesystem.write',
107 HAPTIC: 'http://tizen.org/privilege/haptic',
108 HEALTHINFO: 'http://tizen.org/privilege/healthinfo',
109 INTERNET: 'http://tizen.org/privilege/internet',
110 LED: 'http://tizen.org/privilege/led',
111 LOCATION: 'http://tizen.org/privilege/location',
112 MEDIACONTROLLER_SERVER: 'http://tizen.org/privilege/mediacontroller.server',
113 MEDIACONTROLLER_CLIENT: 'http://tizen.org/privilege/mediacontroller.client',
114 MESSAGING_READ: 'http://tizen.org/privilege/messaging.read',
115 MESSAGING_WRITE: 'http://tizen.org/privilege/messaging.write',
116 NETWORKBEARERSELECTION: 'http://tizen.org/privilege/networkbearerselection',
117 NFC_ADMIN: 'http://tizen.org/privilege/nfc.admin',
118 NFC_CARDEMULATION: 'http://tizen.org/privilege/nfc.cardemulation',
119 NFC_COMMON: 'http://tizen.org/privilege/nfc.common',
120 NFC_P2P: 'http://tizen.org/privilege/nfc.p2p',
121 NFC_TAG: 'http://tizen.org/privilege/nfc.tag',
122 NOTIFICATION: 'http://tizen.org/privilege/notification',
123 PACKAGE_INFO: 'http://tizen.org/privilege/packagemanager.info',
124 PACKAGEMANAGER_INSTALL: 'http://tizen.org/privilege/packagemanager.install',
125 POWER: 'http://tizen.org/privilege/power',
126 PUSH: 'http://tizen.org/privilege/push',
127 SECUREELEMENT: 'http://tizen.org/privilege/secureelement',
128 SETTING_ADMIN: 'http://tizen.org/privilege/systemsettings.admin',
129 SETTING: 'http://tizen.org/privilege/setting',
130 SYSTEM: 'http://tizen.org/privilege/system',
131 SYSTEMMANAGER: 'http://tizen.org/privilege/systemmanager',
132 TELEPHONY: 'http://tizen.org/privilege/telephony',
133 VOLUME_SET: 'http://tizen.org/privilege/volume.set',
134 WEBSETTING: 'http://tizen.org/privilege/websetting',
135 TV_INPUT_DEVICE: 'http://tizen.org/privilege/tv.inputdevice'
138 Object.freeze(privilege);
140 Object.defineProperty(this, 'privilege', {
148 Utils.prototype.error = console.error.bind(console);
149 Utils.prototype.warn = console.warn.bind(console);
150 Utils.prototype.log = _enableJsLogs ? console.log.bind(console) : function(){};
152 Utils.prototype.global = _global;
154 Utils.prototype.repackFilter = function(filter) {
155 if (filter instanceof tizen.AttributeFilter) {
157 filterType: 'AttributeFilter',
158 attributeName: filter.attributeName,
159 matchFlag: filter.matchFlag,
160 matchValue: _dateConverter.fromTZDate(filter.matchValue)
163 if (filter instanceof tizen.AttributeRangeFilter) {
165 filterType: 'AttributeRangeFilter',
166 attributeName: filter.attributeName,
167 initialValue: _dateConverter.fromTZDate(filter.initialValue),
168 endValue: _dateConverter.fromTZDate(filter.endValue)
171 if (filter instanceof tizen.CompositeFilter) {
173 var filters = filter.filters;
175 for (var i = 0; i < filters.length; ++i) {
176 _f.push(this.repackFilter(filters[i]));
180 filterType: 'CompositeFilter',
190 * @deprecated You should use xwalk.utils.validator.validateMethod() instead.
192 Utils.prototype.validateArguments = function(signature, args) {
193 var full_args = Array.prototype.slice.call(args);
195 // After '?' everything is optional.
196 var mandatory_len = signature.indexOf('?') === -1 ? signature.length : signature.indexOf('?');
198 if (full_args.length < mandatory_len)
201 // Mandatory arguments.
202 for (var i = 0; i < mandatory_len; i++) {
203 if (typeof full_args[i] !== signature_to_type[signature[i]] || full_args[i] === null)
207 // Optional args may be null.
208 for (var i = mandatory_len; i < full_args.length && i < signature.length - 1; i++) {
209 if (full_args[i] !== null && typeof full_args[i] !== signature_to_type[signature[i + 1]])
216 Utils.prototype.validateObject = function(object, signature, attributes) {
217 for (var i = 0; i < signature.length; i++) {
218 if (object.hasOwnProperty(attributes[i]) &&
219 typeof object[attributes[i]] !== signature_to_type[signature[i]]) {
227 Utils.prototype.getPkgApiVersion = function() {
228 var result = native_.callSync('Utils_getPkgApiVersion');
229 if (native_.isFailure(result)) {
230 throw native_.getErrorObject(result);
232 return native_.getResultObject(result);
235 Utils.prototype.checkPrivilegeAccess = function(privilege) {
236 var result = native_.callSync('Utils_checkPrivilegeAccess', {
237 privilege : _toString(privilege),
240 if (native_.isFailure(result)) {
241 throw native_.getErrorObject(result);
245 Utils.prototype.isAppVersionEarlierThan= function(ver) {
246 var app_ver = this.getPkgApiVersion();
248 var arr_ver = ver.split("."); // reference version
249 var arr_app_ver = app_ver.split("."); // application version
254 var length = Math.min(arr_ver.length, arr_app_ver.length);
255 for (i = 0; i < length; i++) {
256 num_ver = parseInt(arr_ver[i]);
257 num_app = parseInt(arr_app_ver[i]);
258 if (num_app < num_ver) {
260 } else if (num_app > num_ver) {
265 if (arr_ver.length > arr_app_ver.length) {
271 Utils.prototype.checkPrivilegeAccess4Ver = function(new_ver, new_priv, old_priv) {
272 if (!this.isAppVersionEarlierThan(new_ver)) {
273 this.checkPrivilegeAccess(new_priv);
274 } else if (old_priv != undefined) {
275 this.checkPrivilegeAccess(old_priv);
279 Utils.prototype.checkBackwardCompabilityPrivilegeAccess = function(current_privilege, previous_privilege) {
280 var result = native_.callSync('Utils_checkBackwardCompabilityPrivilegeAccess', {
281 current_privilege : _toString(current_privilege),
282 previous_privilege : _toString(previous_privilege),
285 if (native_.isFailure(result)) {
286 throw native_.getErrorObject(result);
290 Utils.prototype.checkProfile = function() {
291 var result = native_.callSync('Utils_checkProfile', {});
293 return native_.getResultObject(result);
297 /////////////////////////////////////////////////////////////////////////////
299 var Type = function() {};
301 Type.prototype.isBoolean = function(obj) {
302 return typeof obj === 'boolean';
305 Type.prototype.isObject = function(obj) {
306 return (null !== obj && typeof obj === 'object' && !this.isArray(obj));
309 Type.prototype.isArray = function(obj) {
310 return Array.isArray(obj);
313 Type.prototype.isFunction = function(obj) {
314 return typeof obj === 'function';
317 Type.prototype.isNumber = function(obj) {
318 return typeof obj === 'number';
321 Type.prototype.isString = function(obj) {
322 return typeof obj === 'string';
325 Type.prototype.isDate = function(obj) {
326 return obj instanceof Date;
329 Type.prototype.isNull = function(obj) {
333 Type.prototype.isNullOrUndefined = function(obj) {
334 return (obj === null || obj === undefined);
337 Type.prototype.isUndefined = function(obj) {
338 return obj === void 0;
341 Type.prototype.isA = function(obj, type) {
342 var clas = Object.prototype.toString.call(obj).slice(8, -1);
343 return (obj !== undefined) && (obj !== null) && (clas === type);
346 Type.prototype.isEmptyObject = function(obj) {
347 for (var property in obj) {
348 if (obj.hasOwnProperty(property)) {
355 Type.prototype.hasProperty = function(obj, prop) {
359 Type.prototype.arrayContains = function(arr, value) {
360 return (arr.indexOf(value) > -1);
363 Type.prototype.getValues = function(obj) {
365 for (var key in obj) {
366 if (obj.hasOwnProperty(key)) {
373 var _type = new Type();
377 /////////////////////////////////////////////////////////////////////////////
379 var Converter = function() {};
381 function _nullableGeneric(func, nullable, val) {
382 if (_type.isNull(val) && nullable === true) {
385 return func.apply(null, [].slice.call(arguments, 2));
389 function _toBoolean(val) {
393 Converter.prototype.toBoolean = function(val, nullable) {
394 return _nullableGeneric(_toBoolean, nullable, val);
397 function _toLong(val) {
398 var ret = parseInt(val);
399 return isNaN(ret) ? (val === true ? 1 : 0) : ret;
402 Converter.prototype.toLong = function(val, nullable) {
403 return _nullableGeneric(_toLong, nullable, val);
406 function _toLongLong(val) {
407 // According to WebIDL specification this will not be a precise representation
408 // of requested val. We're converting the val to signed long and then pass it
409 // to C++ to get the value in required range.
410 return native_.getResultObject(native_.callSync('Utils_toLongLong', {
415 Converter.prototype.toLongLong = function(val, nullable) {
416 return _nullableGeneric(_toLongLong, nullable, val);
419 function _toUnsignedLong(val) {
420 return _toLong(val) >>> 0;
423 Converter.prototype.toUnsignedLong = function(val, nullable) {
424 return _nullableGeneric(_toUnsignedLong, nullable, val);
427 function _toUnsignedLongLong(val) {
428 // According to WebIDL specification this will not be a precise representation
429 // of requested val. We're converting the val to signed long and then pass it
430 // to C++ to get the value in required range.
431 return native_.getResultObject(native_.callSync('Utils_toUnsignedLongLong', {
436 Converter.prototype.toUnsignedLongLong = function(val, nullable) {
437 return _nullableGeneric(_toUnsignedLongLong, nullable, val);
440 function _toShort(val) {
441 return ((_toLong(val) + 32768) & 0xFFFF) - 32768;
444 Converter.prototype.toShort = function(val, nullable) {
445 return _nullableGeneric(_toShort, nullable, val);
448 function _toUnsignedShort(val) {
449 return (Math.abs(_toLong(val)) & 0xFFFF);
452 Converter.prototype.toUnsignedShort = function(val, nullable) {
453 return _nullableGeneric(_toUnsignedShort, nullable, val);
456 function _toByte(val) {
457 return ((_toLong(val) + 128) & 0xFF) - 128;
460 Converter.prototype.toByte = function(val, nullable) {
461 return _nullableGeneric(_toByte, nullable, val);
464 function _toOctet(val) {
465 return _toLong(val) & 0xFF;
468 Converter.prototype.toOctet = function(val, nullable) {
469 return _nullableGeneric(_toOctet, nullable, val);
472 function _toDouble(val) {
473 var ret = Number(val);
474 if (isNaN(ret) || !isFinite(ret)) {
475 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
476 'Cannot convert ' + String(val) + ' to double.');
481 Converter.prototype.toDouble = function(val, nullable) {
482 return _nullableGeneric(_toDouble, nullable, val);
485 function _toString(val) {
489 Converter.prototype.toString = function(val, nullable) {
490 return _nullableGeneric(_toString, nullable, val);
493 function _toPlatformObject(val, types) {
496 if (_type.isArray(val)) {
502 if (_type.isArray(types)) {
508 for (var i = 0; i < t.length; ++i) {
509 for (var j = 0; j < v.length; ++j) {
510 match = match || (v[j] instanceof t[i]);
517 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
518 'Cannot convert ' + String(val) + ' to ' + String(t[0].name) + '.');
521 Converter.prototype.toPlatformObject = function(val, types, nullable) {
522 return _nullableGeneric(_toPlatformObject, nullable, val, types);
525 function _toFunction(val) {
526 if (_type.isFunction(val)) {
530 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
531 'Cannot convert ' + String(val) + ' to function.');
534 Converter.prototype.toFunction = function(val, nullable) {
535 return _nullableGeneric(_toFunction, nullable, val);
538 function _toArray(val) {
539 if (_type.isArray(val)) {
543 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
544 'Cannot convert ' + String(val) + ' to array.');
547 Converter.prototype.toArray = function(val, nullable) {
548 return _nullableGeneric(_toArray, nullable, val);
551 function _toDictionary(val) {
552 if (_type.isObject(val) || _type.isFunction(val)) {
556 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
557 'Cannot convert ' + String(val) + ' to dictionary.');
560 Converter.prototype.toDictionary = function(val, nullable) {
561 return _nullableGeneric(_toDictionary, nullable, val);
564 function _toEnum(val, e) {
565 var v = _toString(val);
566 if (_type.arrayContains(e, v)) {
570 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
571 'Cannot convert ' + v + ' to enum.');
574 Converter.prototype.toEnum = function(val, e, nullable) {
575 return _nullableGeneric(_toEnum, nullable, val, e);
578 var _converter = new Converter();
580 /////////////////////////////////////////////////////////////////////////////
582 var Validator = function() {
586 LONG_LONG: 'LONG_LONG',
587 UNSIGNED_LONG: 'UNSIGNED_LONG',
588 UNSIGNED_LONG_LONG: 'UNSIGNED_LONG_LONG',
593 FUNCTION: 'FUNCTION',
594 DICTIONARY: 'DICTIONARY',
595 PLATFORM_OBJECT: 'PLATFORM_OBJECT',
596 LISTENER: 'LISTENER',
599 FILE_REFERENCE: 'FILE_REFERENCE',
600 SIMPLE_TYPE: 'SIMPLE_TYPE' // Boolean, Number or String
606 * Verifies if arguments passed to function are valid.
608 * Description of expected arguments.
609 * This is an array of objects, each object represents one argument.
610 * First object in this array describes first argument, second object describes second
611 * argument, and so on.
612 * Object describing an argument needs to have two properties:
613 * - name - name of the argument,
614 * - type - type of the argument, only values specified in Validator.Types are allowed.
615 * Other properties, which may appear:
616 * - optional - if set to value which evaluates to true, argument is optional
617 * - nullable - if set to to true, argument may be set to null
618 * - values - required in case of some objects, value depends on type
619 * - validator - function which accepts a single parameter and returns true or false;
620 * if this property is present, this function will be executed,
621 * argument converted to expected type is going to be passed to this function
623 * @param {Array} a - arguments of a method
624 * @param {Array} d - description of expected arguments
625 * @return {Object} which holds all available arguments.
626 * @throws TypeMismatchError if arguments are not valid
664 * type: Validator.Types.PLATFORM_OBJECT,
665 * values: ApplicationControl // type of platform object
672 * type: Validator.Types.PLATFORM_OBJECT,
673 * values: [Alarm, AlarmRelative, AlarmAbsolute] // accepted types
680 * type: Validator.Types.LISTENER,
681 * values: ['onsuccess', 'onfailure'] // array of callbacks' names
688 * type: Validator.Types.ARRAY,
689 * values: ApplicationControlData // type of each element in array,
690 * // tested with instanceof
697 * type: Validator.Types.ARRAY,
698 * values: Validator.Types.DOUBLE // converts elements, only primitive types are supported
705 * type: Validator.Types.ENUM,
706 * values: ['SCREEN_DIM', 'SCREEN_NORMAL', 'CPU_AWAKE'] // array of allowed values
710 Validator.prototype.validateArgs = function(a, d) {
711 var args = {has: {}};
713 for (var i = 0; i < d.length; ++i) {
714 var name = d[i].name;
715 args.has[name] = (i < a.length);
717 var optional = d[i].optional;
718 var nullable = d[i].nullable;
721 if (args.has[name] || !optional) {
722 var type = d[i].type;
723 var values = d[i].values;
726 case this.Types.BOOLEAN:
727 val = _converter.toBoolean(val, nullable);
730 case this.Types.LONG:
731 val = _converter.toLong(val, nullable);
734 case this.Types.LONG_LONG:
735 val = _converter.toLongLong(val, nullable);
738 case this.Types.UNSIGNED_LONG:
739 val = _converter.toUnsignedLong(val, nullable);
742 case this.Types.UNSIGNED_LONG_LONG:
743 val = _converter.toUnsignedLongLong(val, nullable);
746 case this.Types.BYTE:
747 val = _converter.toByte(val, nullable);
750 case this.Types.OCTET:
751 val = _converter.toOctet(val, nullable);
754 case this.Types.DOUBLE:
755 val = _converter.toDouble(val, nullable);
758 case this.Types.STRING:
759 val = _converter.toString(val, nullable);
762 case this.Types.FUNCTION:
763 val = _converter.toFunction(val, nullable);
766 case this.Types.DICTIONARY:
767 val = _converter.toDictionary(val, nullable);
770 case this.Types.PLATFORM_OBJECT:
771 val = _converter.toPlatformObject(val, values, nullable);
774 case this.Types.LISTENER:
775 if (_type.isNull(val)) {
777 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
778 'Argument "' + name + '" cannot be null.');
781 if (!_type.isObject(val)) {
782 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
783 'Argument "' + name + '" should be an object.');
785 for (var ii = 0; ii < values.length; ++ii) {
786 if (_type.hasProperty(val, values[ii])) {
787 val[values[ii]] = _converter.toFunction(val[values[ii]], false);
793 case this.Types.ARRAY:
794 val = _converter.toArray(val, nullable);
795 if (!_type.isNull(val) && values) {
799 case this.Types.BOOLEAN:
800 func = _converter.toBoolean;
803 case this.Types.LONG:
804 func = _converter.toLong;
807 case this.Types.LONG_LONG:
808 func = _converter.toLongLong;
811 case this.Types.UNSIGNED_LONG:
812 func = _converter.toUnsignedLong;
815 case this.Types.UNSIGNED_LONG_LONG:
816 func = _converter.toUnsignedLongLong;
819 case this.Types.BYTE:
820 func = _converter.toByte;
823 case this.Types.OCTET:
824 func = _converter.toOctet;
827 case this.Types.DOUBLE:
828 func = _converter.toDouble;
831 case this.Types.STRING:
832 func = _converter.toString;
836 func = function(val) {
837 if (!(val instanceof values)) {
838 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
839 'Items of array "' + name + '" should be of type: ' + values + '.');
845 for (var j = 0; j < val.length; ++j) {
846 val[j] = func(val[j]);
851 case this.Types.ENUM:
852 val = _converter.toEnum(val, values, nullable);
855 case this.Types.FILE_REFERENCE:
856 if (_type.isObject(val) && 'File' === val.constructor.name && val.fullPath) {
859 val = _converter.toString(val, nullable);
862 case this.Types.SIMPLE_TYPE:
863 if (optional && _type.isUndefined(val)) {
866 if (nullable && _type.isNull(val)) {
869 if (!_type.isBoolean(val) && !_type.isNumber(val) && !_type.isString(val)) {
870 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
871 'Argument "' + name + '" should be boolean, number or string.');
876 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
877 'Unknown type: "' + type + '".');
880 var _validator = d[i].validator;
882 if (_type.isFunction(_validator) && !_validator(val)) {
883 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
884 'Argument "' + name + '" did not pass additional validation.');
896 * @deprecated Use validateArgs() instead.
898 Validator.prototype.validateMethod = function(a, d) {
899 return this.validateArgs(a, d);
904 * Use this helper to ensure that constructor is invoked by "new" operator.
906 * @param {Object} obj
907 * @param {Function} instance
909 Validator.prototype.isConstructorCall = function(obj, instance) {
910 if (!(obj instanceof instance) || obj._previouslyConstructed) {
911 // There is no TypeError exception in Tizen 2.3.0 API spec but it's required by current TCTs.
912 // For Tizen compliance it's wrapped into WebAPIException.
913 throw new WebAPIException('TypeError', 'Constructor cannot be called as function.');
916 Object.defineProperty(obj, '_previouslyConstructed', {
925 * @deprecated Use isConstructorCall() instead.
927 Validator.prototype.validateConstructorCall = function(obj, instance) {
928 this.isConstructorCall(obj, instance);
931 var _validator = new Validator();
935 /////////////////////////////////////////////////////////////////////////////
937 var NativeManager = function(extension) {
943 this.CALLBACK_ID_KEY = 'callbackId';
949 this.LISTENER_ID_KEY = 'listenerId';
955 var extension_ = extension;
964 * Map of async reply callbacks.
966 * @type {Object.<number, function>}
969 this.callbacks_ = {};
972 * Map of registered listeners.
974 * @type {Object.<string, function>}
977 this.listeners_ = {};
979 _validator.isConstructorCall(this, NativeManager);
981 // TODO: Remove mockup if WRT implements sendRuntimeMessage
982 // This is temporary mockup!
983 extension.sendRuntimeMessage = extension.sendRuntimeMessage || function() {
984 xwalk.utils.error('Runtime did not implement extension.sendRuntimeMessage!');
985 throw new WebAPIException(WebAPIException.UNKNOWN_ERR,
986 'Runtime did not implement extension.sendRuntimeMessage!');
989 extension.sendRuntimeAsyncMessage = extension.sendRuntimeAsyncMessage || function() {
990 xwalk.utils.error('Runtime did not implement extension.sendRuntimeAsyncMessage!');
991 throw new WebAPIException(WebAPIException.UNKNOWN_ERR,
992 'Runtime did not implement extension.sendRuntimeAsyncMessage!');
995 extension.sendRuntimeSyncMessage = extension.sendRuntimeSyncMessage || function() {
996 xwalk.utils.error('Runtime did not implement extension.sendRuntimeSyncMessage!');
997 throw new WebAPIException(WebAPIException.UNKNOWN_ERR,
998 'Runtime did not implement extension.sendRuntimeSyncMessage!');
1001 // check extension prototype
1002 if (!extension || !extension.internal ||
1003 !_type.isFunction(extension.postMessage) ||
1004 !_type.isFunction(extension.internal.sendSyncMessage) ||
1005 !_type.isFunction(extension.sendRuntimeMessage) ||
1006 !_type.isFunction(extension.sendRuntimeAsyncMessage) ||
1007 !_type.isFunction(extension.sendRuntimeSyncMessage) ||
1008 !_type.isFunction(extension.setMessageListener)) {
1009 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
1010 'Wrong extension object passed');
1013 Object.defineProperties(this, {
1028 extension_.setMessageListener(function(json) {
1029 var msg = JSON_.parse(json);
1032 if (msg.hasOwnProperty(this.CALLBACK_ID_KEY)) {
1033 id = msg[this.CALLBACK_ID_KEY];
1034 delete msg[this.CALLBACK_ID_KEY];
1036 if (!_type.isFunction(this.callbacks_[id])) {
1037 xwalk.utils.error('Wrong callback identifier. Ignoring message.');
1041 var f = this.callbacks_[id];
1042 setTimeout(function() {
1046 xwalk.utils.error('########## exception');
1047 xwalk.utils.error(e);
1050 delete this.callbacks_[id];
1055 if (msg.hasOwnProperty(this.LISTENER_ID_KEY)) {
1056 id = msg[this.LISTENER_ID_KEY];
1057 delete msg[this.LISTENER_ID_KEY];
1059 if (!_type.isFunction(this.listeners_[id])) {
1060 xwalk.utils.error('Wrong listener identifier. Ignoring message.');
1064 var f = this.listeners_[id];
1065 setTimeout(function() {
1069 xwalk.utils.error('########## exception');
1070 xwalk.utils.error(e);
1077 xwalk.utils.error('Missing callback or listener identifier. Ignoring message.');
1082 NativeManager.prototype.call = function(cmd, args, callback) {
1085 var replyId = this.nextReplyId;
1086 args[this.CALLBACK_ID_KEY] = replyId;
1087 this.callbacks_[replyId] = callback;
1089 return this.callSync(cmd, args);
1092 NativeManager.prototype.callSync = function(cmd, args) {
1093 var request = JSON_.stringify({
1098 var response = this.extension.internal.sendSyncMessage(request);
1099 if( response === undefined ) {
1100 /* C++ extension didn't set sync response using Instance::SendSyncReply */
1101 throw new WebAPIException(WebAPIException.ABORT_ERR, "Internal error");
1103 return JSON_.parse(response);
1106 NativeManager.prototype.sendRuntimeMessage = function(msg, body) {
1107 return this.extension.sendRuntimeMessage(msg, body || '');
1110 NativeManager.prototype.sendRuntimeAsyncMessage = function(msg, body, callback) {
1111 var handler = function(response) {
1112 if (_type.isFunction(callback)) {
1114 if ('success' === response.toLowerCase()) {
1115 result.status = 'success';
1117 result.status = 'error';
1118 result.error = new WebAPIException(WebAPIException.UNKNOWN_ERR,
1119 'Runtime message failure');
1124 return this.extension.sendRuntimeAsyncMessage(msg, body || '', handler);
1127 NativeManager.prototype.sendRuntimeSyncMessage = function(msg, body) {
1128 return this.extension.sendRuntimeSyncMessage(msg, body || '');
1131 NativeManager.prototype.addListener = function(name, callback) {
1132 if (!_type.isString(name) || !name.length) {
1133 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
1136 this.listeners_[name] = callback;
1139 NativeManager.prototype.removeListener = function(name) {
1140 if (this.listeners_.hasOwnProperty(name)) {
1141 delete this.listeners_[name];
1145 NativeManager.prototype.isListenerSet = function(name) {
1146 return this.listeners_.hasOwnProperty(name);
1149 NativeManager.prototype.isSuccess = function(result) {
1150 return (result.status !== 'error');
1153 NativeManager.prototype.isFailure = function(result) {
1154 return !this.isSuccess(result);
1157 NativeManager.prototype.getResultObject = function(result) {
1158 return result.result;
1161 NativeManager.prototype.getErrorObject = function(result) {
1162 return new WebAPIException(result.error);
1165 NativeManager.prototype.callIfPossible = function(callback) {
1166 if (!_type.isNullOrUndefined(callback)) {
1167 callback.apply(callback, [].slice.call(arguments, 1));
1171 // WebAPIException and WebAPIError definition moved to Utils for compliance
1172 // reasons with blink-wrt environment.
1173 // In blink-wrt the original Tizen module is loaded, which is not providing exception constructor.
1174 // As modules needs exceptions internally so they are loaded here for now.
1175 // See http://168.219.209.56/gerrit/#/c/23472/ for more details.
1176 // In future exception definition could be moved back to Tizen module.
1177 function __isObject(object) {
1178 return object instanceof _global.Object;
1181 function __isUndefined(object) {
1182 return object === void 0;
1185 function __isNumber(object) {
1186 return typeof object === 'number';
1189 // WARNING! This list should be in sync with the equivalent enum
1190 // located at tizen.h. Remember to update tizen.h if you change
1197 DOMSTRING_SIZE_ERR: 2,
1198 HIERARCHY_REQUEST_ERR: 3,
1199 WRONG_DOCUMENT_ERR: 4,
1200 INVALID_CHARACTER_ERR: 5,
1201 NO_DATA_ALLOWED_ERR: 6,
1202 NO_MODIFICATION_ALLOWED_ERR: 7,
1204 NOT_SUPPORTED_ERR: 9,
1205 INUSE_ATTRIBUTE_ERR: 10,
1206 INVALID_STATE_ERR: 11,
1208 INVALID_MODIFICATION_ERR: 13,
1210 INVALID_ACCESS_ERR: 15,
1212 TYPE_MISMATCH_ERR: 17,
1216 URL_MISMATCH_ERR: 21,
1217 QUOTA_EXCEEDED_ERR: 22,
1219 INVALID_NODE_TYPE_ERR: 24,
1222 // Error codes for these errors are not really defined anywhere.
1223 INVALID_VALUES_ERR: 100,
1225 PERMISSION_DENIED_ERR: 102,
1226 SERVICE_NOT_AVAILABLE_ERR: 103,
1228 VERIFICATION_ERR: 105
1231 var code_to_name = {};
1232 code_to_name[errors['NO_ERROR']] = 'NoError';
1233 code_to_name[errors['UNKNOWN_ERR']] = 'UnknownError';
1234 code_to_name[errors['INDEX_SIZE_ERR']] = 'IndexSizeError';
1235 code_to_name[errors['DOMSTRING_SIZE_ERR']] = 'DOMStringSizeError';
1236 code_to_name[errors['HIERARCHY_REQUEST_ERR']] = 'HierarchyRequestError';
1237 code_to_name[errors['WRONG_DOCUMENT_ERR']] = 'WrongDocumentError';
1238 code_to_name[errors['INVALID_CHARACTER_ERR']] = 'InvalidCharacterError';
1239 code_to_name[errors['NO_DATA_ALLOWED_ERR']] = 'NoDataAllowedError';
1240 code_to_name[errors['NO_MODIFICATION_ALLOWED_ERR']] = 'NoModificationAllowedError';
1241 code_to_name[errors['NOT_FOUND_ERR']] = 'NotFoundError';
1242 code_to_name[errors['NOT_SUPPORTED_ERR']] = 'NotSupportedError';
1243 code_to_name[errors['INUSE_ATTRIBUTE_ERR']] = 'InuseAttributeError';
1244 code_to_name[errors['INVALID_STATE_ERR']] = 'InvalidStateError';
1245 code_to_name[errors['SYNTAX_ERR']] = 'SyntaxError';
1246 code_to_name[errors['INVALID_MODIFICATION_ERR']] = 'InvalidModificationError';
1247 code_to_name[errors['NAMESPACE_ERR']] = 'NamespaceError';
1248 code_to_name[errors['INVALID_ACCESS_ERR']] = 'InvalidAccessError';
1249 code_to_name[errors['VALIDATION_ERR']] = 'ValidationError';
1250 code_to_name[errors['TYPE_MISMATCH_ERR']] = 'TypeMismatchError';
1251 code_to_name[errors['SECURITY_ERR']] = 'SecurityError';
1252 code_to_name[errors['NETWORK_ERR']] = 'NetworkError';
1253 code_to_name[errors['ABORT_ERR']] = 'AbortError';
1254 code_to_name[errors['URL_MISMATCH_ERR']] = 'URLMismatchError';
1255 code_to_name[errors['QUOTA_EXCEEDED_ERR']] = 'QuotaExceededError';
1256 code_to_name[errors['TIMEOUT_ERR']] = 'TimeoutError';
1257 code_to_name[errors['INVALID_NODE_TYPE_ERR']] = 'InvalidNodeTypeError';
1258 code_to_name[errors['DATA_CLONE_ERR']] = 'DataCloneError';
1260 code_to_name[errors['INVALID_VALUES_ERR']] = 'InvalidValuesError';
1261 code_to_name[errors['IO_ERR']] = 'IOError';
1262 code_to_name[errors['PERMISSION_DENIED_ERR']] = 'PermissionDeniedError';
1263 code_to_name[errors['SERVICE_NOT_AVAILABLE_ERR']] = 'ServiceNotAvailableError';
1264 code_to_name[errors['DATABASE_ERR']] = 'DatabaseError';
1265 code_to_name[errors['VERIFICATION_ERR']] = 'VerificationError';
1267 var name_to_code = {};
1268 Object.keys(errors).forEach(function(key) {
1269 name_to_code[code_to_name[errors[key]]] = errors[key];
1274 * Generic exception interface.
1276 * @param {number} code 16-bit error code.
1277 * @param {string} message An error message that describes the details of an encountered error.
1278 * @param {string} name An error type.
1280 var WebAPIException = function(code, message, name) {
1282 var name_ = code_to_name[code];
1283 var message_ = 'Unknown error';
1285 switch (arguments.length) {
1287 var error = arguments[0];
1288 if (__isObject(error)) {
1291 message_ = error.message;
1292 if (__isUndefined(code_) && !__isUndefined(name_))
1293 code_ = name_to_code[name_];
1294 if (__isUndefined(name_) && !__isUndefined(code_))
1295 name_ = code_to_name[code_];
1296 } else if (__isNumber(error)) {
1297 // backward compatibility with crosswalk implementation
1299 name_ = code_to_name[code];
1304 if (__isNumber(arguments[0])) {
1305 code_ = arguments[0];
1306 if (!__isUndefined(code_to_name[code_])) {
1307 name_ = code_to_name[code_];
1310 name_ = String(arguments[0]);
1311 if (!__isUndefined(name_to_code[name_])) {
1312 code_ = name_to_code[name_];
1315 message_ = String(arguments[1]);
1318 // backward compatibility with crosswalk implementation
1319 code_ = Number(arguments[0]);
1320 message_ = String(arguments[1]);
1321 name_ = String(arguments[2]);
1327 if (code_ > errors.DATA_CLONE_ERR) {
1332 Object.defineProperties(this, {
1333 code: {value: code_, writable: false, enumerable: true},
1334 name: {value: name_, writable: false, enumerable: true},
1335 message: {value: message_, writable: false, enumerable: true}
1338 this.constructor.prototype.__proto__ = Error.prototype;
1339 Error.captureStackTrace && Error.captureStackTrace(this, this.constructor); // V8-specific code
1342 WebAPIException.prototype.toString = function() {
1343 return this.name + ': ' + this.message;
1347 var error_constants = {};
1348 for (var prop in errors) {
1349 error_constants[prop] = {value: errors[prop], writable: false, enumerable: true};
1351 Object.defineProperties(WebAPIException, error_constants);
1352 Object.defineProperties(WebAPIException.prototype, error_constants);
1355 // Export WebAPIException and WebAPIError into global scope.
1356 // For compliance reasons their constructors should not be exported in tizen namespace,
1357 // but should be available internally to allow throwing exceptions from modules.
1359 if (typeof window !== 'undefined') {
1361 } else if(typeof global !== 'undefined') {
1364 scope = scope || {};
1365 scope.WebAPIException = WebAPIException;
1366 scope.WebAPIError = WebAPIException;
1368 Utils.prototype.dateConverter = _dateConverter;
1369 Utils.prototype.type = _type;
1370 Utils.prototype.converter = _converter;
1371 Utils.prototype.validator = _validator;
1372 Utils.prototype.NativeManager = NativeManager;
1374 var native_ = new NativeManager(extension);
1376 exports.utils = new Utils();
1378 Object.freeze(exports);
1379 Object.freeze(exports.utils);
1380 Object.freeze(Utils.prototype);
1381 Object.freeze(NativeManager.prototype);