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.
8 var startListeners = [];
9 var networkTypeCallbacks = [];
10 var mimeTypeCallbacks = [];
11 var httpHeaderCallbacks = [];
13 var postMessage = function(msg) {
14 extension.postMessage(JSON.stringify(msg));
17 var asValidString = function(o) {
18 return (typeof o == 'string') ? o : '';
21 var ensureType = function(o, expected) {
22 if (typeof o != expected) {
23 throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
27 var ensureHas = function(o) {
28 if (typeof o == 'undefined') {
29 throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
33 var getNetworkTypeThrowsError = function(networkType) {
34 if (typeof networkType == 'undefined') {
36 } else if (networkType in AllowDownloadOnNetworkType) {
39 throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
44 'DOWNLOAD_ERROR_NONE': {
45 code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
46 name: 'NotSupportedError',
47 message: 'Download successful'
49 'DOWNLOAD_UNKNOWN_ERROR': {
50 code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
51 name: 'NotSupportedError',
52 message: 'Unknown error'
54 'DOWNLOAD_ERROR_INVALID_PARAMETER': {
55 code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
56 name: 'NotSupportedError',
57 message: 'Invalid parameter'
59 'DOWNLOAD_ERROR_FIELD_NOT_FOUND': {
60 code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
61 name: 'NotSupportedError',
62 message: 'Specified field not found'
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'
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'
74 'DOWNLOAD_ERROR_INVALID_URL': {
75 code: tizen.WebAPIException.SYNTAX_ERR,
77 message: 'Invalid URL'
79 'DOWNLOAD_ERROR_INVALID_DESTINATION': {
80 code: tizen.WebAPIException.SYNTAX_ERR,
82 message: 'Invalid destination'
84 'DOWNLOAD_ERROR_INVALID_STATE': {
85 code: tizen.WebAPIException.INVALID_STATE_ERR,
86 name: 'InvalidStateError',
87 message: 'Invalid state'
89 'DOWNLOAD_ERROR_ALREADY_COMPLETED': {
90 code: tizen.WebAPIException.INVALID_STATE_ERR,
91 name: 'InvalidStateError',
92 message: 'The download is already completed'
94 'DOWNLOAD_ERROR_CANNOT_RESUME': {
95 code: tizen.WebAPIException.NOT_SUPPORTED_ERR,
96 name: 'NotSupportedError',
97 message: 'It cannot resume'
99 'DOWNLOAD_ERROR_IO_ERROR': {
100 code: tizen.WebAPIException.INVALID_ACCESS_ERR,
101 name: 'InvalidAccessError',
102 message: 'Internal I/O error'
104 'DOWNLOAD_ERROR_OUT_OF_MEMORY': {
105 code: tizen.WebAPIException.QUOTA_EXCEEDED_ERR,
106 name: 'QuotaExceededError',
107 message: 'Out of memory'
109 'DOWNLOAD_ERROR_NO_SPACE': {
110 code: tizen.WebAPIException.QUOTA_EXCEEDED_ERR,
111 name: 'QuotaExceededError',
112 message: 'No space left on device'
114 'DOWNLOAD_ERROR_NETWORK_UNREACHABLE': {
115 code: tizen.WebAPIException.NETWORK_ERR,
116 name: 'NetworkError',
117 message: 'Network is unreachable'
119 'DOWNLOAD_ERROR_CONNECTION_TIMED_OUT': {
120 code: tizen.WebAPIException.NETWORK_ERR,
121 name: 'NetworkError',
122 message: 'HTTP session timeout'
124 'DOWNLOAD_ERROR_CONNECTION_FAILED': {
125 code: tizen.WebAPIException.NETWORK_ERR,
126 name: 'NetworkError',
127 message: 'Connection failed'
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'
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'
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'
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'
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'
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'
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'
166 var AllowDownloadOnNetworkType = {
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') {
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);
183 } else if (m.cmd == 'DownloadReplyComplete') {
184 if (typeof startListeners[id].oncompleted !== 'undefined') {
185 startListeners[id].oncompleted(id, m.fullPath);
187 } else if (m.cmd == 'DownloadReplyPause') {
188 if (typeof startListeners[id].onpaused !== 'undefined') {
189 startListeners[id].onpaused(id);
191 } else if (m.cmd == 'DownloadReplyCancel') {
192 if (typeof startListeners[id].oncanceled !== 'undefined') {
193 startListeners[id].oncanceled(id);
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));
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;
218 Object.defineProperty(this, 'url', {
219 get: function() { return this.url_; },
220 set: function(value) {
228 if (!(this instanceof tizen.DownloadRequest)) {
231 this.uid = ++currentUID;
232 this.destination = asValidString(destination);
233 this.fileName = asValidString(fileName);
234 this.networkType = getNetworkTypeThrowsError(networkType);
235 this.httpHeader = {};
238 exports.start = function(request, listener) {
239 if (!(request instanceof tizen.DownloadRequest)) {
240 throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
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);
250 'cmd': 'DownloadStart',
253 'destination': request.destination,
254 'fileName': request.fileName,
255 'networkType': request.networkType,
256 'httpHeader': request.httpHeader
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);
267 for (var property in listener) {
268 ensureType(listener[property], 'function');
270 ensureHas(requests[downloadId]);
271 startListeners[downloadId] = listener;
274 exports.pause = function(downloadId) {
275 ensureType(downloadId, 'number');
276 ensureHas(requests[downloadId]);
278 'cmd': 'DownloadPause',
283 exports.resume = function(downloadId) {
284 ensureType(downloadId, 'number');
285 ensureHas(requests[downloadId]);
287 'cmd': 'DownloadResume',
292 exports.cancel = function(downloadId) {
293 ensureType(downloadId, 'number');
294 ensureHas(requests[downloadId]);
296 'cmd': 'DownloadCancel',
301 exports.getDownloadRequest = function(downloadId) {
302 ensureType(downloadId, 'number');
303 ensureHas(requests[downloadId]);
304 return requests[downloadId];
307 exports.getNetworkType = function(downloadId, callback) {
308 ensureType(downloadId, 'number');
309 ensureType(callback, 'function');
310 ensureHas(requests[downloadId]);
311 networkTypeCallbacks[downloadId] = callback;
313 'cmd': 'DownloadGetNetworkType',
318 exports.getMIMEType = function(downloadId) {
319 ensureType(downloadId, 'number');
320 ensureHas(requests[downloadId]);
321 var reply = JSON.parse(_sendSyncMessage({
322 'cmd': 'DownloadGetMIMEType',
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);
330 case 'DOWNLOAD_ERROR_ID_NOT_FOUND':
331 throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
334 throw new tizen.WebAPIException(tizen.WebAPIException.NOT_SUPPORTED_ERR);
337 delete reply['error'];
338 return reply['mimeType'];
342 exports.getState = function(downloadId) {
343 ensureType(downloadId, 'number');
344 ensureHas(requests[downloadId]);
345 var reply = JSON.parse(_sendSyncMessage({
346 'cmd': 'DownloadGetState',
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);
356 case 'DOWNLOAD_ERROR_ID_NOT_FOUND':
357 throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
360 throw new tizen.WebAPIException(tizen.WebAPIException.NOT_SUPPORTED_ERR);
363 delete reply['error'];
364 return reply['state'];
368 var _sendSyncMessage = function(msg) {
369 return extension.internal.sendSyncMessage(JSON.stringify(msg));