1
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
2
Components.utils.import("resource://unity/unity-misc-utils.js");
4
var EXPORTED_SYMBOLS = [ "makeAPI" ];
6
function makeAPI(setTimeout, contextAddApplicationActions, init, toDataURL, log, get_uwa, unity, CallbackManager, acceptDataCb) {
8
function checkString(str, allowUndef) {
9
if (allowUndef && str == undefined) {
12
if (!str || typeof(str) !== 'string') {
13
throw new TypeError("incorrect argument");
16
function findName(func, prefix, obj) {
18
return findName(func, 'Unity.', api);
20
var keys = Object.keys(obj);
21
for (var i = 0; i < keys.length; i++) {
22
if (typeof(keys[i]) !== 'string') {
25
var descr = Object.getOwnPropertyDescriptor(obj, keys[i]);
26
if (descr.value === func) {
27
return prefix + keys[i];
29
if (descr.value instanceof Object) {
30
var res = findName(func, prefix + keys[i] + '.', obj[keys[i]]);
34
if (obj.__lookupGetter__(keys[i]) === func) {
35
return prefix + keys[i];
37
if (obj.__lookupSetter__(keys[i]) === func) {
38
return prefix + keys[i];
43
function stringify(obj) {
44
if (obj === undefined)
48
if (typeof(obj) == 'string')
50
if (typeof(obj) == 'number')
52
if (typeof(obj) == 'function')
56
if (obj.hasOwnProperty(i))
57
dump[i] = stringify(obj[i]);
61
function stringifyArgs(obj) {
63
for (var i = 0; i < obj.length; i++) {
64
args.push(stringify(obj[i]));
66
var res = JSON.stringify(args);
67
return res.substr(1, res.length - 2);
69
function createArgumentsSanitaizer(func, argsDesc, callback) {
73
var realArgs = arguments;
75
var name = findName(arguments.callee);
76
log(String(name) + '(' + stringifyArgs(arguments) + ')');
78
if (unity.context == null || unity.contextReady == false) {return;}
80
function argumentSanitaizer(desc, arg) {
82
throw new InternalError("argument description is null");
89
if (!(desc.array instanceof Object) || !(desc.array.element instanceof Object)) {
90
throw new InternalError("invalid argument description");
94
for (var j = 0; j < arg.length; j++) {
95
argumentSanitaizer(desc.array.element, arg[j]);
98
throw new TypeError("incorrect argument");
103
if (!(desc.obj instanceof Object)) {
104
throw new InternalError("invalid argument description");
107
for (i in desc.obj) {
108
if (desc.obj.hasOwnProperty(i)) {
112
for (i in desc.obj) {
113
if (desc.obj.hasOwnProperty(i)) {
114
res[desc.obj[i].place] = argumentSanitaizer(desc.obj[i], arg[i]);
120
if (desc.allowNull && !arg) {
123
checkString(arg, false);
127
if (typeof(arg) !== 'number' && typeof(arg) !== 'boolean')
128
throw new TypeError("incorrect argument");
132
throw new InternalError("argument description miss required parameter");
134
if ((arg instanceof desc.type) || (desc.type === Function && ((typeof arg) === 'function'))
135
|| (arg === null && desc.allowNull)) {
136
if (desc.type === Function) {
142
if (desc.argAsCallbackId !== undefined) {
143
id = realArgs[desc.argAsCallbackId];
147
return CallbackManager.makeCallback(uwa.ContextActionCallbackType,
148
function (context, user_data) {
154
throw new TypeError("incorrect argument");
156
throw new InternalError("unreacheable");
158
var args = [unity.context], i;
159
for (i = 0; i < argsDesc.length; i++) {
160
if (k >= realArgs.length && k > 0 && !argsDesc[i].dummy) {
161
throw new Error("not enough arguments");
164
var value = argumentSanitaizer(argsDesc[i], realArgs[k]);
166
if (argsDesc[i].obj) {
167
args = args.concat(value);
173
if (k < realArgs.length) {
174
throw new Error("too much arguments");
178
callback.apply(uwa, args);
180
return Function.apply.apply(func, [uwa, args]);
187
var timeoutId = null;
188
function fireContextAddApplicationActions() {
190
if (unity.context == null || unity.contextReady == false) {return;}
191
contextAddApplicationActions(actions);
193
var firstAddStaticAction = true;
195
init: function(props) {
197
checkString(props.name, false);
198
checkString(props.iconUrl, true);
199
checkString(props.domain, true);
200
checkString(props.login, true);
201
checkString(props.mimeTypes, true);
202
checkString(props.homepage, true);
203
if (props.homepage && !/^(http|https|file):\/\//.test(props.homepage)) {
204
throw new TypeError("incorrect argument");
215
toDataURL(props.iconUrl, function (aResult, uri) {
217
for (var i in props) {
218
if (props.hasOwnProperty(i)) {
229
acceptData: createArgumentsSanitaizer(null, [{ array: { element: { str: true } } },
230
{ type: Function, js: true }],
233
addAction: createArgumentsSanitaizer(null, [{ str: true },
234
{ type: Function, argAsCallbackId: 0 }],
235
function (context, name, callback) {
236
actions.push({ name: name, callback: callback });
237
if (timeoutId == null) {
238
timeoutId = setTimeout(fireContextAddApplicationActions, 100);
241
clearAction: createArgumentsSanitaizer(uwa.context_remove_application_action,
242
[{ str: true }], fireContextAddApplicationActions),
243
clearActions: createArgumentsSanitaizer(uwa.context_remove_application_actions,
246
fireContextAddApplicationActions();
247
CallbackManager.releaseCallback('Unity.addAction');
251
init: createArgumentsSanitaizer(uwa.music_player_init, [{ str: true }]),
253
onPlayPause: createArgumentsSanitaizer(uwa.music_player_on_play_pause_callback,
254
[{ type: Function, allowNull: true }, { dummy: true }]),
256
onPrevious: createArgumentsSanitaizer(uwa.music_player_on_previous_callback,
257
[{ type: Function, allowNull: true }, { dummy: true }]),
259
onNext: createArgumentsSanitaizer(uwa.music_player_on_next_callback,
260
[{ type: Function, allowNull: true }, { dummy: true }]),
262
setTrack: createArgumentsSanitaizer(uwa.music_player_set_track,
263
[{ obj: { artist: { str: true, place: 0, allowNull: true },
264
album: { str: true, place: 1, allowNull: true },
265
title: { str: true, place: 2 },
266
artLocation: { str: true, place: 3, allowNull: true } } }]),
268
setCanGoNext: createArgumentsSanitaizer(uwa.music_player_set_can_go_next, [{ number: true }]),
270
setCanGoPrevious: createArgumentsSanitaizer(uwa.music_player_set_can_go_previous, [{ number: true }]),
272
setCanPlay: createArgumentsSanitaizer(uwa.music_player_set_can_play, [{ number: true }]),
274
setCanPause: createArgumentsSanitaizer(uwa.music_player_set_can_pause, [{ number: true }]),
276
setPlaybackState: createArgumentsSanitaizer(uwa.music_player_set_playback_state, [{ number: true }]),
278
getPlaybackState: createArgumentsSanitaizer(null
279
, [{ type: Function }]
280
, function (callback) {
282
callback (uwa.music_player_get_playback_state(unity.context));
285
PlaybackState: {PLAYING: 0, PAUSED:1}
289
showNotification: createArgumentsSanitaizer(uwa.notification_show_notification,
290
[{ str: true }, { str: true }, { str: true, allowNull: true }])
294
setCount: createArgumentsSanitaizer(uwa.launcher_set_count,
296
clearCount: createArgumentsSanitaizer(uwa.launcher_clear_count,
298
setProgress: createArgumentsSanitaizer(uwa.launcher_set_progress,
300
clearProgress: createArgumentsSanitaizer(uwa.launcher_clear_progress,
302
setUrgent: createArgumentsSanitaizer(uwa.launcher_set_urgent,
304
_addAction: createArgumentsSanitaizer(uwa.launcher_add_action,
305
[{ str: true }, { type: Function, argAsCallbackId: 0 }, { dummy: true }]),
306
_addStaticAction: createArgumentsSanitaizer(uwa.launcher_add_static_action,
307
[{ str: true }, { str: true }]),
308
addAction: function (arg1, arg2) {
309
if (typeof(arg2) === 'string') {
310
if (firstAddStaticAction)
311
uwa.launcher_remove_static_actions(unity.context);
312
firstAddStaticAction = false;
313
this._addStaticAction(arg1, arg2);
315
this._addAction(arg1, arg2);
318
removeAction: createArgumentsSanitaizer(uwa.launcher_remove_action,
320
removeActions: createArgumentsSanitaizer(uwa.launcher_remove_actions,
321
[], function () {CallbackManager.releaseCallback('Unity.Launcher.addAction');})
324
MessagingIndicator: {
325
addAction: createArgumentsSanitaizer(uwa.indicator_add_action,
326
[{ str: true }, { type: Function, argAsCallbackId: 0 }, { dummy: true }]),
327
showIndicator: function(name, properties) {
328
log('Unity.MessagingIndicator.showIndicator(' + stringifyArgs(arguments) + ')');
330
if (unity.context == null) {return};
332
checkString(name, false);
335
uwa.indicator_show_indicator(unity.context, String(name));
336
for (i in properties) {
338
uwa.indicator_set_property(unity.context, String(name), i, UnityMiscUtils.toISODate(properties[i]));
340
else if (i == "icon") {
341
uwa.indicator_set_property_icon(unity.context, String(name), i, String(properties[i]));
343
else if (i == "callback") {
344
var callback = CallbackManager.makeCallback(uwa.IndicatorCallbackType,
345
(function (propidx) {
346
return function (context, user_data) {
347
(properties[propidx])();
350
'Unity.MessagingIndicator.showIndicator', name);
352
uwa.indicator_set_callback(unity.context, String(name), callback, null);
354
else if (i == "count") {
355
uwa.indicator_set_property(unity.context, String(name), i, String(Number(properties[i])));
358
uwa.indicator_set_property(unity.context, String(name), i, String(properties[i]));
362
clearIndicator: createArgumentsSanitaizer(uwa.indicator_clear_indicator, [{ str: true }]),
363
clearIndicators: createArgumentsSanitaizer(uwa.indicator_clear_indicators, [], function () {CallbackManager.releaseCallback('Unity.MessagingIndicator.showIndicator');})