2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "download/download_instance.h"
21 #include <net_connection.h>
23 #include "common/filesystem/filesystem_provider.h"
24 #include "common/logger.h"
25 #include "common/picojson.h"
26 #include "common/scope_exit.h"
27 #include "common/tools.h"
28 #include "common/typeutil.h"
33 std::vector<DownloadInstance*> DownloadInstance::instances_;
34 std::mutex DownloadInstance::instances_mutex_;
37 // The privileges that required in Download API
38 const std::string kPrivilegeDownload = "http://tizen.org/privilege/download";
39 const std::string kDownloadManagerListenerId = "DownloadManagerListener";
43 DownloadInstance::DownloadInstance() {
45 using std::placeholders::_1;
46 using std::placeholders::_2;
47 #define REGISTER_SYNC(c, x) RegisterSyncHandler(c, std::bind(&DownloadInstance::x, this, _1, _2));
48 REGISTER_SYNC("DownloadManager_pause", DownloadManagerPause);
49 REGISTER_SYNC("DownloadManager_getMIMEType", DownloadManagerGetmimetype);
50 REGISTER_SYNC("DownloadManager_start", DownloadManagerStart);
51 REGISTER_SYNC("DownloadManager_cancel", DownloadManagerCancel);
52 REGISTER_SYNC("DownloadManager_resume", DownloadManagerResume);
53 REGISTER_SYNC("DownloadManager_getState", DownloadManagerGetstate);
56 std::lock_guard<std::mutex> lock(instances_mutex_);
57 instances_.push_back(this);
60 DownloadInstance::~DownloadInstance() {
64 std::lock_guard<std::mutex> lock(instances_mutex_);
66 for (DownloadCallbackMap::iterator it = download_callbacks.begin();
67 it != download_callbacks.end(); ++it) {
68 DownloadInfoPtr di_ptr = it->second->instance->di_map[it->second->download_id];
69 SLoggerD("~DownloadInstance() for callbackID %d Called", it->second->download_id);
72 ret = download_unset_state_changed_cb(di_ptr->native_download_id);
73 if (ret != DOWNLOAD_ERROR_NONE)
74 LoggerE("download_unset_state_changed_cb() is failed. (%s)", get_error_message(ret));
76 ret = download_unset_progress_cb(di_ptr->native_download_id);
77 if (ret != DOWNLOAD_ERROR_NONE)
78 LoggerE("download_unset_progress_cb() is failed. (%s)", get_error_message(ret));
80 ret = download_cancel(di_ptr->native_download_id);
81 if (ret != DOWNLOAD_ERROR_NONE)
82 LoggerE("download_cancel() is failed. (%s)", get_error_message(ret));
84 ret = download_destroy(di_ptr->native_download_id);
85 if (ret != DOWNLOAD_ERROR_NONE)
86 LoggerE("download_destroy() is failed. (%s)", get_error_message(ret));
88 LoggerD("di_ptr is nullptr");
94 for (auto it = instances_.begin(); it != instances_.end(); it++) {
102 bool DownloadInstance::CheckInstance(DownloadInstance* instance) {
104 for (auto vec_instance : instances_) {
105 if (vec_instance == instance) {
113 common::PlatformResult DownloadInstance::convertError(int err, const std::string& message) {
114 char* error = nullptr;
115 if (message.empty()) {
116 error = get_error_message(err);
118 error = (char*)message.c_str();
122 case DOWNLOAD_ERROR_INVALID_PARAMETER:
123 return common::PlatformResult(common::ErrorCode::INVALID_VALUES_ERR, error);
124 case DOWNLOAD_ERROR_OUT_OF_MEMORY:
125 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
126 case DOWNLOAD_ERROR_NETWORK_UNREACHABLE:
127 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
128 case DOWNLOAD_ERROR_CONNECTION_TIMED_OUT:
129 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
130 case DOWNLOAD_ERROR_NO_SPACE:
131 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
132 case DOWNLOAD_ERROR_PERMISSION_DENIED:
133 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
134 case DOWNLOAD_ERROR_NOT_SUPPORTED:
135 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
136 case DOWNLOAD_ERROR_INVALID_STATE:
137 return common::PlatformResult(common::ErrorCode::INVALID_VALUES_ERR, error);
138 case DOWNLOAD_ERROR_CONNECTION_FAILED:
139 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
140 case DOWNLOAD_ERROR_INVALID_URL:
141 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
142 case DOWNLOAD_ERROR_INVALID_DESTINATION:
143 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
144 case DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS:
145 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
146 case DOWNLOAD_ERROR_QUEUE_FULL:
147 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
148 case DOWNLOAD_ERROR_ALREADY_COMPLETED:
149 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
150 case DOWNLOAD_ERROR_FILE_ALREADY_EXISTS:
151 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
152 case DOWNLOAD_ERROR_CANNOT_RESUME:
153 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
154 case DOWNLOAD_ERROR_FIELD_NOT_FOUND:
155 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
156 case DOWNLOAD_ERROR_TOO_MANY_REDIRECTS:
157 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
158 case DOWNLOAD_ERROR_UNHANDLED_HTTP_CODE:
159 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
160 case DOWNLOAD_ERROR_REQUEST_TIMEOUT:
161 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
162 case DOWNLOAD_ERROR_RESPONSE_TIMEOUT:
163 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
164 case DOWNLOAD_ERROR_SYSTEM_DOWN:
165 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
166 case DOWNLOAD_ERROR_ID_NOT_FOUND:
167 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
168 case DOWNLOAD_ERROR_INVALID_NETWORK_TYPE:
169 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
170 case DOWNLOAD_ERROR_NO_DATA:
171 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
172 case DOWNLOAD_ERROR_IO_ERROR:
173 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, error);
175 return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Unknown error.");
179 #define CHECK_EXIST(args, name, out) \
180 if (!args.contains(name)) { \
181 LogAndReportError(common::PlatformResult(common::ErrorCode::TYPE_MISMATCH_ERR, \
182 name " is required argument"), \
187 void DownloadInstance::OnStateChanged(int download_id, download_state_e state, void* user_data) {
189 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
191 // Prevent to call finished, cancelled or failed function more than once
192 if (DOWNLOAD_STATE_COMPLETED == down_cb_ptr->state ||
193 DOWNLOAD_STATE_CANCELED == down_cb_ptr->state ||
194 DOWNLOAD_STATE_FAILED == down_cb_ptr->state) {
195 LoggerD("Already finished job, not calling callback for %d state", down_cb_ptr->state);
199 down_cb_ptr->state = state;
200 down_cb_ptr->native_download_id = download_id;
202 SLoggerD("State for callbackId %d changed to %d", down_cb_ptr->download_id,
203 static_cast<int>(state));
206 case DOWNLOAD_STATE_NONE:
208 case DOWNLOAD_STATE_DOWNLOADING:
209 OnStart(download_id, user_data);
211 case DOWNLOAD_STATE_PAUSED:
212 g_idle_add(OnPaused, down_cb_ptr);
214 case DOWNLOAD_STATE_COMPLETED:
215 g_idle_add(OnFinished, down_cb_ptr);
217 case DOWNLOAD_STATE_CANCELED:
218 g_idle_add(OnCanceled, down_cb_ptr);
220 case DOWNLOAD_STATE_FAILED:
221 g_idle_add(OnFailed, down_cb_ptr);
224 LoggerD("Unexpected download state: %d", state);
229 gboolean DownloadInstance::OnProgressChanged(void* user_data) {
231 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
232 std::lock_guard<std::mutex> lock(instances_mutex_);
233 if (!CheckInstance(down_cb_ptr->instance)) {
237 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[down_cb_ptr->download_id];
239 LoggerW("Download handle does not exist for callback id %d", down_cb_ptr->download_id);
243 picojson::value::object out;
244 out["status"] = picojson::value("progress");
245 out["downloadId"] = picojson::value(static_cast<double>(down_cb_ptr->download_id));
246 out["receivedSize"] = picojson::value(static_cast<double>(down_cb_ptr->received));
247 out["totalSize"] = picojson::value(static_cast<double>(di_ptr->file_size));
248 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
250 LoggerD("OnProgressChanged for callbackId %d Called: Received: %llu", down_cb_ptr->download_id,
251 down_cb_ptr->received);
253 picojson::value v = picojson::value(out);
254 Instance::PostMessage(down_cb_ptr->instance, v.serialize().c_str());
259 void DownloadInstance::OnStart(int download_id, void* user_data) {
261 unsigned long long totalSize;
263 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
264 std::lock_guard<std::mutex> lock(instances_mutex_);
265 if (!CheckInstance(down_cb_ptr->instance)) {
269 SLoggerD("OnStart for callbackId %d Called", down_cb_ptr->download_id);
271 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[down_cb_ptr->download_id];
273 LoggerW("Download handle does not exist for callback id %d", down_cb_ptr->download_id);
277 download_get_content_size(download_id, &totalSize);
279 di_ptr->file_size = totalSize;
282 gboolean DownloadInstance::OnFinished(void* user_data) {
284 char* fullPath = NULL;
286 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
287 std::lock_guard<std::mutex> lock(instances_mutex_);
288 if (!CheckInstance(down_cb_ptr->instance)) {
292 int download_id = down_cb_ptr->download_id;
293 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[download_id];
295 LoggerW("Download handle does not exist for callback id %d", down_cb_ptr->download_id);
299 LoggerD("OnFinished for callbackID %d Called", download_id);
301 picojson::value::object out;
303 int ret = download_get_downloaded_file_path(down_cb_ptr->native_download_id, &fullPath);
304 if (ret != DOWNLOAD_ERROR_NONE) {
305 LogAndReportError(convertError(ret), &out, ("download_get_downloaded_file_path error: %d (%s)",
306 ret, get_error_message(ret)));
308 ret = download_unset_state_changed_cb(di_ptr->native_download_id);
309 if (ret != DOWNLOAD_ERROR_NONE) {
310 LoggerW("%s", get_error_message(ret));
312 ret = download_unset_progress_cb(di_ptr->native_download_id);
313 if (ret != DOWNLOAD_ERROR_NONE) {
314 LoggerW("%s", get_error_message(ret));
316 ret = download_destroy(di_ptr->native_download_id);
317 if (ret != DOWNLOAD_ERROR_NONE) {
318 LoggerW("%s", get_error_message(ret));
320 out["status"] = picojson::value("completed");
322 picojson::value(common::FilesystemProvider::Create().GetVirtualPath(fullPath));
324 out["downloadId"] = picojson::value(static_cast<double>(download_id));
326 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
327 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
328 // down_cb_ptr is freed in destructor, it prevent from crash if OnFinished state
329 // was called after OnCanceled or OnFailed
335 gboolean DownloadInstance::OnPaused(void* user_data) {
337 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
338 std::lock_guard<std::mutex> lock(instances_mutex_);
339 if (!CheckInstance(down_cb_ptr->instance)) {
343 int download_id = down_cb_ptr->download_id;
344 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[download_id];
346 LoggerW("Download handle does not exist for callback id %d", down_cb_ptr->download_id);
350 LoggerD("OnPaused for callbackID %d Called", download_id);
352 picojson::value::object out;
353 out["status"] = picojson::value("paused");
354 out["downloadId"] = picojson::value(static_cast<double>(download_id));
355 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
357 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
361 gboolean DownloadInstance::OnCanceled(void* user_data) {
363 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
364 std::lock_guard<std::mutex> lock(instances_mutex_);
365 if (!CheckInstance(down_cb_ptr->instance)) {
369 int download_id = down_cb_ptr->download_id;
370 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[download_id];
372 LoggerW("Download handle does not exist for callback id %d", download_id);
376 LoggerD("OnCanceled for callbackID %d Called", download_id);
378 int ret = download_unset_state_changed_cb(di_ptr->native_download_id);
379 if (ret != DOWNLOAD_ERROR_NONE) {
380 LoggerE("%s", get_error_message(ret));
383 ret = download_unset_progress_cb(di_ptr->native_download_id);
384 if (ret != DOWNLOAD_ERROR_NONE) {
385 LoggerE("%s", get_error_message(ret));
388 ret = download_destroy(di_ptr->native_download_id);
389 if (ret != DOWNLOAD_ERROR_NONE) {
390 LoggerE("%s", get_error_message(ret));
393 picojson::value::object out;
394 out["status"] = picojson::value("canceled");
395 out["downloadId"] = picojson::value(static_cast<double>(download_id));
396 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
398 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
399 // down_cb_ptr is freed in destructor, it prevent from crash if OnFinished state
400 // was called after OnFinished or OnFailed
404 gboolean DownloadInstance::OnFailed(void* user_data) {
406 download_error_e error;
407 picojson::object out;
409 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
410 std::lock_guard<std::mutex> lock(instances_mutex_);
411 if (!CheckInstance(down_cb_ptr->instance)) {
415 int download_id = down_cb_ptr->download_id;
416 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[download_id];
418 LoggerW("Download handle does not exist for callback id %d", download_id);
422 LoggerD("OnFailed for callbackID %d called", download_id);
424 download_get_error(down_cb_ptr->native_download_id, &error);
425 if (DOWNLOAD_ERROR_NONE != error) {
427 int ret = download_get_http_status(down_cb_ptr->native_download_id, &http_status);
428 std::string error_message;
429 if (DOWNLOAD_ERROR_NONE != ret) {
430 LoggerE("Gathering HTTP status failed, default error message will be used");
432 LoggerD("HTTP status is: %d", http_status);
433 error_message = "Error with HTTP status: " + std::to_string(http_status);
435 LogAndReportError(convertError(error, error_message), &out,
436 ("download_get_error error: %d (%s)", error, get_error_message(error)));
439 int ret = download_unset_state_changed_cb(di_ptr->native_download_id);
440 if (ret != DOWNLOAD_ERROR_NONE) {
441 LoggerE("%s", get_error_message(ret));
444 ret = download_unset_progress_cb(di_ptr->native_download_id);
445 if (ret != DOWNLOAD_ERROR_NONE) {
446 LoggerE("%s", get_error_message(ret));
449 ret = download_destroy(di_ptr->native_download_id);
450 if (DOWNLOAD_ERROR_NONE != ret) {
451 LoggerE("%s", get_error_message(ret));
454 out["downloadId"] = picojson::value(static_cast<double>(down_cb_ptr->download_id));
455 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
457 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
458 // down_cb_ptr is freed in destructor, it prevent from crash if OnFinished state
459 // was called after OnFinished or OnCanceled
463 void DownloadInstance::progress_changed_cb(int download_id, long long unsigned received,
466 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
467 down_cb_ptr->received = received;
468 down_cb_ptr->native_download_id = download_id;
470 g_idle_add(OnProgressChanged, down_cb_ptr);
473 #define CHECK_CONNECTION_ERROR(ret) \
475 case CONNECTION_ERROR_NONE: \
477 case CONNECTION_ERROR_NOT_SUPPORTED: \
478 return LogAndCreateResult( \
479 common::ErrorCode::NOT_SUPPORTED_ERR, \
480 "The networkType of the given DownloadRequest is not supported", \
481 ("The networkType of the given DownloadRequest is not supported")); \
483 return LogAndCreateResult(common::ErrorCode::UNKNOWN_ERR, "Connection problem occurred", \
484 ("Connection problem occurred")); \
487 common::PlatformResult DownloadInstance::CheckNetworkConnection(const std::string& network_type,
488 bool& network_support,
489 bool& network_available,
490 DownloadInfoPtr di_ptr) {
491 ScopeLogger("network_type: %s", network_type.c_str());
493 connection_h connection = nullptr;
494 int ret = connection_create(&connection);
495 CHECK_CONNECTION_ERROR(ret)
497 connection_destroy(connection);
500 connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
501 ret = connection_get_type(connection, &connection_type);
502 CHECK_CONNECTION_ERROR(ret)
504 if ("CELLULAR" == network_type) {
505 // check if connection type is supported
506 bool cell_support = false;
507 system_info_get_platform_bool("http://tizen.org/feature/network.telephony", &cell_support);
509 // check if connection is available
510 connection_cellular_state_e cell_state = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE;
511 ret = connection_get_cellular_state(connection, &cell_state);
512 CHECK_CONNECTION_ERROR(ret)
513 bool cell_available = (CONNECTION_CELLULAR_STATE_CONNECTED == cell_state);
515 // setup download parameters using cellular network
516 network_support = cell_support;
517 network_available = cell_available;
518 di_ptr->network_type = DOWNLOAD_NETWORK_DATA_NETWORK;
519 } else if ("WIFI" == network_type) {
520 // check if connection type is supported
521 bool wifi_support = false;
522 system_info_get_platform_bool("http://tizen.org/feature/network.wifi", &wifi_support);
524 // check if connection is available
525 connection_wifi_state_e wifi_state = CONNECTION_WIFI_STATE_DEACTIVATED;
526 ret = connection_get_wifi_state(connection, &wifi_state);
527 CHECK_CONNECTION_ERROR(ret)
528 bool wifi_available = (CONNECTION_WIFI_STATE_CONNECTED == wifi_state);
530 // setup download parameters using wifi network
531 network_support = wifi_support;
532 network_available = wifi_available;
533 di_ptr->network_type = DOWNLOAD_NETWORK_WIFI;
534 } else if (("ALL" == network_type) && (CONNECTION_TYPE_DISCONNECTED != connection_type)) {
535 // setup download parameters using 'all' network
536 network_support = true;
537 network_available = true;
538 di_ptr->network_type = DOWNLOAD_NETWORK_ALL;
540 return LogAndCreateResult(
541 common::ErrorCode::INVALID_VALUES_ERR,
542 "The input parameter contains an invalid network type.",
543 ("The input parameter contains an invalid network type: %s", network_type.c_str()));
545 if (CONNECTION_TYPE_DISCONNECTED == connection_type) {
546 return LogAndCreateResult(common::ErrorCode::UNKNOWN_ERR, "Connection problem occurred",
547 ("Connection type is disconnected"));
549 return common::PlatformResult(common::ErrorCode::NO_ERROR);
551 #undef CHECK_CONNECTION_ERROR
553 void DownloadInstance::DownloadManagerStart(const picojson::value& args, picojson::object& out) {
555 CHECK_PRIVILEGE_ACCESS(kPrivilegeDownload, &out);
556 CHECK_EXIST(args, "downloadId", out)
557 CHECK_EXIST(args, "url", out)
560 std::string network_type;
562 DownloadInfoPtr di_ptr(new DownloadInfo);
564 di_ptr->download_id = static_cast<int>(args.get("downloadId").get<double>());
565 di_ptr->url = args.get("url").is<std::string>() ? args.get("url").get<std::string>() : "";
567 if (!args.get("destination").is<picojson::null>()) {
568 if (args.get("destination").is<std::string>() &&
569 args.get("destination").get<std::string>() != "") {
570 di_ptr->destination = args.get("destination").get<std::string>();
571 di_ptr->destination = common::FilesystemProvider::Create().GetRealPath(di_ptr->destination);
575 CHECK_STORAGE_ACCESS(di_ptr->destination.empty()
576 ? common::FilesystemProvider::Create().GetRealPath("downloads")
577 : di_ptr->destination,
580 if (!args.get("fileName").is<picojson::null>()) {
581 if (args.get("fileName").is<std::string>() && args.get("fileName").get<std::string>() != "") {
582 di_ptr->file_name = args.get("fileName").get<std::string>();
586 if (!args.get("networkType").is<picojson::null>()) {
587 network_type = args.get("networkType").is<std::string>()
588 ? args.get("networkType").get<std::string>()
592 bool network_support = false;
593 bool network_available = false;
595 common::PlatformResult result =
596 CheckNetworkConnection(network_type, network_support, network_available, di_ptr);
598 LogAndReportError(result, &out);
603 * There is no relevant feature for network_type == "ALL".
605 if (!network_support && ("ALL" != network_type)) {
606 LogAndReportError(common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
607 "The networkType of the given DownloadRequest "
608 "is not supported on this device."),
610 ("Requested network type (%s) is not supported.", network_type.c_str()));
614 if (!network_available) {
615 LogAndReportError(common::PlatformResult(common::ErrorCode::NETWORK_ERR,
616 "The networkType of the given DownloadRequest "
617 "is currently not available on this device."),
619 ("Requested network type (%s) is not available.", network_type.c_str()));
623 CallbackPtr down_cb_ptr(new DownloadCallback);
625 down_cb_ptr->download_id = di_ptr->download_id;
626 down_cb_ptr->instance = this;
628 download_callbacks[down_cb_ptr->download_id] = down_cb_ptr;
630 ret = download_create(&di_ptr->native_download_id);
631 if (ret != DOWNLOAD_ERROR_NONE) {
632 LogAndReportError(convertError(ret), &out,
633 ("download_create error: %d (%s)", ret, get_error_message(ret)));
637 ret = download_set_state_changed_cb(di_ptr->native_download_id, OnStateChanged,
638 static_cast<void*>(down_cb_ptr));
639 if (ret != DOWNLOAD_ERROR_NONE) {
640 LogAndReportError(convertError(ret), &out, ("download_set_state_changed_cb error: %d (%s)", ret,
641 get_error_message(ret)));
645 ret = download_set_progress_cb(di_ptr->native_download_id, progress_changed_cb,
646 static_cast<void*>(down_cb_ptr));
647 if (ret != DOWNLOAD_ERROR_NONE) {
648 LogAndReportError(convertError(ret), &out,
649 ("download_set_progress_cb error: %d (%s)", ret, get_error_message(ret)));
653 ret = download_set_url(di_ptr->native_download_id, di_ptr->url.c_str());
654 if (ret != DOWNLOAD_ERROR_NONE) {
655 LogAndReportError(convertError(ret), &out,
656 ("download_set_url error: %d (%s)", ret, get_error_message(ret)));
660 if (di_ptr->destination.size() != 0) {
661 ret = download_set_destination(di_ptr->native_download_id, di_ptr->destination.c_str());
662 if (ret != DOWNLOAD_ERROR_NONE) {
663 LogAndReportError(convertError(ret), &out,
664 ("download_set_destination error: %d (%s)", ret, get_error_message(ret)));
669 if (!di_ptr->file_name.empty()) {
670 ret = download_set_file_name(di_ptr->native_download_id, di_ptr->file_name.c_str());
671 if (ret != DOWNLOAD_ERROR_NONE) {
672 LogAndReportError(convertError(ret), &out,
673 ("download_set_file_name error: %d (%s)", ret, get_error_message(ret)));
678 ret = download_set_network_type(di_ptr->native_download_id, di_ptr->network_type);
680 if (args.get("httpHeader").is<picojson::object>()) {
681 picojson::object obj = args.get("httpHeader").get<picojson::object>();
682 for (picojson::object::const_iterator it = obj.begin(); it != obj.end(); ++it) {
683 download_add_http_header_field(di_ptr->native_download_id, it->first.c_str(),
684 it->second.to_str().c_str());
688 di_map[down_cb_ptr->download_id] = di_ptr;
690 ret = download_start(di_ptr->native_download_id);
692 if (ret == DOWNLOAD_ERROR_NONE) {
695 LogAndReportError(convertError(ret), &out,
696 ("download_start error: %d (%s)", ret, get_error_message(ret)));
700 void DownloadInstance::DownloadManagerCancel(const picojson::value& args, picojson::object& out) {
702 CHECK_EXIST(args, "downloadId", out)
705 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
707 if (!GetDownloadID(callbackId, downloadId)) {
709 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
710 "The identifier does not match any download operation in progress"),
711 &out, ("The identifier %d does not match any download operation in progress", downloadId));
715 ret = download_cancel(downloadId);
717 if (ret == DOWNLOAD_ERROR_NONE) {
720 LogAndReportError(convertError(ret), &out,
721 ("download_cancel error: %d (%s)", ret, get_error_message(ret)));
725 void DownloadInstance::DownloadManagerPause(const picojson::value& args, picojson::object& out) {
727 CHECK_EXIST(args, "downloadId", out)
730 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
732 if (!GetDownloadID(callbackId, downloadId)) {
734 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
735 "The identifier does not match any download operation in progress"),
736 &out, ("The identifier %d does not match any download operation in progress", downloadId));
740 ret = download_pause(downloadId);
742 if (ret == DOWNLOAD_ERROR_NONE) {
745 LogAndReportError(convertError(ret), &out,
746 ("download_pause error: %d (%s)", ret, get_error_message(ret)));
750 void DownloadInstance::DownloadManagerResume(const picojson::value& args, picojson::object& out) {
752 CHECK_EXIST(args, "downloadId", out)
755 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
757 if (!GetDownloadID(callbackId, downloadId)) {
759 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
760 "The identifier does not match any download operation in progress"),
761 &out, ("The identifier %d does not match any download operation in progress", downloadId));
765 ret = download_start(downloadId);
767 if (ret == DOWNLOAD_ERROR_NONE) {
770 LogAndReportError(convertError(ret), &out,
771 ("download_start error: %d (%s)", ret, get_error_message(ret)));
775 void DownloadInstance::DownloadManagerGetstate(const picojson::value& args, picojson::object& out) {
777 CHECK_EXIST(args, "downloadId", out)
779 std::string stateValue;
780 download_state_e state;
782 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
784 if (!GetDownloadID(callbackId, downloadId)) {
786 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
787 "The identifier does not match any download operation in progress"),
788 &out, ("The identifier %d does not match any download operation in progress", downloadId));
792 ret = download_get_state(downloadId, &state);
794 if (ret == DOWNLOAD_ERROR_NONE) {
796 case DOWNLOAD_STATE_NONE:
798 case DOWNLOAD_STATE_QUEUED:
799 stateValue = "QUEUED";
801 case DOWNLOAD_STATE_DOWNLOADING:
802 stateValue = "DOWNLOADING";
804 case DOWNLOAD_STATE_PAUSED:
805 stateValue = "PAUSED";
807 case DOWNLOAD_STATE_COMPLETED:
808 stateValue = "COMPLETED";
810 case DOWNLOAD_STATE_FAILED:
811 stateValue = "FAILED";
813 case DOWNLOAD_STATE_CANCELED:
814 stateValue = "CANCELED";
817 LoggerD("Unexpected download state: %d", state);
821 ReportSuccess(picojson::value(stateValue), out);
823 LogAndReportError(convertError(ret), &out,
824 ("download_get_state error: %d (%s)", ret, get_error_message(ret)));
828 void DownloadInstance::DownloadManagerGetmimetype(const picojson::value& args,
829 picojson::object& out) {
831 CHECK_EXIST(args, "downloadId", out)
834 char* mimetype = NULL;
836 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
838 if (!GetDownloadID(callbackId, downloadId)) {
840 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
841 "The identifier does not match any download operation in progress"),
842 &out, ("The identifier %d does not match any download operation in progress", downloadId));
846 ret = download_get_mime_type(downloadId, &mimetype);
848 if (ret == DOWNLOAD_ERROR_NONE) {
849 ReportSuccess(picojson::value(mimetype), out);
851 LogAndReportError(convertError(ret), &out,
852 ("download_get_mime_type error: %d (%s)", ret, get_error_message(ret)));
857 bool DownloadInstance::GetDownloadID(const int download_id, int& native_download_id) {
859 if (di_map.find(download_id) != di_map.end()) {
860 native_download_id = di_map.find(download_id)->second->native_download_id;
869 } // namespace download
870 } // namespace extension