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') {
16 } else if (typeof global != 'undefined') {
21 * @deprecated Used only by validateArguments()
23 var signature_to_type = {
31 var DateConverter = function() {};
33 DateConverter.prototype.toTZDate = function(v, isAllDay) {
34 if (typeof v === 'number') {
41 if (!(v instanceof _global.Object)) {
46 return new tizen.TZDate(
57 return new tizen.TZDate(new Date(v.UTCTimestamp * 1000));
61 DateConverter.prototype.fromTZDate = function(v) {
62 if (!tizen.TZDate || !(v instanceof tizen.TZDate)) {
67 year: v.getFullYear(),
70 timezone: v.getTimezone(),
71 UTCTimestamp: v._utcTimestamp / 1000
75 var _dateConverter = new DateConverter();
80 * Cynara(since tizen 3.0) only support native privilege.
81 * simply web privilege convert native privilege for checking access.
84 ACCOUNT_READ: 'http://tizen.org/privilege/account.read',
85 ACCOUNT_WRITE: 'http://tizen.org/privilege/account.write',
86 ALARM: 'http://tizen.org/privilege/alarm.get',
87 APPLICATION_INFO: 'http://tizen.org/privilege/application.info',
88 APPLICATION_LAUNCH: 'http://tizen.org/privilege/application.launch',
89 APPMANAGER_CERTIFICATE: 'http://tizen.org/privilege/appmanager.certificate',
90 APPMANAGER_KILL: 'http://tizen.org/privilege/appmanager.kill',
91 BLUETOOTH_ADMIN: 'http://tizen.org/privilege/bluetooth.admin',
92 BLUETOOTH_GAP: 'http://tizen.org/privilege/bluetooth.gap',
93 BLUETOOTH_HEALTH: 'http://tizen.org/privilege/bluetooth.health',
94 BLUETOOTH_SPP: 'http://tizen.org/privilege/bluetooth.spp',
95 BLUETOOTHMANAGER: 'http://tizen.org/privilege/bluetoothmanager',
96 BLUETOOTH: 'http://tizen.org/privilege/bluetooth',
97 BOOKMARK_READ: 'http://tizen.org/privilege/bookmark.read',
98 BOOKMARK_WRITE: 'http://tizen.org/privilege/bookmark.write',
99 CALENDAR_READ: 'http://tizen.org/privilege/calendar.read',
100 CALENDAR_WRITE: 'http://tizen.org/privilege/calendar.write',
101 CALLHISTORY_READ: 'http://tizen.org/privilege/callhistory.read',
102 CALLHISTORY_WRITE: 'http://tizen.org/privilege/callhistory.write',
103 CONTACT_READ: 'http://tizen.org/privilege/contact.read',
104 CONTACT_WRITE: 'http://tizen.org/privilege/contact.write',
105 CONTENT_READ: 'http://tizen.org/privilege/content.write',
106 CONTENT_WRITE: 'http://tizen.org/privilege/content.write',
107 DATACONTROL_CONSUMER: 'http://tizen.org/privilege/datacontrol.consumer',
108 DATASYNC: 'http://tizen.org/privilege/datasync',
109 DOWNLOAD: 'http://tizen.org/privilege/download',
110 FILESYSTEM_READ: 'http://tizen.org/privilege/filesystem.read',
111 FILESYSTEM_WRITE: 'http://tizen.org/privilege/filesystem.write',
112 HAPTIC: 'http://tizen.org/privilege/haptic',
113 HEALTHINFO: 'http://tizen.org/privilege/healthinfo',
114 INTERNET: 'http://tizen.org/privilege/internet',
115 LED: 'http://tizen.org/privilege/led',
116 LOCATION: 'http://tizen.org/privilege/location',
117 MEDIACONTROLLER_SERVER: 'http://tizen.org/privilege/mediacontroller.server',
118 MEDIACONTROLLER_CLIENT: 'http://tizen.org/privilege/mediacontroller.client',
119 MESSAGING_READ: 'http://tizen.org/privilege/messaging.read',
120 MESSAGING_WRITE: 'http://tizen.org/privilege/messaging.write',
121 NETWORKBEARERSELECTION: 'http://tizen.org/privilege/networkbearerselection',
122 NFC_ADMIN: 'http://tizen.org/privilege/nfc.admin',
123 NFC_CARDEMULATION: 'http://tizen.org/privilege/nfc.cardemulation',
124 NFC_COMMON: 'http://tizen.org/privilege/nfc.common',
125 NFC_P2P: 'http://tizen.org/privilege/nfc.p2p',
126 NFC_TAG: 'http://tizen.org/privilege/nfc.tag',
127 NOTIFICATION: 'http://tizen.org/privilege/notification',
128 PACKAGE_INFO: 'http://tizen.org/privilege/packagemanager.info',
129 PACKAGEMANAGER_INSTALL: 'http://tizen.org/privilege/packagemanager.install',
130 POWER: 'http://tizen.org/privilege/power',
131 PUSH: 'http://tizen.org/privilege/push',
132 SECUREELEMENT: 'http://tizen.org/privilege/secureelement',
133 SETTING_ADMIN: 'http://tizen.org/privilege/systemsettings.admin',
134 SETTING: 'http://tizen.org/privilege/setting',
135 SYSTEM: 'http://tizen.org/privilege/system',
136 SYSTEMMANAGER: 'http://tizen.org/privilege/systemmanager',
137 TELEPHONY: 'http://tizen.org/privilege/telephony',
138 VOLUME_SET: 'http://tizen.org/privilege/volume.set',
139 WEBSETTING: 'http://tizen.org/privilege/websetting',
140 TV_INPUT_DEVICE: 'http://tizen.org/privilege/tv.inputdevice'
143 Object.freeze(privilege);
145 Object.defineProperty(this, 'privilege', {
153 Utils.prototype.error = console.error.bind(console);
154 Utils.prototype.warn = console.warn.bind(console);
155 Utils.prototype.log = _enableJsLogs ? console.log.bind(console) : function() {};
157 Utils.prototype.global = _global;
159 Utils.prototype.repackFilter = function(filter) {
160 if (filter instanceof tizen.AttributeFilter) {
162 filterType: 'AttributeFilter',
163 attributeName: filter.attributeName,
164 matchFlag: filter.matchFlag,
165 matchValue: _dateConverter.fromTZDate(filter.matchValue)
168 if (filter instanceof tizen.AttributeRangeFilter) {
170 filterType: 'AttributeRangeFilter',
171 attributeName: filter.attributeName,
172 initialValue: _dateConverter.fromTZDate(filter.initialValue),
173 endValue: _dateConverter.fromTZDate(filter.endValue)
176 if (filter instanceof tizen.CompositeFilter) {
178 var filters = filter.filters;
180 for (var i = 0; i < filters.length; ++i) {
181 _f.push(this.repackFilter(filters[i]));
185 filterType: 'CompositeFilter',
195 * @deprecated You should use xwalk.utils.validator.validateMethod() instead.
197 Utils.prototype.validateArguments = function(signature, args) {
198 var full_args = Array.prototype.slice.call(args);
200 // After '?' everything is optional.
202 signature.indexOf('?') === -1 ? signature.length : signature.indexOf('?');
204 if (full_args.length < mandatory_len) return false;
206 // Mandatory arguments.
207 for (var i = 0; i < mandatory_len; i++) {
209 typeof full_args[i] !== signature_to_type[signature[i]] ||
210 full_args[i] === null
215 // Optional args may be null.
216 for (var i = mandatory_len; i < full_args.length && i < signature.length - 1; i++) {
218 full_args[i] !== null &&
219 typeof full_args[i] !== signature_to_type[signature[i + 1]]
227 Utils.prototype.validateObject = function(object, signature, attributes) {
228 for (var i = 0; i < signature.length; i++) {
230 object.hasOwnProperty(attributes[i]) &&
231 typeof object[attributes[i]] !== signature_to_type[signature[i]]
240 Utils.prototype.getPkgApiVersion = function() {
241 var result = native_.callSync('Utils_getPkgApiVersion');
242 if (native_.isFailure(result)) {
243 throw native_.getErrorObject(result);
245 return native_.getResultObject(result);
248 Utils.prototype.checkPrivilegeAccess = function(privilege) {
249 var result = native_.callSync('Utils_checkPrivilegeAccess', {
250 privilege: _toString(privilege)
253 if (native_.isFailure(result)) {
254 throw native_.getErrorObject(result);
258 Utils.prototype.isAppVersionEarlierThan = function(ver) {
259 var app_ver = this.getPkgApiVersion();
261 var arr_ver = ver.split('.'); // reference version
262 var arr_app_ver = app_ver.split('.'); // application version
267 var length = Math.min(arr_ver.length, arr_app_ver.length);
268 for (i = 0; i < length; i++) {
269 num_ver = parseInt(arr_ver[i]);
270 num_app = parseInt(arr_app_ver[i]);
271 if (num_app < num_ver) {
273 } else if (num_app > num_ver) {
278 if (arr_ver.length > arr_app_ver.length) {
284 Utils.prototype.checkPrivilegeAccess4Ver = function(new_ver, new_priv, old_priv) {
285 if (!this.isAppVersionEarlierThan(new_ver)) {
286 this.checkPrivilegeAccess(new_priv);
287 } else if (old_priv != undefined) {
288 this.checkPrivilegeAccess(old_priv);
292 Utils.prototype.checkBackwardCompabilityPrivilegeAccess = function(
296 var result = native_.callSync('Utils_checkBackwardCompabilityPrivilegeAccess', {
297 current_privilege: _toString(current_privilege),
298 previous_privilege: _toString(previous_privilege)
301 if (native_.isFailure(result)) {
302 throw native_.getErrorObject(result);
306 Utils.prototype.checkProfile = function() {
307 var result = native_.callSync('Utils_checkProfile', {});
309 return native_.getResultObject(result);
312 /////////////////////////////////////////////////////////////////////////////
314 var Type = function() {};
316 Type.prototype.isBoolean = function(obj) {
317 return typeof obj === 'boolean';
320 Type.prototype.isObject = function(obj) {
321 return null !== obj && typeof obj === 'object' && !this.isArray(obj);
324 Type.prototype.isArray = function(obj) {
325 return Array.isArray(obj);
328 Type.prototype.isFunction = function(obj) {
329 return typeof obj === 'function';
332 Type.prototype.isNumber = function(obj) {
333 return typeof obj === 'number';
336 Type.prototype.isString = function(obj) {
337 return typeof obj === 'string';
340 Type.prototype.isDate = function(obj) {
341 return obj instanceof Date;
344 Type.prototype.isNull = function(obj) {
348 Type.prototype.isNullOrUndefined = function(obj) {
349 return obj === null || obj === undefined;
352 Type.prototype.isUndefined = function(obj) {
353 return obj === void 0;
356 Type.prototype.isA = function(obj, type) {
357 var clas = Object.prototype.toString.call(obj).slice(8, -1);
358 return obj !== undefined && obj !== null && clas === type;
361 Type.prototype.isEmptyObject = function(obj) {
362 for (var property in obj) {
363 if (obj.hasOwnProperty(property)) {
370 Type.prototype.hasProperty = function(obj, prop) {
374 Type.prototype.arrayContains = function(arr, value) {
375 return arr.indexOf(value) > -1;
378 Type.prototype.getValues = function(obj) {
380 for (var key in obj) {
381 if (obj.hasOwnProperty(key)) {
388 var _type = new Type();
390 /////////////////////////////////////////////////////////////////////////////
392 var Converter = function() {};
394 function _nullableGeneric(func, nullable, val) {
395 if (_type.isNull(val) && nullable === true) {
398 return func.apply(null, [].slice.call(arguments, 2));
402 function _toBoolean(val) {
406 Converter.prototype.toBoolean = function(val, nullable) {
407 return _nullableGeneric(_toBoolean, nullable, val);
410 function _toLong(val) {
411 var ret = parseInt(val);
412 return isNaN(ret) ? (val === true ? 1 : 0) : ret;
415 Converter.prototype.toLong = function(val, nullable) {
416 return _nullableGeneric(_toLong, nullable, val);
419 function _toLongLong(val) {
420 // According to WebIDL specification this will not be a precise representation
421 // of requested val. We're converting the val to signed long and then pass it
422 // to C++ to get the value in required range.
423 return native_.getResultObject(
424 native_.callSync('Utils_toLongLong', {
430 Converter.prototype.toLongLong = function(val, nullable) {
431 return _nullableGeneric(_toLongLong, nullable, val);
434 function _toUnsignedLong(val) {
435 return _toLong(val) >>> 0;
438 Converter.prototype.toUnsignedLong = function(val, nullable) {
439 return _nullableGeneric(_toUnsignedLong, nullable, val);
442 function _toUnsignedLongLong(val) {
443 // According to WebIDL specification this will not be a precise representation
444 // of requested val. We're converting the val to signed long and then pass it
445 // to C++ to get the value in required range.
446 return native_.getResultObject(
447 native_.callSync('Utils_toUnsignedLongLong', {
453 Converter.prototype.toUnsignedLongLong = function(val, nullable) {
454 return _nullableGeneric(_toUnsignedLongLong, nullable, val);
457 function _toShort(val) {
458 return ((_toLong(val) + 32768) & 0xffff) - 32768;
461 Converter.prototype.toShort = function(val, nullable) {
462 return _nullableGeneric(_toShort, nullable, val);
465 function _toUnsignedShort(val) {
466 return Math.abs(_toLong(val)) & 0xffff;
469 Converter.prototype.toUnsignedShort = function(val, nullable) {
470 return _nullableGeneric(_toUnsignedShort, nullable, val);
473 function _toByte(val) {
474 return ((_toLong(val) + 128) & 0xff) - 128;
477 Converter.prototype.toByte = function(val, nullable) {
478 return _nullableGeneric(_toByte, nullable, val);
481 function _toOctet(val) {
482 return _toLong(val) & 0xff;
485 Converter.prototype.toOctet = function(val, nullable) {
486 return _nullableGeneric(_toOctet, nullable, val);
489 function _toDouble(val) {
490 var ret = Number(val);
491 if (isNaN(ret) || !isFinite(ret)) {
492 throw new WebAPIException(
493 WebAPIException.TYPE_MISMATCH_ERR,
494 'Cannot convert ' + String(val) + ' to double.'
500 Converter.prototype.toDouble = function(val, nullable) {
501 return _nullableGeneric(_toDouble, nullable, val);
504 function _toString(val) {
508 Converter.prototype.toString = function(val, nullable) {
509 return _nullableGeneric(_toString, nullable, val);
512 function _toPlatformObject(val, types) {
515 if (_type.isArray(types)) {
521 if (_type.isArray(val)) {
522 throw new WebAPIException(
523 WebAPIException.TYPE_MISMATCH_ERR,
524 'Cannot convert ' + String(val) + ' to ' + String(t[0].name) + '.'
529 for (var i = 0; i < t.length; ++i) {
530 if (val instanceof t[i]) {
535 throw new WebAPIException(
536 WebAPIException.TYPE_MISMATCH_ERR,
537 'Cannot convert ' + String(val) + ' to ' + String(t[0].name) + '.'
541 Converter.prototype.toPlatformObject = function(val, types, nullable) {
542 return _nullableGeneric(_toPlatformObject, nullable, val, types);
545 function _toFunction(val) {
546 if (_type.isFunction(val)) {
550 throw new WebAPIException(
551 WebAPIException.TYPE_MISMATCH_ERR,
552 'Cannot convert ' + String(val) + ' to function.'
556 Converter.prototype.toFunction = function(val, nullable) {
557 return _nullableGeneric(_toFunction, nullable, val);
560 function _toArray(val) {
561 if (_type.isArray(val)) {
565 throw new WebAPIException(
566 WebAPIException.TYPE_MISMATCH_ERR,
567 'Cannot convert ' + String(val) + ' to array.'
571 Converter.prototype.toArray = function(val, nullable) {
572 return _nullableGeneric(_toArray, nullable, val);
575 function _toDictionary(val) {
576 if (_type.isObject(val) || _type.isFunction(val)) {
580 throw new WebAPIException(
581 WebAPIException.TYPE_MISMATCH_ERR,
582 'Cannot convert ' + String(val) + ' to dictionary.'
586 Converter.prototype.toDictionary = function(val, nullable) {
587 return _nullableGeneric(_toDictionary, nullable, val);
590 function _toEnum(val, e) {
591 var v = _toString(val);
592 if (_type.arrayContains(e, v)) {
596 throw new WebAPIException(
597 WebAPIException.TYPE_MISMATCH_ERR,
598 'Cannot convert ' + v + ' to enum.'
602 Converter.prototype.toEnum = function(val, e, nullable) {
603 return _nullableGeneric(_toEnum, nullable, val, e);
606 var _converter = new Converter();
608 /////////////////////////////////////////////////////////////////////////////
610 var Validator = function() {
614 LONG_LONG: 'LONG_LONG',
615 UNSIGNED_LONG: 'UNSIGNED_LONG',
616 UNSIGNED_LONG_LONG: 'UNSIGNED_LONG_LONG',
621 FUNCTION: 'FUNCTION',
622 DICTIONARY: 'DICTIONARY',
623 PLATFORM_OBJECT: 'PLATFORM_OBJECT',
624 LISTENER: 'LISTENER',
627 FILE_REFERENCE: 'FILE_REFERENCE',
628 SIMPLE_TYPE: 'SIMPLE_TYPE' // Boolean, Number or String
633 * Verifies if arguments passed to function are valid.
635 * Description of expected arguments.
636 * This is an array of objects, each object represents one argument.
637 * First object in this array describes first argument, second object describes second
638 * argument, and so on.
639 * Object describing an argument needs to have two properties:
640 * - name - name of the argument,
641 * - type - type of the argument, only values specified in Validator.Types are allowed.
642 * Other properties, which may appear:
643 * - optional - if set to value which evaluates to true, argument is optional
644 * - nullable - if set to to true, argument may be set to null
645 * - values - required in case of some objects, value depends on type
646 * - validator - function which accepts a single parameter and returns true or false;
647 * if this property is present, this function will be executed,
648 * argument converted to expected type is going to be passed to this
651 * @param {Array} a - arguments of a method
652 * @param {Array} d - description of expected arguments
653 * @return {Object} which holds all available arguments.
654 * @throws TypeMismatchError if arguments are not valid
692 * type: Validator.Types.PLATFORM_OBJECT,
693 * values: ApplicationControl // type of platform object
700 * type: Validator.Types.PLATFORM_OBJECT,
701 * values: [Alarm, AlarmRelative, AlarmAbsolute] // accepted types
708 * type: Validator.Types.LISTENER,
709 * values: ['onsuccess', 'onfailure'] // array of callbacks' names
716 * type: Validator.Types.ARRAY,
717 * values: ApplicationControlData // type of each element in array,
718 * // tested with instanceof
725 * type: Validator.Types.ARRAY,
726 * values: Validator.Types.DOUBLE // converts elements, only primitive types are
734 * type: Validator.Types.ENUM,
735 * values: ['SCREEN_DIM', 'SCREEN_NORMAL', 'CPU_AWAKE'] // array of allowed values
739 Validator.prototype.validateArgs = function(a, d) {
740 var args = { has: {} };
742 for (var i = 0; i < d.length; ++i) {
743 var name = d[i].name;
744 args.has[name] = i < a.length;
746 var optional = d[i].optional;
747 var nullable = d[i].nullable;
750 if (args.has[name] || !optional) {
751 var type = d[i].type;
752 var values = d[i].values;
755 case this.Types.BOOLEAN:
756 val = _converter.toBoolean(val, nullable);
759 case this.Types.LONG:
760 val = _converter.toLong(val, nullable);
763 case this.Types.LONG_LONG:
764 val = _converter.toLongLong(val, nullable);
767 case this.Types.UNSIGNED_LONG:
768 val = _converter.toUnsignedLong(val, nullable);
771 case this.Types.UNSIGNED_LONG_LONG:
772 val = _converter.toUnsignedLongLong(val, nullable);
775 case this.Types.BYTE:
776 val = _converter.toByte(val, nullable);
779 case this.Types.OCTET:
780 val = _converter.toOctet(val, nullable);
783 case this.Types.DOUBLE:
784 val = _converter.toDouble(val, nullable);
787 case this.Types.STRING:
788 val = _converter.toString(val, nullable);
791 case this.Types.FUNCTION:
792 val = _converter.toFunction(val, nullable);
795 case this.Types.DICTIONARY:
796 val = _converter.toDictionary(val, nullable);
799 case this.Types.PLATFORM_OBJECT:
800 val = _converter.toPlatformObject(val, values, nullable);
803 case this.Types.LISTENER:
804 if (_type.isNull(val)) {
806 throw new WebAPIException(
807 WebAPIException.TYPE_MISMATCH_ERR,
808 'Argument "' + name + '" cannot be null.'
812 if (!_type.isObject(val)) {
813 throw new WebAPIException(
814 WebAPIException.TYPE_MISMATCH_ERR,
815 'Argument "' + name + '" should be an object.'
818 for (var ii = 0; ii < values.length; ++ii) {
819 if (_type.hasProperty(val, values[ii])) {
820 val[values[ii]] = _converter.toFunction(
829 case this.Types.ARRAY:
830 val = _converter.toArray(val, nullable);
831 if (!_type.isNull(val) && values) {
835 case this.Types.BOOLEAN:
836 func = _converter.toBoolean;
839 case this.Types.LONG:
840 func = _converter.toLong;
843 case this.Types.LONG_LONG:
844 func = _converter.toLongLong;
847 case this.Types.UNSIGNED_LONG:
848 func = _converter.toUnsignedLong;
851 case this.Types.UNSIGNED_LONG_LONG:
852 func = _converter.toUnsignedLongLong;
855 case this.Types.BYTE:
856 func = _converter.toByte;
859 case this.Types.OCTET:
860 func = _converter.toOctet;
863 case this.Types.DOUBLE:
864 func = _converter.toDouble;
867 case this.Types.STRING:
868 func = _converter.toString;
872 func = function(val) {
873 if (!(val instanceof values)) {
874 throw new WebAPIException(
875 WebAPIException.TYPE_MISMATCH_ERR,
878 '" should be of type: ' +
887 for (var j = 0; j < val.length; ++j) {
888 val[j] = func(val[j]);
893 case this.Types.ENUM:
894 val = _converter.toEnum(val, values, nullable);
897 case this.Types.FILE_REFERENCE:
899 _type.isObject(val) &&
900 'File' === val.constructor.name &&
905 val = _converter.toString(val, nullable);
908 case this.Types.SIMPLE_TYPE:
909 if (optional && _type.isUndefined(val)) {
912 if (nullable && _type.isNull(val)) {
916 !_type.isBoolean(val) &&
917 !_type.isNumber(val) &&
920 throw new WebAPIException(
921 WebAPIException.TYPE_MISMATCH_ERR,
922 'Argument "' + name + '" should be boolean, number or string.'
928 throw new WebAPIException(
929 WebAPIException.TYPE_MISMATCH_ERR,
930 'Unknown type: "' + type + '".'
934 var _validator = d[i].validator;
936 if (_type.isFunction(_validator) && !_validator(val)) {
937 throw new WebAPIException(
938 WebAPIException.TYPE_MISMATCH_ERR,
939 'Argument "' + name + '" did not pass additional validation.'
951 * @deprecated Use validateArgs() instead.
953 Validator.prototype.validateMethod = function(a, d) {
954 return this.validateArgs(a, d);
958 * Use this helper to ensure that constructor is invoked by "new" operator.
960 * @param {Object} obj
961 * @param {Function} instance
963 Validator.prototype.isConstructorCall = function(obj, instance) {
964 if (!(obj instanceof instance) || obj._previouslyConstructed) {
965 // There is no TypeError exception in Tizen 2.3.0 API spec but it's required by
967 // For Tizen compliance it's wrapped into WebAPIException.
968 throw new WebAPIException(
970 'Constructor cannot be called as function.'
974 Object.defineProperty(obj, '_previouslyConstructed', {
982 * @deprecated Use isConstructorCall() instead.
984 Validator.prototype.validateConstructorCall = function(obj, instance) {
985 this.isConstructorCall(obj, instance);
988 var _validator = new Validator();
990 /////////////////////////////////////////////////////////////////////////////
992 var NativeManager = function(extension) {
997 this.CALLBACK_ID_KEY = 'callbackId';
1003 this.LISTENER_ID_KEY = 'listenerId';
1009 var extension_ = extension;
1018 * Map of async reply callbacks.
1020 * @type {Object.<number, function>}
1023 this.callbacks_ = {};
1026 * Map of registered listeners.
1028 * @type {Object.<string, function>}
1031 this.listeners_ = {};
1033 _validator.isConstructorCall(this, NativeManager);
1035 // TODO: Remove mockup if WRT implements sendRuntimeMessage
1036 // This is temporary mockup!
1037 extension.sendRuntimeMessage =
1038 extension.sendRuntimeMessage ||
1040 xwalk.utils.error('Runtime did not implement extension.sendRuntimeMessage!');
1041 throw new WebAPIException(
1042 WebAPIException.UNKNOWN_ERR,
1043 'Runtime did not implement extension.sendRuntimeMessage!'
1047 extension.sendRuntimeAsyncMessage =
1048 extension.sendRuntimeAsyncMessage ||
1051 'Runtime did not implement extension.sendRuntimeAsyncMessage!'
1053 throw new WebAPIException(
1054 WebAPIException.UNKNOWN_ERR,
1055 'Runtime did not implement extension.sendRuntimeAsyncMessage!'
1059 extension.sendRuntimeSyncMessage =
1060 extension.sendRuntimeSyncMessage ||
1063 'Runtime did not implement extension.sendRuntimeSyncMessage!'
1065 throw new WebAPIException(
1066 WebAPIException.UNKNOWN_ERR,
1067 'Runtime did not implement extension.sendRuntimeSyncMessage!'
1071 // check extension prototype
1074 !extension.internal ||
1075 !_type.isFunction(extension.postMessage) ||
1076 !_type.isFunction(extension.internal.sendSyncMessage) ||
1077 !_type.isFunction(extension.sendRuntimeMessage) ||
1078 !_type.isFunction(extension.sendRuntimeAsyncMessage) ||
1079 !_type.isFunction(extension.sendRuntimeSyncMessage) ||
1080 !_type.isFunction(extension.setMessageListener)
1082 throw new WebAPIException(
1083 WebAPIException.TYPE_MISMATCH_ERR,
1084 'Wrong extension object passed'
1088 Object.defineProperties(this, {
1103 extension_.setMessageListener(
1106 var msg = JSON_.parse(json);
1108 // Because of special handling of power lock in chromium, the special
1110 // - __DisableChromiumInternalPowerLock
1111 // - __EnableChromiumInternalPowerLock
1112 // could occur. In such cases we are silently ignroing those messages.
1113 // TODO This is workaround for missing patch in chromium-efl package
1114 // which should handle this special message and don't forward it to
1115 // webapi JS. After chromium-efl will be updated, below checking should
1117 if (json.substring(0, 2) === '__') {
1120 xwalk.utils.error('Ignoring message - Invalid JSON received: ' + json);
1125 if (msg.hasOwnProperty(this.CALLBACK_ID_KEY)) {
1126 id = msg[this.CALLBACK_ID_KEY];
1127 delete msg[this.CALLBACK_ID_KEY];
1129 if (!_type.isFunction(this.callbacks_[id])) {
1130 xwalk.utils.error('Wrong callback identifier. Ignoring message.');
1134 var f = this.callbacks_[id];
1135 setTimeout(function() {
1139 xwalk.utils.error('########## exception');
1140 xwalk.utils.error(e);
1143 delete this.callbacks_[id];
1148 if (msg.hasOwnProperty(this.LISTENER_ID_KEY)) {
1149 id = msg[this.LISTENER_ID_KEY];
1150 delete msg[this.LISTENER_ID_KEY];
1152 if (!_type.isFunction(this.listeners_[id])) {
1153 xwalk.utils.error('Wrong listener identifier. Ignoring message.');
1157 var f = this.listeners_[id];
1158 setTimeout(function() {
1162 xwalk.utils.error('########## exception');
1163 xwalk.utils.error(e);
1171 'Missing callback or listener identifier. Ignoring message.'
1177 NativeManager.prototype.call = function(cmd, args, callback) {
1180 var replyId = this.nextReplyId;
1181 args[this.CALLBACK_ID_KEY] = replyId;
1182 this.callbacks_[replyId] = callback;
1184 return this.callSync(cmd, args);
1187 NativeManager.prototype.callSync = function(cmd, args) {
1188 var request = JSON_.stringify({
1193 var response = this.extension.internal.sendSyncMessage(request);
1194 if (response === undefined) {
1195 /* C++ extension didn't set sync response using Instance::SendSyncReply */
1196 throw new WebAPIException(WebAPIException.ABORT_ERR, 'Internal error');
1198 return JSON_.parse(response);
1201 NativeManager.prototype.sendRuntimeMessage = function(msg, body) {
1202 return this.extension.sendRuntimeMessage(msg, body || '');
1205 NativeManager.prototype.sendRuntimeAsyncMessage = function(msg, body, callback) {
1206 var handler = function(response) {
1207 if (_type.isFunction(callback)) {
1209 if ('success' === response.toLowerCase()) {
1210 result.status = 'success';
1212 result.status = 'error';
1213 result.error = new WebAPIException(
1214 WebAPIException.UNKNOWN_ERR,
1215 'Runtime message failure'
1221 return this.extension.sendRuntimeAsyncMessage(msg, body || '', handler);
1224 NativeManager.prototype.sendRuntimeSyncMessage = function(msg, body) {
1225 return this.extension.sendRuntimeSyncMessage(msg, body || '');
1228 NativeManager.prototype.addListener = function(name, callback) {
1229 if (!_type.isString(name) || !name.length) {
1230 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
1233 this.listeners_[name] = callback;
1236 NativeManager.prototype.removeListener = function(name) {
1237 if (this.listeners_.hasOwnProperty(name)) {
1238 delete this.listeners_[name];
1242 NativeManager.prototype.isListenerSet = function(name) {
1243 return this.listeners_.hasOwnProperty(name);
1246 NativeManager.prototype.isSuccess = function(result) {
1247 return result.status !== 'error';
1250 NativeManager.prototype.isFailure = function(result) {
1251 return !this.isSuccess(result);
1254 NativeManager.prototype.getResultObject = function(result) {
1255 return result.result;
1258 NativeManager.prototype.getErrorObject = function(result) {
1259 return new WebAPIException(result.error);
1262 NativeManager.prototype.callIfPossible = function(callback) {
1263 if (!_type.isNullOrUndefined(callback)) {
1264 callback.apply(callback, [].slice.call(arguments, 1));
1268 // WebAPIException and WebAPIError definition moved to Utils for compliance
1269 // reasons with blink-wrt environment.
1270 // In blink-wrt the original Tizen module is loaded, which is not providing
1271 // exception constructor.
1272 // As modules needs exceptions internally so they are loaded here for now.
1273 // See http://168.219.209.56/gerrit/#/c/23472/ for more details.
1274 // In future exception definition could be moved back to Tizen module.
1275 function __isObject(object) {
1276 return object instanceof _global.Object;
1279 function __isUndefined(object) {
1280 return object === void 0;
1283 function __isNumber(object) {
1284 return typeof object === 'number';
1287 // WARNING! This list should be in sync with the equivalent enum
1288 // located at tizen.h. Remember to update tizen.h if you change
1295 DOMSTRING_SIZE_ERR: 2,
1296 HIERARCHY_REQUEST_ERR: 3,
1297 WRONG_DOCUMENT_ERR: 4,
1298 INVALID_CHARACTER_ERR: 5,
1299 NO_DATA_ALLOWED_ERR: 6,
1300 NO_MODIFICATION_ALLOWED_ERR: 7,
1302 NOT_SUPPORTED_ERR: 9,
1303 INUSE_ATTRIBUTE_ERR: 10,
1304 INVALID_STATE_ERR: 11,
1306 INVALID_MODIFICATION_ERR: 13,
1308 INVALID_ACCESS_ERR: 15,
1310 TYPE_MISMATCH_ERR: 17,
1314 URL_MISMATCH_ERR: 21,
1315 QUOTA_EXCEEDED_ERR: 22,
1317 INVALID_NODE_TYPE_ERR: 24,
1320 // Error codes for these errors are not really defined anywhere.
1321 INVALID_VALUES_ERR: 100,
1323 PERMISSION_DENIED_ERR: 102,
1324 SERVICE_NOT_AVAILABLE_ERR: 103,
1326 VERIFICATION_ERR: 105
1329 var code_to_name = {};
1330 code_to_name[errors['NO_ERROR']] = 'NoError';
1331 code_to_name[errors['UNKNOWN_ERR']] = 'UnknownError';
1332 code_to_name[errors['INDEX_SIZE_ERR']] = 'IndexSizeError';
1333 code_to_name[errors['DOMSTRING_SIZE_ERR']] = 'DOMStringSizeError';
1334 code_to_name[errors['HIERARCHY_REQUEST_ERR']] = 'HierarchyRequestError';
1335 code_to_name[errors['WRONG_DOCUMENT_ERR']] = 'WrongDocumentError';
1336 code_to_name[errors['INVALID_CHARACTER_ERR']] = 'InvalidCharacterError';
1337 code_to_name[errors['NO_DATA_ALLOWED_ERR']] = 'NoDataAllowedError';
1338 code_to_name[errors['NO_MODIFICATION_ALLOWED_ERR']] = 'NoModificationAllowedError';
1339 code_to_name[errors['NOT_FOUND_ERR']] = 'NotFoundError';
1340 code_to_name[errors['NOT_SUPPORTED_ERR']] = 'NotSupportedError';
1341 code_to_name[errors['INUSE_ATTRIBUTE_ERR']] = 'InuseAttributeError';
1342 code_to_name[errors['INVALID_STATE_ERR']] = 'InvalidStateError';
1343 code_to_name[errors['SYNTAX_ERR']] = 'SyntaxError';
1344 code_to_name[errors['INVALID_MODIFICATION_ERR']] = 'InvalidModificationError';
1345 code_to_name[errors['NAMESPACE_ERR']] = 'NamespaceError';
1346 code_to_name[errors['INVALID_ACCESS_ERR']] = 'InvalidAccessError';
1347 code_to_name[errors['VALIDATION_ERR']] = 'ValidationError';
1348 code_to_name[errors['TYPE_MISMATCH_ERR']] = 'TypeMismatchError';
1349 code_to_name[errors['SECURITY_ERR']] = 'SecurityError';
1350 code_to_name[errors['NETWORK_ERR']] = 'NetworkError';
1351 code_to_name[errors['ABORT_ERR']] = 'AbortError';
1352 code_to_name[errors['URL_MISMATCH_ERR']] = 'URLMismatchError';
1353 code_to_name[errors['QUOTA_EXCEEDED_ERR']] = 'QuotaExceededError';
1354 code_to_name[errors['TIMEOUT_ERR']] = 'TimeoutError';
1355 code_to_name[errors['INVALID_NODE_TYPE_ERR']] = 'InvalidNodeTypeError';
1356 code_to_name[errors['DATA_CLONE_ERR']] = 'DataCloneError';
1358 code_to_name[errors['INVALID_VALUES_ERR']] = 'InvalidValuesError';
1359 code_to_name[errors['IO_ERR']] = 'IOError';
1360 code_to_name[errors['PERMISSION_DENIED_ERR']] = 'PermissionDeniedError';
1361 code_to_name[errors['SERVICE_NOT_AVAILABLE_ERR']] = 'ServiceNotAvailableError';
1362 code_to_name[errors['DATABASE_ERR']] = 'DatabaseError';
1363 code_to_name[errors['VERIFICATION_ERR']] = 'VerificationError';
1365 var name_to_code = {};
1366 Object.keys(errors).forEach(function(key) {
1367 name_to_code[code_to_name[errors[key]]] = errors[key];
1371 * Generic exception interface.
1373 * @param {number} code 16-bit error code.
1374 * @param {string} message An error message that describes the details of
1375 * an encountered error.
1376 * @param {string} name An error type.
1378 var WebAPIException = function(code, message, name) {
1380 var name_ = code_to_name[code];
1381 var message_ = 'Unknown error';
1383 switch (arguments.length) {
1385 var error = arguments[0];
1386 if (__isObject(error)) {
1389 message_ = error.message;
1390 if (__isUndefined(code_) && !__isUndefined(name_))
1391 code_ = name_to_code[name_];
1392 if (__isUndefined(name_) && !__isUndefined(code_))
1393 name_ = code_to_name[code_];
1394 } else if (__isNumber(error)) {
1395 // backward compatibility with crosswalk implementation
1397 name_ = code_to_name[code];
1402 if (__isNumber(arguments[0])) {
1403 code_ = arguments[0];
1404 if (!__isUndefined(code_to_name[code_])) {
1405 name_ = code_to_name[code_];
1408 name_ = String(arguments[0]);
1409 if (!__isUndefined(name_to_code[name_])) {
1410 code_ = name_to_code[name_];
1413 message_ = String(arguments[1]);
1416 // backward compatibility with crosswalk implementation
1417 code_ = Number(arguments[0]);
1418 message_ = String(arguments[1]);
1419 name_ = String(arguments[2]);
1425 if (code_ > errors.DATA_CLONE_ERR) {
1430 Object.defineProperties(this, {
1431 code: { value: code_, writable: false, enumerable: true },
1432 name: { value: name_, writable: false, enumerable: true },
1433 message: { value: message_, writable: false, enumerable: true }
1436 this.constructor.prototype.__proto__ = Error.prototype;
1437 Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
1441 WebAPIException.prototype.toString = function() {
1442 return this.name + ': ' + this.message;
1445 var error_constants = {};
1446 for (var prop in errors) {
1447 error_constants[prop] = { value: errors[prop], writable: false, enumerable: true };
1449 Object.defineProperties(WebAPIException, error_constants);
1450 Object.defineProperties(WebAPIException.prototype, error_constants);
1452 // Export WebAPIException and WebAPIError into global scope.
1453 // For compliance reasons their constructors should not be exported in tizen namespace,
1454 // but should be available internally to allow throwing exceptions from modules.
1456 if (typeof window !== 'undefined') {
1458 } else if (typeof global !== 'undefined') {
1461 scope = scope || {};
1462 scope.WebAPIException = WebAPIException;
1463 scope.WebAPIError = WebAPIException;
1465 Utils.prototype.dateConverter = _dateConverter;
1466 Utils.prototype.type = _type;
1467 Utils.prototype.converter = _converter;
1468 Utils.prototype.validator = _validator;
1469 Utils.prototype.NativeManager = NativeManager;
1471 var native_ = new NativeManager(extension);
1473 exports.utils = new Utils();
1475 Object.freeze(exports);
1476 Object.freeze(exports.utils);
1477 Object.freeze(Utils.prototype);
1478 Object.freeze(NativeManager.prototype);