[Cpplint] Re-enable style checker for download and fix some errors.
[platform/framework/web/tizen-extensions-crosswalk.git] / download / download_api.js
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var repliedMsg;
6 var currentUID = 0;
7 var requests = {};
8 var startListeners = [];
9 var networkTypeCallbacks = [];
10 var mimeTypeCallbacks = [];
11 var httpHeaderCallbacks = [];
12
13 var postMessage = function(msg) {
14   extension.postMessage(JSON.stringify(msg));
15 };
16
17 var asValidString = function(o) {
18   return (typeof o == 'string') ? o : '';
19 };
20
21 var ensureType = function(o, expected) {
22   if (typeof o != expected) {
23     throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
24   }
25 };
26
27 var ensureHas = function(o) {
28   if (typeof o == 'undefined') {
29     throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
30   }
31 };
32
33 var getNetworkTypeThrowsError = function(networkType) {
34   if (typeof networkType == 'undefined') {
35     return 'ALL';
36   } else if (networkType in AllowDownloadOnNetworkType) {
37     return networkType;
38   } else {
39     throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
40   }
41 };
42
43 var errorMap = {
44   'DOWNLOAD_ERROR_NONE': {
45     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
46     name: 'NotSupportedError',
47     message: 'Download successful'
48   },
49   'DOWNLOAD_UNKNOWN_ERROR': {
50     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
51     name: 'NotSupportedError',
52     message: 'Unknown error'
53   },
54   'DOWNLOAD_ERROR_INVALID_PARAMETER': {
55     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
56     name: 'NotSupportedError',
57     message: 'Invalid parameter'
58   },
59   'DOWNLOAD_ERROR_FIELD_NOT_FOUND': {
60     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
61     name: 'NotSupportedError',
62     message: 'Specified field not found'
63   },
64   'DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS': {
65     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
66     name: 'NotSupportedError',
67     message: 'Full of available downloading items from server'
68   },
69   'DOWNLOAD_ERROR_FILE_ALREADY_EXISTS': {
70     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
71     name: 'NotSupportedError',
72     message: 'It is failed to rename the downloaded file'
73   },
74   'DOWNLOAD_ERROR_INVALID_URL': {
75     code: tizen.WebAPIException.SYNTAX_ERR,
76     name: 'SyntaxError',
77     message: 'Invalid URL'
78   },
79   'DOWNLOAD_ERROR_INVALID_DESTINATION': {
80     code: tizen.WebAPIException.SYNTAX_ERR,
81     name: 'SyntaxError',
82     message: 'Invalid destination'
83   },
84   'DOWNLOAD_ERROR_INVALID_STATE': {
85     code: tizen.WebAPIException.INVALID_STATE_ERR,
86     name: 'InvalidStateError',
87     message: 'Invalid state'
88   },
89   'DOWNLOAD_ERROR_ALREADY_COMPLETED': {
90     code: tizen.WebAPIException.INVALID_STATE_ERR,
91     name: 'InvalidStateError',
92     message: 'The download is already completed'
93   },
94   'DOWNLOAD_ERROR_CANNOT_RESUME': {
95     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
96     name: 'NotSupportedError',
97     message: 'It cannot resume'
98   },
99   'DOWNLOAD_ERROR_IO_ERROR': {
100     code: tizen.WebAPIException.INVALID_ACCESS_ERR,
101     name: 'InvalidAccessError',
102     message: 'Internal I/O error'
103   },
104   'DOWNLOAD_ERROR_OUT_OF_MEMORY': {
105     code: tizen.WebAPIException.QUOTA_EXCEEDED_ERR,
106     name: 'QuotaExceededError',
107     message: 'Out of memory'
108   },
109   'DOWNLOAD_ERROR_NO_SPACE': {
110     code: tizen.WebAPIException.QUOTA_EXCEEDED_ERR,
111     name: 'QuotaExceededError',
112     message: 'No space left on device'
113   },
114   'DOWNLOAD_ERROR_NETWORK_UNREACHABLE': {
115     code: tizen.WebAPIException.NETWORK_ERR,
116     name: 'NetworkError',
117     message: 'Network is unreachable'
118   },
119   'DOWNLOAD_ERROR_CONNECTION_TIMED_OUT': {
120     code: tizen.WebAPIException.NETWORK_ERR,
121     name: 'NetworkError',
122     message: 'HTTP session timeout'
123   },
124   'DOWNLOAD_ERROR_CONNECTION_FAILED': {
125     code: tizen.WebAPIException.NETWORK_ERR,
126     name: 'NetworkError',
127     message: 'Connection failed'
128   },
129   'DOWNLOAD_ERROR_REQUEST_TIMEOUT': {
130     code: tizen.WebAPIException.NETWORK_ERR,
131     name: 'NetworkError',
132     message: 'There are no action after client create a download id'
133   },
134   'DOWNLOAD_ERROR_RESPONSE_TIMEOUT': {
135     code: tizen.WebAPIException.NETWORK_ERR,
136     name: 'NetworkError',
137     message: 'It does not call start API in some time although the download is created'
138   },
139   'DOWNLOAD_ERROR_TOO_MANY_REDIRECTS': {
140     code: tizen.WebAPIException.NETWORK_ERR,
141     name: 'NetworkError',
142     message: 'In case of too may redirects from http response header'
143   },
144   'DOWNLOAD_ERROR_UNHANDLED_HTTP_CODE': {
145     code: tizen.WebAPIException.NETWORK_ERR,
146     name: 'NetworkError',
147     message: 'The download cannot handle the HTTP status value'
148   },
149   'DOWNLOAD_ERROR_SYSTEM_DOWN': {
150     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
151     name: 'NotSupportedError',
152     message: 'There are no response from client after rebooting download daemon'
153   },
154   'DOWNLOAD_ERROR_NO_DATA': {
155     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
156     name: 'NotSupportedError',
157     message: 'No data because the set API is not called'
158   },
159   'DOWNLOAD_ERROR_ID_NOT_FOUND': {
160     code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
161     name: 'NotSupportedError',
162     message: 'The download id is not existed in download service module'
163   }
164 };
165
166 var AllowDownloadOnNetworkType = {
167   'ALL': 0,
168   'CELLULAR': 1,
169   'WIFI': 2
170 };
171
172 extension.setMessageListener(function(msg) {
173   var m = JSON.parse(msg);
174   var id = parseInt(m.uid);
175   if (isNaN(id) || typeof startListeners[id] === 'undefined') {
176     return;
177   } else if (m.cmd == 'DownloadReplyProgress') {
178     if (typeof startListeners[id].onprogress !== 'undefined') {
179       var receivedSize = parseInt(m.receivedSize);
180       var totalSize = parseInt(m.totalSize);
181       startListeners[id].onprogress(id, receivedSize, totalSize);
182     }
183   } else if (m.cmd == 'DownloadReplyComplete') {
184     if (typeof startListeners[id].oncompleted !== 'undefined') {
185       startListeners[id].oncompleted(id, m.fullPath);
186     }
187   } else if (m.cmd == 'DownloadReplyPause') {
188     if (typeof startListeners[id].onpaused !== 'undefined') {
189       startListeners[id].onpaused(id);
190     }
191   } else if (m.cmd == 'DownloadReplyCancel') {
192     if (typeof startListeners[id].oncanceled !== 'undefined') {
193       startListeners[id].oncanceled(id);
194     }
195   } else if (m.cmd == 'DownloadReplyNetworkType') {
196     networkTypeCallbacks[id](m.networkType);
197   } else if (m.cmd == 'DownloadReplyMIMEType') {
198     mimeTypeCallbacks[id](m.mimeType);
199   } else if (m.cmd == 'DownloadReplyFail') {
200     startListeners[id].onfailed(id,
201         new tizen.WebAPIError(errorMap[m.errorCode].code,
202                               errorMap[m.errorCode].message,
203                               errorMap[m.errorCode].name));
204   }
205 });
206
207 tizen.DownloadRequest = function(url, destination, fileName, networkType) {
208   Object.defineProperty(this, 'networkType', {
209     get: function() { return this.networkTypeValue; },
210     set: function(type) {
211       if (type === null || type in AllowDownloadOnNetworkType) {
212         this.networkTypeValue = type;
213       }
214     }
215   });
216
217   var url_;
218   Object.defineProperty(this, 'url', {
219     get: function() { return this.url_; },
220     set: function(value) {
221       if (value != null) {
222         this.url_ = value;
223       }
224     }
225   });
226   this.url_ = url;
227
228   if (!(this instanceof tizen.DownloadRequest)) {
229     throw new TypeError;
230   }
231   this.uid = ++currentUID;
232   this.destination = asValidString(destination);
233   this.fileName = asValidString(fileName);
234   this.networkType = getNetworkTypeThrowsError(networkType);
235   this.httpHeader = {};
236 };
237
238 exports.start = function(request, listener) {
239   if (!(request instanceof tizen.DownloadRequest)) {
240     throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
241   }
242   requests[request.uid] = request;
243   // If listener is equal to 'undefined', 'listener !== null' is still true.
244   // So change condition 'listener !== null' to 'listener != null'.
245   if (listener != null) {
246     ensureType(listener, 'object');
247     exports.setListener(request.uid, listener);
248   }
249   postMessage({
250     'cmd': 'DownloadStart',
251     'url': request.url,
252     'uid': request.uid,
253     'destination': request.destination,
254     'fileName': request.fileName,
255     'networkType': request.networkType,
256     'httpHeader': request.httpHeader
257   });
258   return request.uid;
259 };
260
261 exports.setListener = function(downloadId, listener) {
262   ensureType(downloadId, 'number');
263   ensureType(listener, 'object');
264   if (listener === null) { // null is also an object, so we need double check
265     throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
266   }
267   for (var property in listener) {
268     ensureType(listener[property], 'function');
269   }
270   ensureHas(requests[downloadId]);
271   startListeners[downloadId] = listener;
272 };
273
274 exports.pause = function(downloadId) {
275   ensureType(downloadId, 'number');
276   ensureHas(requests[downloadId]);
277   postMessage({
278     'cmd': 'DownloadPause',
279     'uid': downloadId
280   });
281 };
282
283 exports.resume = function(downloadId) {
284   ensureType(downloadId, 'number');
285   ensureHas(requests[downloadId]);
286   postMessage({
287     'cmd': 'DownloadResume',
288     'uid': downloadId
289   });
290 };
291
292 exports.cancel = function(downloadId) {
293   ensureType(downloadId, 'number');
294   ensureHas(requests[downloadId]);
295   postMessage({
296     'cmd': 'DownloadCancel',
297     'uid': downloadId
298   });
299 };
300
301 exports.getDownloadRequest = function(downloadId) {
302   ensureType(downloadId, 'number');
303   ensureHas(requests[downloadId]);
304   return requests[downloadId];
305 };
306
307 exports.getNetworkType = function(downloadId, callback) {
308   ensureType(downloadId, 'number');
309   ensureType(callback, 'function');
310   ensureHas(requests[downloadId]);
311   networkTypeCallbacks[downloadId] = callback;
312   postMessage({
313     'cmd': 'DownloadGetNetworkType',
314     'uid': downloadId
315   });
316 };
317
318 exports.getMIMEType = function(downloadId) {
319   ensureType(downloadId, 'number');
320   ensureHas(requests[downloadId]);
321   var reply = JSON.parse(_sendSyncMessage({
322     'cmd': 'DownloadGetMIMEType',
323     'uid': downloadId
324   }));
325   if (reply['error'] != 'DOWNLOAD_ERROR_NONE') {
326     switch (reply['error']) {
327       case 'DOWNLOAD_ERROR_INVALID_PARAMETER':
328         throw new tizen.WebAPIException(tizen.WebAPIException.SYNTAX_ERR);
329         break;
330       case 'DOWNLOAD_ERROR_ID_NOT_FOUND':
331         throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
332         break;
333       default:
334         throw new tizen.WebAPIException(tizen.WebAPIException.NOT_SUPPORTED_ERR);
335     }
336   } else {
337     delete reply['error'];
338     return reply['mimeType'];
339   }
340 };
341
342 exports.getState = function(downloadId) {
343   ensureType(downloadId, 'number');
344   ensureHas(requests[downloadId]);
345   var reply = JSON.parse(_sendSyncMessage({
346     'cmd': 'DownloadGetState',
347     'uid': downloadId
348   }));
349   if (reply['error'] != 'DOWNLOAD_ERROR_NONE') {
350     switch (reply['error']) {
351       case 'DOWNLOAD_ERROR_INVALID_PARAMETER':
352         // TODO(hdq): Spec said to throw 'InvalidValuesError' here,
353         // but there is no such value in WebAPIException
354         throw new tizen.WebAPIException(tizen.WebAPIException.SYNTAX_ERR);
355         break;
356       case 'DOWNLOAD_ERROR_ID_NOT_FOUND':
357         throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
358         break;
359       default:
360         throw new tizen.WebAPIException(tizen.WebAPIException.NOT_SUPPORTED_ERR);
361     }
362   } else {
363     delete reply['error'];
364     return reply['state'];
365   }
366 };
367
368 var _sendSyncMessage = function(msg) {
369   return extension.internal.sendSyncMessage(JSON.stringify(msg));
370 };