Merge branch 'tizen_4.0' into tizen_5.0
[platform/core/api/webapi-plugins.git] / src / utils / utils_api.js
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.
5
6 //Object xwalk.JSON - guaranteed to not being modified by the application programmer
7 var JSON_ = { stringify: JSON.stringify, parse: JSON.parse };
8 Object.freeze(JSON_);
9 exports.JSON = JSON_;
10
11 var _enableJsLogs = false;
12
13 var _global = {};
14 if (typeof window != 'undefined') {
15     _global = window;
16 } else if (typeof global != 'undefined') {
17     _global = global;
18 }
19
20 /**
21  * @deprecated Used only by validateArguments()
22  */
23 var signature_to_type = {
24     n: 'number',
25     f: 'function',
26     b: 'boolean',
27     s: 'string',
28     o: 'object'
29 };
30
31 var DateConverter = function() {};
32
33 DateConverter.prototype.toTZDate = function(v, isAllDay) {
34     if (typeof v === 'number') {
35         v = {
36             UTCTimestamp: v
37         };
38         isAllDay = false;
39     }
40
41     if (!(v instanceof _global.Object)) {
42         return v;
43     }
44
45     if (isAllDay) {
46         return new tizen.TZDate(
47             v.year,
48             v.month - 1,
49             v.day,
50             null,
51             null,
52             null,
53             null,
54             v.timezone || null
55         );
56     } else {
57         return new tizen.TZDate(new Date(v.UTCTimestamp * 1000));
58     }
59 };
60
61 DateConverter.prototype.fromTZDate = function(v) {
62     if (!tizen.TZDate || !(v instanceof tizen.TZDate)) {
63         return v;
64     }
65
66     return {
67         year: v.getFullYear(),
68         month: v.getMonth(),
69         day: v.getDate(),
70         timezone: v.getTimezone(),
71         UTCTimestamp: v._utcTimestamp / 1000
72     };
73 };
74
75 var _dateConverter = new DateConverter();
76
77 /** @constructor */
78 function Utils() {
79     /**
80      * Cynara(since tizen 3.0) only support native privilege.
81      * simply web privilege convert native privilege for checking access.
82      */
83     var privilege = {
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'
141     };
142
143     Object.freeze(privilege);
144
145     Object.defineProperty(this, 'privilege', {
146         value: privilege,
147         writable: false,
148         enumerable: true,
149         configurable: false
150     });
151 }
152
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() {};
156
157 Utils.prototype.global = _global;
158
159 Utils.prototype.repackFilter = function(filter) {
160     if (filter instanceof tizen.AttributeFilter) {
161         return {
162             filterType: 'AttributeFilter',
163             attributeName: filter.attributeName,
164             matchFlag: filter.matchFlag,
165             matchValue: _dateConverter.fromTZDate(filter.matchValue)
166         };
167     }
168     if (filter instanceof tizen.AttributeRangeFilter) {
169         return {
170             filterType: 'AttributeRangeFilter',
171             attributeName: filter.attributeName,
172             initialValue: _dateConverter.fromTZDate(filter.initialValue),
173             endValue: _dateConverter.fromTZDate(filter.endValue)
174         };
175     }
176     if (filter instanceof tizen.CompositeFilter) {
177         var _f = [];
178         var filters = filter.filters;
179
180         for (var i = 0; i < filters.length; ++i) {
181             _f.push(this.repackFilter(filters[i]));
182         }
183
184         return {
185             filterType: 'CompositeFilter',
186             type: filter.type,
187             filters: _f
188         };
189     }
190
191     return null;
192 };
193
194 /**
195  * @deprecated You should use xwalk.utils.validator.validateMethod() instead.
196  */
197 Utils.prototype.validateArguments = function(signature, args) {
198     var full_args = Array.prototype.slice.call(args);
199
200     // After '?' everything is optional.
201     var mandatory_len =
202         signature.indexOf('?') === -1 ? signature.length : signature.indexOf('?');
203
204     if (full_args.length < mandatory_len) return false;
205
206     // Mandatory arguments.
207     for (var i = 0; i < mandatory_len; i++) {
208         if (
209             typeof full_args[i] !== signature_to_type[signature[i]] ||
210             full_args[i] === null
211         )
212             return false;
213     }
214
215     // Optional args may be null.
216     for (var i = mandatory_len; i < full_args.length && i < signature.length - 1; i++) {
217         if (
218             full_args[i] !== null &&
219             typeof full_args[i] !== signature_to_type[signature[i + 1]]
220         )
221             return false;
222     }
223
224     return true;
225 };
226
227 Utils.prototype.validateObject = function(object, signature, attributes) {
228     for (var i = 0; i < signature.length; i++) {
229         if (
230             object.hasOwnProperty(attributes[i]) &&
231             typeof object[attributes[i]] !== signature_to_type[signature[i]]
232         ) {
233             return false;
234         }
235     }
236
237     return true;
238 };
239
240 Utils.prototype.getPkgApiVersion = function() {
241     var result = native_.callSync('Utils_getPkgApiVersion');
242     if (native_.isFailure(result)) {
243         throw native_.getErrorObject(result);
244     }
245     return native_.getResultObject(result);
246 };
247
248 Utils.prototype.checkPrivilegeAccess = function(privilege) {
249     var result = native_.callSync('Utils_checkPrivilegeAccess', {
250         privilege: _toString(privilege)
251     });
252
253     if (native_.isFailure(result)) {
254         throw native_.getErrorObject(result);
255     }
256 };
257
258 Utils.prototype.isAppVersionEarlierThan = function(ver) {
259     var app_ver = this.getPkgApiVersion();
260
261     var arr_ver = ver.split('.'); // reference version
262     var arr_app_ver = app_ver.split('.'); // application version
263     var num_ver;
264     var num_app;
265
266     var i;
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) {
272             return true;
273         } else if (num_app > num_ver) {
274             return false;
275         }
276     }
277
278     if (arr_ver.length > arr_app_ver.length) {
279         return true;
280     }
281     return false;
282 };
283
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);
289     }
290 };
291
292 Utils.prototype.checkBackwardCompabilityPrivilegeAccess = function(
293     current_privilege,
294     previous_privilege
295 ) {
296     var result = native_.callSync('Utils_checkBackwardCompabilityPrivilegeAccess', {
297         current_privilege: _toString(current_privilege),
298         previous_privilege: _toString(previous_privilege)
299     });
300
301     if (native_.isFailure(result)) {
302         throw native_.getErrorObject(result);
303     }
304 };
305
306 Utils.prototype.checkProfile = function() {
307     var result = native_.callSync('Utils_checkProfile', {});
308
309     return native_.getResultObject(result);
310 };
311
312 /////////////////////////////////////////////////////////////////////////////
313 /** @constructor */
314 var Type = function() {};
315
316 Type.prototype.isBoolean = function(obj) {
317     return typeof obj === 'boolean';
318 };
319
320 Type.prototype.isObject = function(obj) {
321     return null !== obj && typeof obj === 'object' && !this.isArray(obj);
322 };
323
324 Type.prototype.isArray = function(obj) {
325     return Array.isArray(obj);
326 };
327
328 Type.prototype.isFunction = function(obj) {
329     return typeof obj === 'function';
330 };
331
332 Type.prototype.isNumber = function(obj) {
333     return typeof obj === 'number';
334 };
335
336 Type.prototype.isString = function(obj) {
337     return typeof obj === 'string';
338 };
339
340 Type.prototype.isDate = function(obj) {
341     return obj instanceof Date;
342 };
343
344 Type.prototype.isNull = function(obj) {
345     return obj === null;
346 };
347
348 Type.prototype.isNullOrUndefined = function(obj) {
349     return obj === null || obj === undefined;
350 };
351
352 Type.prototype.isUndefined = function(obj) {
353     return obj === void 0;
354 };
355
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;
359 };
360
361 Type.prototype.isEmptyObject = function(obj) {
362     for (var property in obj) {
363         if (obj.hasOwnProperty(property)) {
364             return false;
365         }
366     }
367     return true;
368 };
369
370 Type.prototype.hasProperty = function(obj, prop) {
371     return prop in obj;
372 };
373
374 Type.prototype.arrayContains = function(arr, value) {
375     return arr.indexOf(value) > -1;
376 };
377
378 Type.prototype.getValues = function(obj) {
379     var ret = [];
380     for (var key in obj) {
381         if (obj.hasOwnProperty(key)) {
382             ret.push(obj[key]);
383         }
384     }
385     return ret;
386 };
387
388 var _type = new Type();
389
390 /////////////////////////////////////////////////////////////////////////////
391 /** @constructor */
392 var Converter = function() {};
393
394 function _nullableGeneric(func, nullable, val) {
395     if (_type.isNull(val) && nullable === true) {
396         return val;
397     } else {
398         return func.apply(null, [].slice.call(arguments, 2));
399     }
400 }
401
402 function _toBoolean(val) {
403     return Boolean(val);
404 }
405
406 Converter.prototype.toBoolean = function(val, nullable) {
407     return _nullableGeneric(_toBoolean, nullable, val);
408 };
409
410 function _toLong(val) {
411     var ret = parseInt(val);
412     return isNaN(ret) ? (val === true ? 1 : 0) : ret;
413 }
414
415 Converter.prototype.toLong = function(val, nullable) {
416     return _nullableGeneric(_toLong, nullable, val);
417 };
418
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', {
425             n: _toLong(val)
426         })
427     );
428 }
429
430 Converter.prototype.toLongLong = function(val, nullable) {
431     return _nullableGeneric(_toLongLong, nullable, val);
432 };
433
434 function _toUnsignedLong(val) {
435     return _toLong(val) >>> 0;
436 }
437
438 Converter.prototype.toUnsignedLong = function(val, nullable) {
439     return _nullableGeneric(_toUnsignedLong, nullable, val);
440 };
441
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', {
448             n: _toLong(val)
449         })
450     );
451 }
452
453 Converter.prototype.toUnsignedLongLong = function(val, nullable) {
454     return _nullableGeneric(_toUnsignedLongLong, nullable, val);
455 };
456
457 function _toShort(val) {
458     return ((_toLong(val) + 32768) & 0xffff) - 32768;
459 }
460
461 Converter.prototype.toShort = function(val, nullable) {
462     return _nullableGeneric(_toShort, nullable, val);
463 };
464
465 function _toUnsignedShort(val) {
466     return Math.abs(_toLong(val)) & 0xffff;
467 }
468
469 Converter.prototype.toUnsignedShort = function(val, nullable) {
470     return _nullableGeneric(_toUnsignedShort, nullable, val);
471 };
472
473 function _toByte(val) {
474     return ((_toLong(val) + 128) & 0xff) - 128;
475 }
476
477 Converter.prototype.toByte = function(val, nullable) {
478     return _nullableGeneric(_toByte, nullable, val);
479 };
480
481 function _toOctet(val) {
482     return _toLong(val) & 0xff;
483 }
484
485 Converter.prototype.toOctet = function(val, nullable) {
486     return _nullableGeneric(_toOctet, nullable, val);
487 };
488
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.'
495         );
496     }
497     return ret;
498 }
499
500 Converter.prototype.toDouble = function(val, nullable) {
501     return _nullableGeneric(_toDouble, nullable, val);
502 };
503
504 function _toString(val) {
505     return String(val);
506 }
507
508 Converter.prototype.toString = function(val, nullable) {
509     return _nullableGeneric(_toString, nullable, val);
510 };
511
512 function _toPlatformObject(val, types) {
513     var t;
514
515     if (_type.isArray(types)) {
516         t = types;
517     } else {
518         t = [types];
519     }
520
521     if (_type.isArray(val)) {
522         throw new WebAPIException(
523             WebAPIException.TYPE_MISMATCH_ERR,
524             'Cannot convert ' + String(val) + ' to ' + String(t[0].name) + '.'
525         );
526     }
527
528     var match = false;
529     for (var i = 0; i < t.length; ++i) {
530         if (val instanceof t[i]) {
531             return val;
532         }
533     }
534
535     throw new WebAPIException(
536         WebAPIException.TYPE_MISMATCH_ERR,
537         'Cannot convert ' + String(val) + ' to ' + String(t[0].name) + '.'
538     );
539 }
540
541 Converter.prototype.toPlatformObject = function(val, types, nullable) {
542     return _nullableGeneric(_toPlatformObject, nullable, val, types);
543 };
544
545 function _toFunction(val) {
546     if (_type.isFunction(val)) {
547         return val;
548     }
549
550     throw new WebAPIException(
551         WebAPIException.TYPE_MISMATCH_ERR,
552         'Cannot convert ' + String(val) + ' to function.'
553     );
554 }
555
556 Converter.prototype.toFunction = function(val, nullable) {
557     return _nullableGeneric(_toFunction, nullable, val);
558 };
559
560 function _toArray(val) {
561     if (_type.isArray(val)) {
562         return val;
563     }
564
565     throw new WebAPIException(
566         WebAPIException.TYPE_MISMATCH_ERR,
567         'Cannot convert ' + String(val) + ' to array.'
568     );
569 }
570
571 Converter.prototype.toArray = function(val, nullable) {
572     return _nullableGeneric(_toArray, nullable, val);
573 };
574
575 function _toDictionary(val) {
576     if (_type.isObject(val) || _type.isFunction(val)) {
577         return val;
578     }
579
580     throw new WebAPIException(
581         WebAPIException.TYPE_MISMATCH_ERR,
582         'Cannot convert ' + String(val) + ' to dictionary.'
583     );
584 }
585
586 Converter.prototype.toDictionary = function(val, nullable) {
587     return _nullableGeneric(_toDictionary, nullable, val);
588 };
589
590 function _toEnum(val, e) {
591     var v = _toString(val);
592     if (_type.arrayContains(e, v)) {
593         return v;
594     }
595
596     throw new WebAPIException(
597         WebAPIException.TYPE_MISMATCH_ERR,
598         'Cannot convert ' + v + ' to enum.'
599     );
600 }
601
602 Converter.prototype.toEnum = function(val, e, nullable) {
603     return _nullableGeneric(_toEnum, nullable, val, e);
604 };
605
606 var _converter = new Converter();
607
608 /////////////////////////////////////////////////////////////////////////////
609 /** @constructor */
610 var Validator = function() {
611     this.Types = {
612         BOOLEAN: 'BOOLEAN',
613         LONG: 'LONG',
614         LONG_LONG: 'LONG_LONG',
615         UNSIGNED_LONG: 'UNSIGNED_LONG',
616         UNSIGNED_LONG_LONG: 'UNSIGNED_LONG_LONG',
617         BYTE: 'BYTE',
618         OCTET: 'OCTET',
619         DOUBLE: 'DOUBLE',
620         STRING: 'STRING',
621         FUNCTION: 'FUNCTION',
622         DICTIONARY: 'DICTIONARY',
623         PLATFORM_OBJECT: 'PLATFORM_OBJECT',
624         LISTENER: 'LISTENER',
625         ARRAY: 'ARRAY',
626         ENUM: 'ENUM',
627         FILE_REFERENCE: 'FILE_REFERENCE',
628         SIMPLE_TYPE: 'SIMPLE_TYPE' // Boolean, Number or String
629     };
630 };
631
632 /**
633  * Verifies if arguments passed to function are valid.
634  *
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
649  *                 function
650  *
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
655  *
656  * @code
657  * [
658  *   {
659  *     name: 'first',
660  *     type: 'aType'
661  *   }
662  * ]
663  * @code
664  * [
665  *   {
666  *     name: 'first',
667  *     type: 'aType',
668  *     optional: true
669  *   }
670  * ]
671  * @code
672  * [
673  *   {
674  *     name: 'first',
675  *     type: 'aType',
676  *     nullable: true
677  *   }
678  * ]
679  * @code
680  * [
681  *   {
682  *     name: 'first',
683  *     type: 'aType',
684  *     optional: true,
685  *     nullable: true
686  *   }
687  * ]
688  * @code
689  * [
690  *   {
691  *     name: 'first',
692  *     type: Validator.Types.PLATFORM_OBJECT,
693  *     values: ApplicationControl // type of platform object
694  *   }
695  * ]
696  * @code
697  * [
698  *   {
699  *     name: 'first',
700  *     type: Validator.Types.PLATFORM_OBJECT,
701  *     values: [Alarm, AlarmRelative, AlarmAbsolute] // accepted types
702  *   }
703  * ]
704  * @code
705  * [
706  *   {
707  *     name: 'first',
708  *     type: Validator.Types.LISTENER,
709  *     values: ['onsuccess', 'onfailure'] // array of callbacks' names
710  *   }
711  * ]
712  * @code
713  * [
714  *   {
715  *     name: 'first',
716  *     type: Validator.Types.ARRAY,
717  *     values: ApplicationControlData // type of each element in array,
718  *                                    // tested with instanceof
719  *   }
720  * ]
721  * @code
722  * [
723  *   {
724  *     name: 'first',
725  *     type: Validator.Types.ARRAY,
726  *     values: Validator.Types.DOUBLE // converts elements, only primitive types are
727  *                                          supported
728  *   }
729  * ]
730  * @code
731  * [
732  *   {
733  *     name: 'first',
734  *     type: Validator.Types.ENUM,
735  *     values: ['SCREEN_DIM', 'SCREEN_NORMAL', 'CPU_AWAKE'] // array of allowed values
736  *   }
737  * ]
738  */
739 Validator.prototype.validateArgs = function(a, d) {
740     var args = { has: {} };
741
742     for (var i = 0; i < d.length; ++i) {
743         var name = d[i].name;
744         args.has[name] = i < a.length;
745
746         var optional = d[i].optional;
747         var nullable = d[i].nullable;
748         var val = a[i];
749
750         if (args.has[name] || !optional) {
751             var type = d[i].type;
752             var values = d[i].values;
753
754             switch (type) {
755             case this.Types.BOOLEAN:
756                 val = _converter.toBoolean(val, nullable);
757                 break;
758
759             case this.Types.LONG:
760                 val = _converter.toLong(val, nullable);
761                 break;
762
763             case this.Types.LONG_LONG:
764                 val = _converter.toLongLong(val, nullable);
765                 break;
766
767             case this.Types.UNSIGNED_LONG:
768                 val = _converter.toUnsignedLong(val, nullable);
769                 break;
770
771             case this.Types.UNSIGNED_LONG_LONG:
772                 val = _converter.toUnsignedLongLong(val, nullable);
773                 break;
774
775             case this.Types.BYTE:
776                 val = _converter.toByte(val, nullable);
777                 break;
778
779             case this.Types.OCTET:
780                 val = _converter.toOctet(val, nullable);
781                 break;
782
783             case this.Types.DOUBLE:
784                 val = _converter.toDouble(val, nullable);
785                 break;
786
787             case this.Types.STRING:
788                 val = _converter.toString(val, nullable);
789                 break;
790
791             case this.Types.FUNCTION:
792                 val = _converter.toFunction(val, nullable);
793                 break;
794
795             case this.Types.DICTIONARY:
796                 val = _converter.toDictionary(val, nullable);
797                 break;
798
799             case this.Types.PLATFORM_OBJECT:
800                 val = _converter.toPlatformObject(val, values, nullable);
801                 break;
802
803             case this.Types.LISTENER:
804                 if (_type.isNull(val)) {
805                     if (!nullable) {
806                         throw new WebAPIException(
807                             WebAPIException.TYPE_MISMATCH_ERR,
808                             'Argument "' + name + '" cannot be null.'
809                         );
810                     }
811                 } else {
812                     if (!_type.isObject(val)) {
813                         throw new WebAPIException(
814                             WebAPIException.TYPE_MISMATCH_ERR,
815                             'Argument "' + name + '" should be an object.'
816                         );
817                     }
818                     for (var ii = 0; ii < values.length; ++ii) {
819                         if (_type.hasProperty(val, values[ii])) {
820                             val[values[ii]] = _converter.toFunction(
821                                 val[values[ii]],
822                                 false
823                             );
824                         }
825                     }
826                 }
827                 break;
828
829             case this.Types.ARRAY:
830                 val = _converter.toArray(val, nullable);
831                 if (!_type.isNull(val) && values) {
832                     var func;
833
834                     switch (values) {
835                     case this.Types.BOOLEAN:
836                         func = _converter.toBoolean;
837                         break;
838
839                     case this.Types.LONG:
840                         func = _converter.toLong;
841                         break;
842
843                     case this.Types.LONG_LONG:
844                         func = _converter.toLongLong;
845                         break;
846
847                     case this.Types.UNSIGNED_LONG:
848                         func = _converter.toUnsignedLong;
849                         break;
850
851                     case this.Types.UNSIGNED_LONG_LONG:
852                         func = _converter.toUnsignedLongLong;
853                         break;
854
855                     case this.Types.BYTE:
856                         func = _converter.toByte;
857                         break;
858
859                     case this.Types.OCTET:
860                         func = _converter.toOctet;
861                         break;
862
863                     case this.Types.DOUBLE:
864                         func = _converter.toDouble;
865                         break;
866
867                     case this.Types.STRING:
868                         func = _converter.toString;
869                         break;
870
871                     default:
872                         func = function(val) {
873                             if (!(val instanceof values)) {
874                                 throw new WebAPIException(
875                                     WebAPIException.TYPE_MISMATCH_ERR,
876                                     'Items of array "' +
877                                                 name +
878                                                 '" should be of type: ' +
879                                                 values +
880                                                 '.'
881                                 );
882                             }
883                             return val;
884                         };
885                     }
886
887                     for (var j = 0; j < val.length; ++j) {
888                         val[j] = func(val[j]);
889                     }
890                 }
891                 break;
892
893             case this.Types.ENUM:
894                 val = _converter.toEnum(val, values, nullable);
895                 break;
896
897             case this.Types.FILE_REFERENCE:
898                 if (
899                     _type.isObject(val) &&
900                         'File' === val.constructor.name &&
901                         val.fullPath
902                 ) {
903                     val = val.fullPath;
904                 }
905                 val = _converter.toString(val, nullable);
906                 break;
907
908             case this.Types.SIMPLE_TYPE:
909                 if (optional && _type.isUndefined(val)) {
910                     break;
911                 }
912                 if (nullable && _type.isNull(val)) {
913                     break;
914                 }
915                 if (
916                     !_type.isBoolean(val) &&
917                         !_type.isNumber(val) &&
918                         !_type.isString(val)
919                 ) {
920                     throw new WebAPIException(
921                         WebAPIException.TYPE_MISMATCH_ERR,
922                         'Argument "' + name + '" should be boolean, number or string.'
923                     );
924                 }
925                 break;
926
927             default:
928                 throw new WebAPIException(
929                     WebAPIException.TYPE_MISMATCH_ERR,
930                     'Unknown type: "' + type + '".'
931                 );
932             }
933
934             var _validator = d[i].validator;
935
936             if (_type.isFunction(_validator) && !_validator(val)) {
937                 throw new WebAPIException(
938                     WebAPIException.TYPE_MISMATCH_ERR,
939                     'Argument "' + name + '" did not pass additional validation.'
940                 );
941             }
942
943             args[name] = val;
944         }
945     }
946
947     return args;
948 };
949
950 /**
951  * @deprecated Use validateArgs() instead.
952  */
953 Validator.prototype.validateMethod = function(a, d) {
954     return this.validateArgs(a, d);
955 };
956
957 /**
958  * Use this helper to ensure that constructor is invoked by "new" operator.
959  *
960  * @param {Object} obj
961  * @param {Function} instance
962  */
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
966         // current TCTs.
967         // For Tizen compliance it's wrapped into WebAPIException.
968         throw new WebAPIException(
969             'TypeError',
970             'Constructor cannot be called as function.'
971         );
972     }
973
974     Object.defineProperty(obj, '_previouslyConstructed', {
975         value: true,
976         writable: false,
977         enumerable: false
978     });
979 };
980
981 /**
982  * @deprecated Use isConstructorCall() instead.
983  */
984 Validator.prototype.validateConstructorCall = function(obj, instance) {
985     this.isConstructorCall(obj, instance);
986 };
987
988 var _validator = new Validator();
989
990 /////////////////////////////////////////////////////////////////////////////
991 /** @constructor */
992 var NativeManager = function(extension) {
993     /**
994      * @type {string}
995      * @const
996      */
997     this.CALLBACK_ID_KEY = 'callbackId';
998
999     /**
1000      * @type {string}
1001      * @const
1002      */
1003     this.LISTENER_ID_KEY = 'listenerId';
1004
1005     /**
1006      * @type {Object}
1007      * @private
1008      */
1009     var extension_ = extension;
1010
1011     /**
1012      * @type {number}
1013      * @private
1014      */
1015     var replyId_ = 0;
1016
1017     /**
1018      * Map of async reply callbacks.
1019      *
1020      * @type {Object.<number, function>}
1021      * @protected
1022      */
1023     this.callbacks_ = {};
1024
1025     /**
1026      * Map of registered listeners.
1027      *
1028      * @type {Object.<string, function>}
1029      * @protected
1030      */
1031     this.listeners_ = {};
1032
1033     _validator.isConstructorCall(this, NativeManager);
1034
1035     // TODO: Remove mockup if WRT implements sendRuntimeMessage
1036     // This is temporary mockup!
1037     extension.sendRuntimeMessage =
1038         extension.sendRuntimeMessage ||
1039         function() {
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!'
1044             );
1045         };
1046
1047     extension.sendRuntimeAsyncMessage =
1048         extension.sendRuntimeAsyncMessage ||
1049         function() {
1050             xwalk.utils.error(
1051                 'Runtime did not implement extension.sendRuntimeAsyncMessage!'
1052             );
1053             throw new WebAPIException(
1054                 WebAPIException.UNKNOWN_ERR,
1055                 'Runtime did not implement extension.sendRuntimeAsyncMessage!'
1056             );
1057         };
1058
1059     extension.sendRuntimeSyncMessage =
1060         extension.sendRuntimeSyncMessage ||
1061         function() {
1062             xwalk.utils.error(
1063                 'Runtime did not implement extension.sendRuntimeSyncMessage!'
1064             );
1065             throw new WebAPIException(
1066                 WebAPIException.UNKNOWN_ERR,
1067                 'Runtime did not implement extension.sendRuntimeSyncMessage!'
1068             );
1069         };
1070
1071     // check extension prototype
1072     if (
1073         !extension ||
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)
1081     ) {
1082         throw new WebAPIException(
1083             WebAPIException.TYPE_MISMATCH_ERR,
1084             'Wrong extension object passed'
1085         );
1086     }
1087
1088     Object.defineProperties(this, {
1089         nextReplyId: {
1090             get: function() {
1091                 return ++replyId_;
1092             },
1093             enumerable: false
1094         },
1095         extension: {
1096             get: function() {
1097                 return extension_;
1098             },
1099             enumerable: true
1100         }
1101     });
1102
1103     extension_.setMessageListener(
1104         function(json) {
1105             try {
1106                 var msg = JSON_.parse(json);
1107             } catch (error) {
1108                 // Because of special handling of power lock in chromium, the special
1109                 // signals:
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
1116                 // be removed.
1117                 if (json.substring(0, 2) === '__') {
1118                     return;
1119                 }
1120                 xwalk.utils.error('Ignoring message - Invalid JSON received: ' + json);
1121                 return;
1122             }
1123             var id;
1124
1125             if (msg.hasOwnProperty(this.CALLBACK_ID_KEY)) {
1126                 id = msg[this.CALLBACK_ID_KEY];
1127                 delete msg[this.CALLBACK_ID_KEY];
1128
1129                 if (!_type.isFunction(this.callbacks_[id])) {
1130                     xwalk.utils.error('Wrong callback identifier. Ignoring message.');
1131                     return;
1132                 }
1133
1134                 var f = this.callbacks_[id];
1135                 setTimeout(function() {
1136                     try {
1137                         f(msg);
1138                     } catch (e) {
1139                         xwalk.utils.error('########## exception');
1140                         xwalk.utils.error(e);
1141                     }
1142                 }, 0);
1143                 delete this.callbacks_[id];
1144
1145                 return;
1146             }
1147
1148             if (msg.hasOwnProperty(this.LISTENER_ID_KEY)) {
1149                 id = msg[this.LISTENER_ID_KEY];
1150                 delete msg[this.LISTENER_ID_KEY];
1151
1152                 if (!_type.isFunction(this.listeners_[id])) {
1153                     xwalk.utils.error('Wrong listener identifier. Ignoring message.');
1154                     return;
1155                 }
1156
1157                 var f = this.listeners_[id];
1158                 setTimeout(function() {
1159                     try {
1160                         f(msg);
1161                     } catch (e) {
1162                         xwalk.utils.error('########## exception');
1163                         xwalk.utils.error(e);
1164                     }
1165                 }, 0);
1166
1167                 return;
1168             }
1169
1170             xwalk.utils.error(
1171                 'Missing callback or listener identifier. Ignoring message.'
1172             );
1173         }.bind(this)
1174     );
1175 };
1176
1177 NativeManager.prototype.call = function(cmd, args, callback) {
1178     args = args || {};
1179
1180     var replyId = this.nextReplyId;
1181     args[this.CALLBACK_ID_KEY] = replyId;
1182     this.callbacks_[replyId] = callback;
1183
1184     return this.callSync(cmd, args);
1185 };
1186
1187 NativeManager.prototype.callSync = function(cmd, args) {
1188     var request = JSON_.stringify({
1189         cmd: cmd,
1190         args: args || {}
1191     });
1192
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');
1197     }
1198     return JSON_.parse(response);
1199 };
1200
1201 NativeManager.prototype.sendRuntimeMessage = function(msg, body) {
1202     return this.extension.sendRuntimeMessage(msg, body || '');
1203 };
1204
1205 NativeManager.prototype.sendRuntimeAsyncMessage = function(msg, body, callback) {
1206     var handler = function(response) {
1207         if (_type.isFunction(callback)) {
1208             var result = {};
1209             if ('success' === response.toLowerCase()) {
1210                 result.status = 'success';
1211             } else {
1212                 result.status = 'error';
1213                 result.error = new WebAPIException(
1214                     WebAPIException.UNKNOWN_ERR,
1215                     'Runtime message failure'
1216                 );
1217             }
1218             callback(result);
1219         }
1220     };
1221     return this.extension.sendRuntimeAsyncMessage(msg, body || '', handler);
1222 };
1223
1224 NativeManager.prototype.sendRuntimeSyncMessage = function(msg, body) {
1225     return this.extension.sendRuntimeSyncMessage(msg, body || '');
1226 };
1227
1228 NativeManager.prototype.addListener = function(name, callback) {
1229     if (!_type.isString(name) || !name.length) {
1230         throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
1231     }
1232
1233     this.listeners_[name] = callback;
1234 };
1235
1236 NativeManager.prototype.removeListener = function(name) {
1237     if (this.listeners_.hasOwnProperty(name)) {
1238         delete this.listeners_[name];
1239     }
1240 };
1241
1242 NativeManager.prototype.isListenerSet = function(name) {
1243     return this.listeners_.hasOwnProperty(name);
1244 };
1245
1246 NativeManager.prototype.isSuccess = function(result) {
1247     return result.status !== 'error';
1248 };
1249
1250 NativeManager.prototype.isFailure = function(result) {
1251     return !this.isSuccess(result);
1252 };
1253
1254 NativeManager.prototype.getResultObject = function(result) {
1255     return result.result;
1256 };
1257
1258 NativeManager.prototype.getErrorObject = function(result) {
1259     return new WebAPIException(result.error);
1260 };
1261
1262 NativeManager.prototype.callIfPossible = function(callback) {
1263     if (!_type.isNullOrUndefined(callback)) {
1264         callback.apply(callback, [].slice.call(arguments, 1));
1265     }
1266 };
1267
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;
1277 }
1278
1279 function __isUndefined(object) {
1280     return object === void 0;
1281 }
1282
1283 function __isNumber(object) {
1284     return typeof object === 'number';
1285 }
1286
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
1289 // something here.
1290 var errors = {
1291     NO_ERROR: 0,
1292     UNKNOWN_ERR: -1,
1293
1294     INDEX_SIZE_ERR: 1,
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,
1301     NOT_FOUND_ERR: 8,
1302     NOT_SUPPORTED_ERR: 9,
1303     INUSE_ATTRIBUTE_ERR: 10,
1304     INVALID_STATE_ERR: 11,
1305     SYNTAX_ERR: 12,
1306     INVALID_MODIFICATION_ERR: 13,
1307     NAMESPACE_ERR: 14,
1308     INVALID_ACCESS_ERR: 15,
1309     VALIDATION_ERR: 16,
1310     TYPE_MISMATCH_ERR: 17,
1311     SECURITY_ERR: 18,
1312     NETWORK_ERR: 19,
1313     ABORT_ERR: 20,
1314     URL_MISMATCH_ERR: 21,
1315     QUOTA_EXCEEDED_ERR: 22,
1316     TIMEOUT_ERR: 23,
1317     INVALID_NODE_TYPE_ERR: 24,
1318     DATA_CLONE_ERR: 25,
1319
1320     // Error codes for these errors are not really defined anywhere.
1321     INVALID_VALUES_ERR: 100,
1322     IO_ERR: 101,
1323     PERMISSION_DENIED_ERR: 102,
1324     SERVICE_NOT_AVAILABLE_ERR: 103,
1325     DATABASE_ERR: 104,
1326     VERIFICATION_ERR: 105
1327 };
1328
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';
1357
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';
1364
1365 var name_to_code = {};
1366 Object.keys(errors).forEach(function(key) {
1367     name_to_code[code_to_name[errors[key]]] = errors[key];
1368 });
1369
1370 /**
1371  * Generic exception interface.
1372  *
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.
1377  */
1378 var WebAPIException = function(code, message, name) {
1379     var code_ = 0;
1380     var name_ = code_to_name[code];
1381     var message_ = 'Unknown error';
1382
1383     switch (arguments.length) {
1384     case 1:
1385         var error = arguments[0];
1386         if (__isObject(error)) {
1387             code_ = error.code;
1388             name_ = error.name;
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
1396             code_ = error;
1397             name_ = code_to_name[code];
1398             message_ = name_;
1399         }
1400         break;
1401     case 2:
1402         if (__isNumber(arguments[0])) {
1403             code_ = arguments[0];
1404             if (!__isUndefined(code_to_name[code_])) {
1405                 name_ = code_to_name[code_];
1406             }
1407         } else {
1408             name_ = String(arguments[0]);
1409             if (!__isUndefined(name_to_code[name_])) {
1410                 code_ = name_to_code[name_];
1411             }
1412         }
1413         message_ = String(arguments[1]);
1414         break;
1415     case 3:
1416         // backward compatibility with crosswalk implementation
1417         code_ = Number(arguments[0]);
1418         message_ = String(arguments[1]);
1419         name_ = String(arguments[2]);
1420         break;
1421     default:
1422         return;
1423     }
1424
1425     if (code_ > errors.DATA_CLONE_ERR) {
1426         code_ = 0;
1427     }
1428
1429     // attributes
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 }
1434     });
1435
1436     this.constructor.prototype.__proto__ = Error.prototype;
1437     Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
1438     // V8-specific code
1439 };
1440
1441 WebAPIException.prototype.toString = function() {
1442     return this.name + ': ' + this.message;
1443 };
1444
1445 var error_constants = {};
1446 for (var prop in errors) {
1447     error_constants[prop] = { value: errors[prop], writable: false, enumerable: true };
1448 }
1449 Object.defineProperties(WebAPIException, error_constants);
1450 Object.defineProperties(WebAPIException.prototype, error_constants);
1451
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.
1455 var scope;
1456 if (typeof window !== 'undefined') {
1457     scope = window;
1458 } else if (typeof global !== 'undefined') {
1459     scope = global;
1460 }
1461 scope = scope || {};
1462 scope.WebAPIException = WebAPIException;
1463 scope.WebAPIError = WebAPIException;
1464
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;
1470
1471 var native_ = new NativeManager(extension);
1472
1473 exports.utils = new Utils();
1474
1475 Object.freeze(exports);
1476 Object.freeze(exports.utils);
1477 Object.freeze(Utils.prototype);
1478 Object.freeze(NativeManager.prototype);