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");
323 out["downloadId"] = picojson::value(static_cast<double>(download_id));
325 out["fullPath"] = picojson::value(common::FilesystemProvider::Create().GetVirtualPath(fullPath));
326 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
328 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
329 // down_cb_ptr is freed in destructor, it prevent from crash if OnFinished state
330 // was called after OnCanceled or OnFailed
336 gboolean DownloadInstance::OnPaused(void* user_data) {
338 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
339 std::lock_guard<std::mutex> lock(instances_mutex_);
340 if (!CheckInstance(down_cb_ptr->instance)) {
344 int download_id = down_cb_ptr->download_id;
345 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[download_id];
347 LoggerW("Download handle does not exist for callback id %d", down_cb_ptr->download_id);
351 LoggerD("OnPaused for callbackID %d Called", download_id);
353 picojson::value::object out;
354 out["status"] = picojson::value("paused");
355 out["downloadId"] = picojson::value(static_cast<double>(download_id));
356 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
358 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
362 gboolean DownloadInstance::OnCanceled(void* user_data) {
364 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
365 std::lock_guard<std::mutex> lock(instances_mutex_);
366 if (!CheckInstance(down_cb_ptr->instance)) {
370 int download_id = down_cb_ptr->download_id;
371 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[download_id];
373 LoggerW("Download handle does not exist for callback id %d", download_id);
377 LoggerD("OnCanceled for callbackID %d Called", download_id);
379 int ret = download_unset_state_changed_cb(di_ptr->native_download_id);
380 if (ret != DOWNLOAD_ERROR_NONE) {
381 LoggerE("%s", get_error_message(ret));
384 ret = download_unset_progress_cb(di_ptr->native_download_id);
385 if (ret != DOWNLOAD_ERROR_NONE) {
386 LoggerE("%s", get_error_message(ret));
389 ret = download_destroy(di_ptr->native_download_id);
390 if (ret != DOWNLOAD_ERROR_NONE) {
391 LoggerE("%s", get_error_message(ret));
394 picojson::value::object out;
395 out["status"] = picojson::value("canceled");
396 out["downloadId"] = picojson::value(static_cast<double>(download_id));
397 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
399 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
400 // down_cb_ptr is freed in destructor, it prevent from crash if OnFinished state
401 // was called after OnFinished or OnFailed
405 gboolean DownloadInstance::OnFailed(void* user_data) {
407 download_error_e error;
408 picojson::object out;
410 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
411 std::lock_guard<std::mutex> lock(instances_mutex_);
412 if (!CheckInstance(down_cb_ptr->instance)) {
416 int download_id = down_cb_ptr->download_id;
417 DownloadInfoPtr di_ptr = down_cb_ptr->instance->di_map[download_id];
419 LoggerW("Download handle does not exist for callback id %d", download_id);
423 LoggerD("OnFailed for callbackID %d called", download_id);
425 download_get_error(down_cb_ptr->native_download_id, &error);
426 if (DOWNLOAD_ERROR_NONE != error) {
428 int ret = download_get_http_status(down_cb_ptr->native_download_id, &http_status);
429 std::string error_message;
430 if (DOWNLOAD_ERROR_NONE != ret) {
431 LoggerE("Gathering HTTP status failed, default error message will be used");
433 LoggerD("HTTP status is: %d", http_status);
434 error_message = "Error with HTTP status: " + std::to_string(http_status);
436 LogAndReportError(convertError(error, error_message), &out,
437 ("download_get_error error: %d (%s)", error, get_error_message(error)));
440 int ret = download_unset_state_changed_cb(di_ptr->native_download_id);
441 if (ret != DOWNLOAD_ERROR_NONE) {
442 LoggerE("%s", get_error_message(ret));
445 ret = download_unset_progress_cb(di_ptr->native_download_id);
446 if (ret != DOWNLOAD_ERROR_NONE) {
447 LoggerE("%s", get_error_message(ret));
450 ret = download_destroy(di_ptr->native_download_id);
451 if (DOWNLOAD_ERROR_NONE != ret) {
452 LoggerE("%s", get_error_message(ret));
455 out["downloadId"] = picojson::value(static_cast<double>(down_cb_ptr->download_id));
456 out["listenerId"] = picojson::value(kDownloadManagerListenerId);
458 Instance::PostMessage(down_cb_ptr->instance, picojson::value(out).serialize().c_str());
459 // down_cb_ptr is freed in destructor, it prevent from crash if OnFinished state
460 // was called after OnFinished or OnCanceled
464 void DownloadInstance::progress_changed_cb(int download_id, long long unsigned received,
467 CallbackPtr down_cb_ptr = static_cast<CallbackPtr>(user_data);
468 down_cb_ptr->received = received;
469 down_cb_ptr->native_download_id = download_id;
471 g_idle_add(OnProgressChanged, down_cb_ptr);
474 void DownloadInstance::DownloadManagerStart(const picojson::value& args, picojson::object& out) {
476 CHECK_PRIVILEGE_ACCESS(kPrivilegeDownload, &out);
477 CHECK_EXIST(args, "downloadId", out)
478 CHECK_EXIST(args, "url", out)
481 std::string networkType;
483 DownloadInfoPtr di_ptr(new DownloadInfo);
485 di_ptr->download_id = static_cast<int>(args.get("downloadId").get<double>());
486 di_ptr->url = args.get("url").is<std::string>() ? args.get("url").get<std::string>() : "";
488 if (!args.get("destination").is<picojson::null>()) {
489 if (args.get("destination").is<std::string>() &&
490 args.get("destination").get<std::string>() != "") {
491 di_ptr->destination = args.get("destination").get<std::string>();
492 di_ptr->destination = common::FilesystemProvider::Create().GetRealPath(di_ptr->destination);
496 if (!args.get("fileName").is<picojson::null>()) {
497 if (args.get("fileName").is<std::string>() && args.get("fileName").get<std::string>() != "") {
498 di_ptr->file_name = args.get("fileName").get<std::string>();
502 if (!args.get("networkType").is<picojson::null>()) {
503 networkType = args.get("networkType").is<std::string>()
504 ? args.get("networkType").get<std::string>()
508 bool network_support = false;
509 bool cell_support = false;
510 bool wifi_support = false;
512 system_info_get_platform_bool("http://tizen.org/feature/network.telephony", &cell_support);
513 system_info_get_platform_bool("http://tizen.org/feature/network.wifi", &wifi_support);
515 connection_h connection = nullptr;
516 connection_create(&connection);
518 connection_destroy(connection);
521 connection_cellular_state_e cell_state = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE;
522 connection_wifi_state_e wifi_state = CONNECTION_WIFI_STATE_DEACTIVATED;
524 connection_get_cellular_state(connection, &cell_state);
525 connection_get_wifi_state(connection, &wifi_state);
527 connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
528 connection_get_type(connection, &connection_type);
530 if (CONNECTION_TYPE_DISCONNECTED == connection_type) {
532 common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Connection problem occured"), &out,
533 ("Connection type is disconnected"));
537 bool network_available = false;
538 bool cell_available = (CONNECTION_CELLULAR_STATE_CONNECTED == cell_state);
539 bool wifi_available = (CONNECTION_WIFI_STATE_CONNECTED == wifi_state);
541 if ("CELLULAR" == networkType) {
542 network_support = cell_support;
543 network_available = cell_available;
544 di_ptr->network_type = DOWNLOAD_NETWORK_DATA_NETWORK;
545 } else if ("WIFI" == networkType) {
546 network_support = wifi_support;
547 network_available = wifi_available;
548 di_ptr->network_type = DOWNLOAD_NETWORK_WIFI;
549 } else if (("ALL" == networkType) && (CONNECTION_TYPE_DISCONNECTED != connection_type)) {
550 network_support = true;
551 network_available = true;
552 di_ptr->network_type = DOWNLOAD_NETWORK_ALL;
555 common::PlatformResult(common::ErrorCode::INVALID_VALUES_ERR,
556 "The input parameter contains an invalid network type."),
557 &out, ("The input parameter contains an invalid network type: %s", networkType.c_str()));
562 * There is no relevant feature for networkType == "ALL".
564 if (!network_support && ("ALL" != networkType)) {
565 LogAndReportError(common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
566 "The networkType of the given DownloadRequest "
567 "is not supported on this device."),
568 &out, ("Requested network type (%s) is not supported.", networkType.c_str()));
572 if (!network_available) {
573 LogAndReportError(common::PlatformResult(common::ErrorCode::NETWORK_ERR,
574 "The networkType of the given DownloadRequest "
575 "is currently not available on this device."),
576 &out, ("Requested network type (%s) is not available.", networkType.c_str()));
580 CallbackPtr down_cb_ptr(new DownloadCallback);
582 down_cb_ptr->download_id = di_ptr->download_id;
583 down_cb_ptr->instance = this;
585 download_callbacks[down_cb_ptr->download_id] = down_cb_ptr;
587 ret = download_create(&di_ptr->native_download_id);
588 if (ret != DOWNLOAD_ERROR_NONE) {
589 LogAndReportError(convertError(ret), &out,
590 ("download_create error: %d (%s)", ret, get_error_message(ret)));
594 ret = download_set_state_changed_cb(di_ptr->native_download_id, OnStateChanged,
595 static_cast<void*>(down_cb_ptr));
596 if (ret != DOWNLOAD_ERROR_NONE) {
597 LogAndReportError(convertError(ret), &out, ("download_set_state_changed_cb error: %d (%s)", ret,
598 get_error_message(ret)));
602 ret = download_set_progress_cb(di_ptr->native_download_id, progress_changed_cb,
603 static_cast<void*>(down_cb_ptr));
604 if (ret != DOWNLOAD_ERROR_NONE) {
605 LogAndReportError(convertError(ret), &out,
606 ("download_set_progress_cb error: %d (%s)", ret, get_error_message(ret)));
610 ret = download_set_url(di_ptr->native_download_id, di_ptr->url.c_str());
611 if (ret != DOWNLOAD_ERROR_NONE) {
612 LogAndReportError(convertError(ret), &out,
613 ("download_set_url error: %d (%s)", ret, get_error_message(ret)));
617 if (di_ptr->destination.size() != 0) {
618 ret = download_set_destination(di_ptr->native_download_id, di_ptr->destination.c_str());
619 if (ret != DOWNLOAD_ERROR_NONE) {
620 LogAndReportError(convertError(ret), &out,
621 ("download_set_destination error: %d (%s)", ret, get_error_message(ret)));
626 if (!di_ptr->file_name.empty()) {
627 ret = download_set_file_name(di_ptr->native_download_id, di_ptr->file_name.c_str());
628 if (ret != DOWNLOAD_ERROR_NONE) {
629 LogAndReportError(convertError(ret), &out,
630 ("download_set_file_name error: %d (%s)", ret, get_error_message(ret)));
635 ret = download_set_network_type(di_ptr->native_download_id, di_ptr->network_type);
637 if (args.get("httpHeader").is<picojson::object>()) {
638 picojson::object obj = args.get("httpHeader").get<picojson::object>();
639 for (picojson::object::const_iterator it = obj.begin(); it != obj.end(); ++it) {
640 download_add_http_header_field(di_ptr->native_download_id, it->first.c_str(),
641 it->second.to_str().c_str());
645 di_map[down_cb_ptr->download_id] = di_ptr;
647 ret = download_start(di_ptr->native_download_id);
649 if (ret == DOWNLOAD_ERROR_NONE) {
652 LogAndReportError(convertError(ret), &out,
653 ("download_start error: %d (%s)", ret, get_error_message(ret)));
657 void DownloadInstance::DownloadManagerCancel(const picojson::value& args, picojson::object& out) {
659 CHECK_EXIST(args, "downloadId", out)
662 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
664 if (!GetDownloadID(callbackId, downloadId)) {
666 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
667 "The identifier does not match any download operation in progress"),
668 &out, ("The identifier %d does not match any download operation in progress", downloadId));
672 ret = download_cancel(downloadId);
674 if (ret == DOWNLOAD_ERROR_NONE) {
677 LogAndReportError(convertError(ret), &out,
678 ("download_cancel error: %d (%s)", ret, get_error_message(ret)));
682 void DownloadInstance::DownloadManagerPause(const picojson::value& args, picojson::object& out) {
684 CHECK_EXIST(args, "downloadId", out)
687 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
689 if (!GetDownloadID(callbackId, downloadId)) {
691 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
692 "The identifier does not match any download operation in progress"),
693 &out, ("The identifier %d does not match any download operation in progress", downloadId));
697 ret = download_pause(downloadId);
699 if (ret == DOWNLOAD_ERROR_NONE) {
702 LogAndReportError(convertError(ret), &out,
703 ("download_pause error: %d (%s)", ret, get_error_message(ret)));
707 void DownloadInstance::DownloadManagerResume(const picojson::value& args, picojson::object& out) {
709 CHECK_EXIST(args, "downloadId", out)
712 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
714 if (!GetDownloadID(callbackId, downloadId)) {
716 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
717 "The identifier does not match any download operation in progress"),
718 &out, ("The identifier %d does not match any download operation in progress", downloadId));
722 ret = download_start(downloadId);
724 if (ret == DOWNLOAD_ERROR_NONE) {
727 LogAndReportError(convertError(ret), &out,
728 ("download_start error: %d (%s)", ret, get_error_message(ret)));
732 void DownloadInstance::DownloadManagerGetstate(const picojson::value& args, picojson::object& out) {
734 CHECK_EXIST(args, "downloadId", out)
736 std::string stateValue;
737 download_state_e state;
739 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
741 if (!GetDownloadID(callbackId, downloadId)) {
743 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
744 "The identifier does not match any download operation in progress"),
745 &out, ("The identifier %d does not match any download operation in progress", downloadId));
749 ret = download_get_state(downloadId, &state);
751 if (ret == DOWNLOAD_ERROR_NONE) {
753 case DOWNLOAD_STATE_NONE:
755 case DOWNLOAD_STATE_QUEUED:
756 stateValue = "QUEUED";
758 case DOWNLOAD_STATE_DOWNLOADING:
759 stateValue = "DOWNLOADING";
761 case DOWNLOAD_STATE_PAUSED:
762 stateValue = "PAUSED";
764 case DOWNLOAD_STATE_COMPLETED:
765 stateValue = "COMPLETED";
767 case DOWNLOAD_STATE_FAILED:
768 stateValue = "FAILED";
770 case DOWNLOAD_STATE_CANCELED:
771 stateValue = "CANCELED";
774 LoggerD("Unexpected download state: %d", state);
778 ReportSuccess(picojson::value(stateValue), out);
780 LogAndReportError(convertError(ret), &out,
781 ("download_get_state error: %d (%s)", ret, get_error_message(ret)));
785 void DownloadInstance::DownloadManagerGetmimetype(const picojson::value& args,
786 picojson::object& out) {
788 CHECK_EXIST(args, "downloadId", out)
791 char* mimetype = NULL;
793 int callbackId = static_cast<int>(args.get("downloadId").get<double>());
795 if (!GetDownloadID(callbackId, downloadId)) {
797 common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
798 "The identifier does not match any download operation in progress"),
799 &out, ("The identifier %d does not match any download operation in progress", downloadId));
803 ret = download_get_mime_type(downloadId, &mimetype);
805 if (ret == DOWNLOAD_ERROR_NONE) {
806 ReportSuccess(picojson::value(mimetype), out);
808 LogAndReportError(convertError(ret), &out,
809 ("download_get_mime_type error: %d (%s)", ret, get_error_message(ret)));
814 bool DownloadInstance::GetDownloadID(const int download_id, int& native_download_id) {
816 if (di_map.find(download_id) != di_map.end()) {
817 native_download_id = di_map.find(download_id)->second->native_download_id;
826 } // namespace download
827 } // namespace extension