--- /dev/null
+{
+ 'includes':[
+ '../common/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'tizen_download',
+ 'type': 'loadable_module',
+ 'sources': [
+ 'download_api.js',
+ 'download_context.cc',
+ 'download_context.h',
+ 'download_context_desktop.cc',
+ 'download_context_mobile.cc',
+ ],
+ 'conditions': [
+ ['extension_host_os=="mobile"', {
+ 'variables': {
+ 'packages': [
+ 'capi-appfw-application',
+ 'capi-web-url-download',
+ ]
+ },
+ }],
+ ],
+ 'includes': [
+ '../common/pkg-config.gypi',
+ ],
+ },
+ ],
+}
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var repliedMsg;
+var currentUID = 0;
+var startListeners = [];
+
+var postMessage = function(msg) {
+ extension.postMessage(JSON.stringify(msg));
+};
+
+var errorMap = {
+ "DOWNLOAD_ERROR_NONE" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "Download successful",
+ },
+ "DOWNLOAD_UNKNOWN_ERROR" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "Unknown error",
+ },
+ "DOWNLOAD_ERROR_INVALID_PARAMETER" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "Invalid parameter",
+ },
+ "DOWNLOAD_ERROR_FIELD_NOT_FOUND" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "Specified field not found",
+ },
+ "DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "Full of available downloading items from server",
+ },
+ "DOWNLOAD_ERROR_FILE_ALREADY_EXISTS" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "It is failed to rename the downloaded file",
+ },
+ "DOWNLOAD_ERROR_INVALID_URL" : {
+ code : tizen.WebAPIException.SYNTAX_ERR,
+ name : "SyntaxError",
+ message : "Invalid URL",
+ },
+ "DOWNLOAD_ERROR_INVALID_DESTINATION" : {
+ code : tizen.WebAPIException.SYNTAX_ERR,
+ name : "SyntaxError",
+ message : "Invalid destination",
+ },
+ "DOWNLOAD_ERROR_INVALID_STATE" : {
+ code : tizen.WebAPIException.INVALID_STATE_ERR,
+ name : "InvalidStateError",
+ message : "Invalid state",
+ },
+ "DOWNLOAD_ERROR_ALREADY_COMPLETED" : {
+ code : tizen.WebAPIException.INVALID_STATE_ERR,
+ name : "InvalidStateError",
+ message : "The download is already completed",
+ },
+ "DOWNLOAD_ERROR_CANNOT_RESUME" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "It cannot resume",
+ },
+ "DOWNLOAD_ERROR_IO_ERROR" : {
+ code : tizen.WebAPIException.INVALID_ACCESS_ERR,
+ name : "InvalidAccessError",
+ message : "Internal I/O error",
+ },
+ "DOWNLOAD_ERROR_OUT_OF_MEMORY" : {
+ code : tizen.WebAPIException.QUOTA_EXCEEDED_ERR,
+ name : "QuotaExceededError",
+ message : "Out of memory",
+ },
+ "DOWNLOAD_ERROR_NO_SPACE" : {
+ code : tizen.WebAPIException.QUOTA_EXCEEDED_ERR,
+ name : "QuotaExceededError",
+ message : "No space left on device",
+ },
+ "DOWNLOAD_ERROR_NETWORK_UNREACHABLE" : {
+ code : tizen.WebAPIException.NETWORK_ERR,
+ name : "NetworkError",
+ message : "Network is unreachable",
+ },
+ "DOWNLOAD_ERROR_CONNECTION_TIMED_OUT" : {
+ code : tizen.WebAPIException.NETWORK_ERR,
+ name : "NetworkError",
+ message : "HTTP session timeout",
+ },
+ "DOWNLOAD_ERROR_CONNECTION_FAILED" : {
+ code : tizen.WebAPIException.NETWORK_ERR,
+ name : "NetworkError",
+ message : "Connection failed",
+ },
+ "DOWNLOAD_ERROR_REQUEST_TIMEOUT" : {
+ code : tizen.WebAPIException.NETWORK_ERR,
+ name : "NetworkError",
+ message : "There are no action after client create a download id",
+ },
+ "DOWNLOAD_ERROR_RESPONSE_TIMEOUT" : {
+ code : tizen.WebAPIException.NETWORK_ERR,
+ name : "NetworkError",
+ message : "It does not call start API in some time although the download is created",
+ },
+ "DOWNLOAD_ERROR_TOO_MANY_REDIRECTS" : {
+ code : tizen.WebAPIException.NETWORK_ERR,
+ name : "NetworkError",
+ message : "In case of too may redirects from http response header",
+ },
+ "DOWNLOAD_ERROR_UNHANDLED_HTTP_CODE" : {
+ code : tizen.WebAPIException.NETWORK_ERR,
+ name : "NetworkError",
+ message : "The download cannot handle the HTTP status value",
+ },
+ "DOWNLOAD_ERROR_SYSTEM_DOWN" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "There are no response from client after rebooting download daemon",
+ },
+ "DOWNLOAD_ERROR_NO_DATA" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "No data because the set API is not called",
+ },
+ "DOWNLOAD_ERROR_ID_NOT_FOUND" : {
+ code : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+ name : "NotSupportedError",
+ message : "The download id is not existed in download service module",
+ },
+};
+
+var downloadState = {};
+
+extension.setMessageListener(function(msg) {
+ var m = JSON.parse(msg);
+ if (m.cmd == "DownloadReplyProgress") {
+ downloadState[m.uid] = "DOWNLOADING";
+ startListeners[m.uid].onprogress(m.uid, m.receivedSize, m.totalSize);
+ } else if (m.cmd == "DownloadReplyComplete") {
+ downloadState[m.uid] = "COMPLETED";
+ startListeners[m.uid].oncompleted(m.uid, m.fullPath);
+ } else if (m.cmd == "DownloadReplyPause") {
+ downloadState[m.uid] = "PAUSED";
+ startListeners[m.uid].onpaused(m.uid);
+ } else if (m.cmd == "DownloadReplyCancel") {
+ downloadState[m.uid] = "CANCELED";
+ startListeners[m.uid].oncanceled(m.uid);
+ } else if (m.cmd == "DownloadReplyFail") {
+ downloadState[m.uid] = "FAILED";
+ startListeners[m.uid].onfailed(m.uid,
+ new tizen.WebAPIError(errorMap[m.errorCode].code,
+ errorMap[m.errorCode].message,
+ errorMap[m.errorCode].name));
+ }
+});
+
+tizen.DownloadRequest = function(url, destination, filename) {
+ this.url = url;
+ this.uid = (++currentUID).toString();
+ typeof destination != 'undefined' && (this.destination = destination);
+ typeof filename != 'undefined' && (this.filename = filename);
+}
+
+exports.start = function(request, listener) {
+ if (!(request instanceof tizen.DownloadRequest)) {
+ console.log(
+ "tizen.download.start(): argument of invalid type " + typeof(request));
+ return;
+ }
+ startListeners[request.uid] = listener;
+ postMessage({
+ "cmd": "DownloadStart",
+ "url": request.url,
+ "uid": request.uid,
+ "destination": request.destination,
+ "filename": request.filename,
+ });
+ return request.uid;
+}
+
+exports.setListener = function(downloadId, listener) {
+ startListeners[request.uid] = listener;
+}
+
+exports.pause = function(downloadId) {
+ postMessage({
+ "cmd": "DownloadPause",
+ "uid": downloadId,
+ });
+}
+
+exports.resume = function(downloadId) {
+ postMessage({
+ "cmd": "DownloadResume",
+ "uid": downloadId,
+ });
+}
+
+exports.cancel = function(downloadId) {
+ postMessage({
+ "cmd": "DownloadCancel",
+ "uid": downloadId,
+ });
+}
+
+// TODO(hdq): Use sync message to get state from manager.
+exports.getState = function(downloadId) {
+ return downloadState[downloadId];
+}
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "download/download_context.h"
+
+#include "common/picojson.h"
+
+#define CHECK(x, args) do { \
+ int retval = (x); \
+ if (retval != DOWNLOAD_ERROR_NONE) { \
+ fprintf(stderr, "Download error: %s returned %s at %s:%d \n", #x, \
+ ConvertErrorToString(retval), __FILE__, __LINE__); \
+ OnFailedInfo(args, ToString(ConvertErrorToString(retval))); \
+ return; \
+ } \
+} while (0)
+
+#define CHECK_DO(x, args, y) do { \
+ int retval = (x); \
+ if (retval != DOWNLOAD_ERROR_NONE) { \
+ fprintf(stderr, "Download error: %s returned %s at %s:%d \n", #x, \
+ ConvertErrorToString(retval), __FILE__, __LINE__); \
+ OnFailedInfo(args, ToString(ConvertErrorToString(retval))); \
+ y; \
+ } \
+} while (0)
+
+CXWalkExtension* xwalk_extension_init(int32_t api_version) {
+ return ExtensionAdapter<DownloadContext>::Initialize();
+}
+
+DownloadContext::DownloadContext(ContextAPI* api)
+ : api_(api) {
+}
+
+DownloadContext::~DownloadContext() {
+ delete (api_);
+ for (DownloadArgsVector::iterator it = args_.begin();
+ it != args_.end(); it++) {
+ delete (*it);
+ }
+}
+
+const char DownloadContext::name[] = "tizen.download";
+
+// This will be generated from download_api.js.
+extern const char kSource_download_api[];
+
+const char* DownloadContext::GetJavaScript() {
+ return kSource_download_api;
+}
+
+const char* DownloadContext::ConvertErrorToString(int error) {
+ switch (error) {
+ case DOWNLOAD_ERROR_NONE:
+ return "DOWNLOAD_ERROR_NONE";
+ case DOWNLOAD_ERROR_INVALID_PARAMETER:
+ return "DOWNLOAD_ERROR_INVALID_PARAMETER";
+ case DOWNLOAD_ERROR_OUT_OF_MEMORY:
+ return "DOWNLOAD_ERROR_OUT_OF_MEMORY";
+ case DOWNLOAD_ERROR_NETWORK_UNREACHABLE:
+ return "DOWNLOAD_ERROR_NETWORK_UNREACHABLE";
+ case DOWNLOAD_ERROR_CONNECTION_TIMED_OUT:
+ return "DOWNLOAD_ERROR_CONNECTION_TIMED_OUT";
+ case DOWNLOAD_ERROR_NO_SPACE:
+ return "DOWNLOAD_ERROR_NO_SPACE";
+ case DOWNLOAD_ERROR_FIELD_NOT_FOUND:
+ return "DOWNLOAD_ERROR_FIELD_NOT_FOUND";
+ case DOWNLOAD_ERROR_INVALID_STATE:
+ return "DOWNLOAD_ERROR_INVALID_STATE";
+ case DOWNLOAD_ERROR_CONNECTION_FAILED:
+ return "DOWNLOAD_ERROR_CONNECTION_FAILED";
+ case DOWNLOAD_ERROR_INVALID_URL:
+ return "DOWNLOAD_ERROR_INVALID_URL";
+ case DOWNLOAD_ERROR_INVALID_DESTINATION:
+ return "DOWNLOAD_ERROR_INVALID_DESTINATION";
+ case DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS:
+ return "DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS";
+ case DOWNLOAD_ERROR_QUEUE_FULL:
+ return "DOWNLOAD_ERROR_QUEUE_FULL";
+ case DOWNLOAD_ERROR_ALREADY_COMPLETED:
+ return "DOWNLOAD_ERROR_ALREADY_COMPLETED";
+ case DOWNLOAD_ERROR_FILE_ALREADY_EXISTS:
+ return "DOWNLOAD_ERROR_FILE_ALREADY_EXISTS";
+ case DOWNLOAD_ERROR_CANNOT_RESUME:
+ return "DOWNLOAD_ERROR_CANNOT_RESUME";
+ case DOWNLOAD_ERROR_TOO_MANY_REDIRECTS:
+ return "DOWNLOAD_ERROR_TOO_MANY_REDIRECTS";
+ case DOWNLOAD_ERROR_UNHANDLED_HTTP_CODE:
+ return "DOWNLOAD_ERROR_UNHANDLED_HTTP_CODE";
+ case DOWNLOAD_ERROR_REQUEST_TIMEOUT:
+ return "DOWNLOAD_ERROR_REQUEST_TIMEOUT";
+ case DOWNLOAD_ERROR_RESPONSE_TIMEOUT:
+ return "DOWNLOAD_ERROR_RESPONSE_TIMEOUT";
+ case DOWNLOAD_ERROR_SYSTEM_DOWN:
+ return "DOWNLOAD_ERROR_SYSTEM_DOWN";
+ case DOWNLOAD_ERROR_ID_NOT_FOUND:
+ return "DOWNLOAD_ERROR_ID_NOT_FOUND";
+ case DOWNLOAD_ERROR_NO_DATA:
+ return "DOWNLOAD_ERROR_NO_DATA";
+ case DOWNLOAD_ERROR_IO_ERROR:
+ return "DOWNLOAD_ERROR_IO_ERROR";
+ default:
+ return "DOWNLOAD_UNKNOWN_ERROR";
+ }
+}
+
+void DownloadContext::HandleMessage(const char* message) {
+ picojson::value v;
+
+ std::string err;
+ picojson::parse(v, message, message + strlen(message), &err);
+ if (!err.empty()) {
+ fprintf(stderr, "Ignoring message.\n");
+ return;
+ }
+
+ std::string cmd = v.get("cmd").to_str();
+ if (cmd == "DownloadStart")
+ HandleStart(v);
+ else if (cmd == "DownloadPause")
+ HandleGeneral(v, download_pause, "HandlePause");
+ else if (cmd == "DownloadResume")
+ HandleGeneral(v, download_start, "HandleResume");
+ else if (cmd == "DownloadCancel")
+ HandleGeneral(v, download_cancel, "HandleCancel");
+ // TODO(hdq): add getstate
+}
+
+void DownloadContext::OnStateChanged(int download_id,
+ download_state_e state, void* user_data) {
+ DownloadArgs* args = static_cast<DownloadArgs*>(user_data);
+ switch (state) {
+ case DOWNLOAD_STATE_DOWNLOADING:
+ OnStartInfo(download_id, user_data);
+ break;
+ case DOWNLOAD_STATE_PAUSED:
+ OnPausedInfo(user_data);
+ break;
+ case DOWNLOAD_STATE_COMPLETED:
+ OnFinishedInfo(download_id, user_data);
+ break;
+ case DOWNLOAD_STATE_CANCELED:
+ OnCanceledInfo(user_data);
+ break;
+ case DOWNLOAD_STATE_FAILED: {
+ download_error_e error;
+ CHECK(download_get_error(download_id, &error), args);
+ args->context->OnFailedInfo(args, ToString(ConvertErrorToString(error)));
+ }
+ break;
+ default:
+ fprintf(stderr, "Ignore state: %d\n", state);
+ break;
+ }
+}
+
+void DownloadContext::OnStartInfo(int download_id, void* user_param) {
+ DownloadArgs* args = static_cast<DownloadArgs*>(user_param);
+ const std::string uid(args->download_uid);
+ DownloadItemRefPtr downloadItem = args->context->downloads_[uid];
+
+ long long unsigned file_size = 0;
+ CHECK(download_get_content_size(download_id, &file_size), args);
+ downloadItem->file_size = file_size;
+}
+
+void DownloadContext::OnProgressInfo(int download_id,
+ long long unsigned received,
+ void* user_param) {
+ DownloadArgs* args = static_cast<DownloadArgs*>(user_param);
+ DownloadItemRefPtr downloadItem =
+ args->context->downloads_[args->download_uid];
+
+ picojson::value::object o;
+ o["cmd"] = picojson::value("DownloadReplyProgress");
+ o["uid"] = picojson::value(args->download_uid);
+ o["receivedSize"] = picojson::value(ToString(received));
+ o["totalSize"] = picojson::value(ToString(downloadItem->file_size));
+ picojson::value v(o);
+ args->context->api_->PostMessage(v.serialize().c_str());
+}
+
+void DownloadContext::OnFinishedInfo(int download_id, void* user_param) {
+ DownloadArgs* args = static_cast<DownloadArgs*>(user_param);
+ const std::string uid(args->download_uid);
+ DownloadItemRefPtr downloadItem = args->context->downloads_[uid];
+ char* path = 0;
+ CHECK(download_get_downloaded_file_path(download_id, &path), args);
+ std::string full_path = ToString(path);
+ free(path);
+
+ picojson::value::object o;
+ o["cmd"] = picojson::value("DownloadReplyComplete");
+ o["fullPath"] = picojson::value(full_path);
+ o["uid"] = picojson::value(args->download_uid);
+ picojson::value v(o);
+ args->context->api_->PostMessage(v.serialize().c_str());
+}
+
+void DownloadContext::OnPausedInfo(void* user_param) {
+ DownloadArgs* args = static_cast<DownloadArgs*>(user_param);
+
+ picojson::value::object o;
+ o["cmd"] = picojson::value("DownloadReplyPause");
+ o["uid"] = picojson::value(args->download_uid);
+ picojson::value v(o);
+ args->context->api_->PostMessage(v.serialize().c_str());
+}
+
+void DownloadContext::OnCanceledInfo(void* user_param) {
+ DownloadArgs* args = static_cast<DownloadArgs*>(user_param);
+
+ picojson::value::object o;
+ o["cmd"] = picojson::value("DownloadReplyCancel");
+ o["uid"] = picojson::value(args->download_uid);
+ picojson::value v(o);
+ args->context->api_->PostMessage(v.serialize().c_str());
+}
+
+void DownloadContext::OnFailedInfo(void* user_param,
+ const std::string& error) {
+ DownloadArgs* args = static_cast<DownloadArgs*>(user_param);
+
+ picojson::value::object o;
+ o["cmd"] = picojson::value("DownloadReplyFail");
+ o["uid"] = picojson::value(args->download_uid);
+ o["errorCode"] = picojson::value(error);
+ picojson::value v(o);
+ args->context->api_->PostMessage(v.serialize().c_str());
+}
+
+void DownloadContext::HandleStart(const picojson::value& msg) {
+ // Add to Downloads map
+ DownloadItemRefPtr d(new DownloadItem);
+ d->url = msg.get("url").to_str();
+ d->destination = GetFullDestinationPath(msg.get("destination").to_str());
+ std::string filename = msg.get("filename").to_str();
+ d->filename = (filename == "null") ? std::string() : filename;
+ std::string uid = msg.get("uid").to_str();
+ d->uid = uid;
+
+ DownloadArgs* args = new DownloadArgs(uid, this);
+ args_.push_back(args);
+
+ // create and start
+ CHECK(download_create(&d->downloadID), args);
+ CHECK(download_set_state_changed_cb(d->downloadID, OnStateChanged,
+ static_cast<void* >(args)), args);
+ CHECK(download_set_progress_cb(d->downloadID, OnProgressInfo,
+ static_cast<void*>(args)), args);
+ CHECK(download_set_destination(d->downloadID, d->destination.c_str()), args);
+
+ if (!d->filename.empty()) {
+ CHECK(download_set_file_name(d->downloadID, d->filename.c_str()), args);
+ }
+ downloads_[uid] = d; // FIXME if uid duplicate we will lose previous item
+
+ CHECK(download_set_url(d->downloadID, d->url.c_str()), args);
+ CHECK(download_start(d->downloadID), args);
+}
+
+template <typename FnType>
+bool DownloadContext::HandleGeneral(const picojson::value& msg,
+ FnType fn,
+ const char* fn_name) {
+ std::string uid = msg.get("uid").to_str();
+ if (uid == "null") {
+ fprintf(stderr, "%s - ERROR: Undefined download UID\n", fn_name);
+ return false;
+ }
+
+ DownloadArgs* args = new DownloadArgs(uid, this);
+ args_.push_back(args);
+ int downloadID = downloads_[uid]->downloadID;
+ CHECK_DO(fn(downloadID), args, return false);
+ return true;
+}
+
+std::string DownloadContext::GetUID(int downloadID) const {
+ std::string uid("null");
+ for (DownloadItemMap::const_iterator it = downloads_.begin();
+ it != downloads_.end(); it++) {
+ if (it->second->downloadID == downloadID) {
+ uid = it->second->uid;
+ break;
+ }
+ }
+ return uid;
+}
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DOWNLOAD_DOWNLOAD_CONTEXT_H_
+#define DOWNLOAD_DOWNLOAD_CONTEXT_H_
+
+#include <tr1/memory>
+#include <map>
+#include <vector>
+#include <string>
+#include <sstream>
+
+#include "common/extension_adapter.h"
+#include "web/download.h"
+
+namespace picojson {
+class value;
+}
+
+class DownloadContext {
+ public:
+ explicit DownloadContext(ContextAPI* api);
+ ~DownloadContext();
+
+ // ExtensionAdapter implementation.
+ static const char name[];
+ static const char* GetJavaScript();
+ void HandleMessage(const char* message);
+ void HandleSyncMessage(const char* message) {}
+
+ private:
+ void HandleStart(const picojson::value& msg);
+ template <typename FnType>
+ bool HandleGeneral(const picojson::value& msg,
+ FnType fn,
+ const char* fn_name);
+ struct DownloadArgs {
+ std::string download_uid;
+ DownloadContext* context;
+ DownloadArgs(std::string uid, DownloadContext* c)
+ : download_uid(uid), context(c) {}
+ };
+ typedef std::vector<DownloadArgs*> DownloadArgsVector;
+ DownloadArgsVector args_;
+ static void OnStateChanged(int download_id,
+ download_state_e state,
+ void* user_data);
+ static void OnProgressInfo(int download_id,
+ long long unsigned received,
+ void* user_param);
+ static void OnStartInfo(int download_id, void* user_param);
+ static void OnFinishedInfo(int download_id, void* user_param);
+ static void OnPausedInfo(void* user_param);
+ static void OnCanceledInfo(void* user_param);
+ static void OnFailedInfo(void* user_param,
+ const std::string& error);
+
+ ContextAPI* api_;
+
+ struct DownloadItem {
+ std::string url;
+ std::string destination;
+ std::string filename;
+ std::string uid;
+
+ int downloadID;
+ char* file_type;
+ long long unsigned file_size;
+ char* tmp_saved_path;
+ char* content_name;
+
+ DownloadItem() {}
+ ~DownloadItem() {
+ download_unset_state_changed_cb(downloadID);
+ download_unset_progress_cb(downloadID);
+ download_destroy(downloadID);
+ }
+
+ private:
+ explicit DownloadItem(DownloadItem const&);
+ void operator= (DownloadItem const&);
+ };
+ typedef std::tr1::shared_ptr<DownloadItem> DownloadItemRefPtr;
+ typedef std::map<std::string, DownloadItemRefPtr> DownloadItemMap;
+ DownloadItemMap downloads_;
+
+ // FullDestPath = HomePath + DestPath
+ // TODO(hdq): This depends on filesystem api?
+ std::string GetFullDestinationPath(const std::string destination) const;
+
+ // helpers
+ template <typename T>
+ static std::string ToString(T a) {
+ std::ostringstream ss;
+ ss << a;
+ return ss.str();
+ }
+ std::string GetUID(int downloadID) const;
+ static const char* ConvertErrorToString(int error); // download_error_e
+
+ private:
+ explicit DownloadContext(DownloadContext const&);
+ void operator=(DownloadContext const&);
+};
+
+#endif // DOWNLOAD_DOWNLOAD_CONTEXT_H_
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "download/download_context.h"
+
+#include <pwd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+std::string DownloadContext::GetFullDestinationPath(
+ const std::string destination) const {
+ std::string folder = (destination == "null") ? std::string() : destination;
+
+ std::string path(getenv("HOME"));
+ if (path.empty()) {
+ struct passwd password_entry;
+ struct passwd *password_entry_ptr;
+ char buf[1024];
+ if (!getpwuid_r(getuid(), &password_entry,
+ buf, sizeof buf, &password_entry_ptr)) {
+ path = password_entry.pw_dir;
+ }
+ }
+ return (path + '/' + folder);
+}
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "download/download_context.h"
+
+std::string DownloadContext::GetFullDestinationPath(
+ const std::string destination) const {
+ std::string folder = (destination == "null") ? std::string() : destination;
+
+ // TODO(hdq): User should be able to choose store to external storage
+ // i.e. /opt/storage/sdcard/Downloads
+ std::string path("/opt/usr/media/");
+ if (folder.empty()) {
+ return (path + "Downloads/");
+ }
+ return (path + folder);
+}
--- /dev/null
+<h1>Hello Tizen Download API</h1>
+
+<body>
+ <style type="text/css">
+ span { border: none; }
+ div { max-width: 500px; }
+ </style>
+ <span contenteditable="true" id="download1"></span><br>
+ <span contenteditable="true" id="download2"></span><br>
+ <textarea cols=80 rows=20 id="output"></textarea><br>
+ <button id="bnstart1">Click 1</button>
+ <button id="bnstart2">Click 2</button><br>
+ <button id="button1">Click 1</button>
+ <button id="button2">Click 2</button><br>
+ <button id="b1cancel">Click 1</button>
+ <button id="b2cancel">Click 2</button><br>
+ <button id="bnstate1">Click 1</button>
+ <button id="bnstate2">Click 2</button>
+</body>
+
+<script>
+
+var output = document.getElementById("output");
+
+function handle(button, text, callback) {
+ var b = document.getElementById(button);
+ b.innerText = text;
+ b.addEventListener("click", callback);
+}
+
+var listener = {
+ onprogress: function(id, receivedSize, totalSize) {
+ if (urls[id] == url1)
+ document.getElementById("download1").innerHTML = "Download1 received " + receivedSize + "/" + totalSize + " bytes"
+ else if (urls[id] == url2)
+ document.getElementById("download2").innerHTML = "Download2 received " + receivedSize + "/" + totalSize + " bytes"
+ else
+ output.value += "> listener::onprogress - unexpected call: id " + id + ", size " + receivedSize + "/" + totalSize + "\n";
+ },
+ oncompleted: function(id, fullPath) {
+ output.value += "> Download complete, id:" + id + ", saved to path: " + fullPath + "\n";
+ },
+ onpaused: function(id) {
+ output.value += "> Download is paused by user\n";
+ },
+ oncanceled: function(id) {
+ output.value += "> Download is canceled by user\n";
+ },
+ onfailed: function(id, error) {
+ output.value += "> Download of id[" + id + "] failed with error:" +
+ " code[" + error.code + "]" +
+ " name[" + error.name + "]" +
+ " message[" + error.message + "]\n";
+ }
+};
+
+// Test big file downloading
+var url1 = "http://ipv4.download.thinkbroadband.com/200MB.zip";
+// Test https downloading
+var url2 = "https://developer.tizen.org/sites/all/themes/tizen_theme/logo.png";
+var urls = { "1" : url1, "2" : url2 }
+
+var r1, id1, r2, id2;
+var paused1=false;
+var paused2=false;
+
+handle("bnstart1", "Start Download1", function() {
+ r1 = new tizen.DownloadRequest(url1); // Test saving to default folder
+ id1 = tizen.download.start(r1, listener);
+ urls[id1] = url1;
+ output.value += "> asked to start download " + url1 + " to default location.\n";
+});
+
+handle("button1", "Pause Download1", function() {
+ if (typeof id1 == "undefined") {
+ output.value += "> Download1 is not started yet.\n";
+ return;
+ }
+
+ if (paused1) {
+ output.value += "> asked to resume download of " + url1 + "\n";
+ tizen.download.resume(id1);
+ paused1 = false;
+ var b = document.getElementById("button1");
+ b.innerText = "Pause Download1";
+ } else {
+ output.value += "> asked to pause download of " + url1 + "\n";
+ tizen.download.pause(id1);
+ paused1 = true;
+ var b = document.getElementById("button1");
+ b.innerText = "Resume Download1";
+ }
+});
+
+handle("bnstart2", "Start Download2", function() {
+ r2 = new tizen.DownloadRequest(url2, "Images"); // Test saving to specific folder
+ id2 = tizen.download.start(r2, listener);
+ urls[id2] = url2;
+ output.value += "> asked to start download "+url2+" to Images folder\n";
+});
+
+handle("button2", "Pause Download2", function() {
+ if (typeof id2 == "undefined") {
+ output.value += "> Download1 is not started yet.\n";
+ return;
+ }
+
+ if (paused2) {
+ output.value += "> asked to resume download of " + url2 + "\n";
+ tizen.download.resume(id2);
+ paused2 = false;
+ var b = document.getElementById("button2");
+ b.innerText = "Pause Download2";
+ } else {
+ output.value += "> asked to pause download of " + url2 + "\n";
+ tizen.download.pause(id2);
+ paused2 = true;
+ var b = document.getElementById("button2");
+ b.innerText = "Resume Download2";
+ }
+});
+
+handle("b1cancel", "Cancel Download1", function() {
+ if (typeof id1 == "undefined") {
+ output.value += "> Download1 is not started yet.\n";
+ return;
+ }
+
+ output.value += "> asked to cancel download of " + url1 + "\n";
+ tizen.download.cancel(id1);
+});
+
+handle("b2cancel", "Cancel Download2", function() {
+ if (typeof id2 == "undefined") {
+ output.value += "> Download2 is not started yet.\n";
+ return;
+ }
+
+ output.value += "> asked to cancel download of " + url2 + "\n";
+ tizen.download.cancel(id2);
+});
+
+handle("bnstate1", "GetState of Download1", function() {
+ if (typeof id1 == "undefined") {
+ output.value += "> Download1 is not started yet.\n";
+ return;
+ }
+
+ output.value += "> asked to get state of download1, id:" + id1 + "\n";
+ output.value += "> return: " + tizen.download.getState(id1) + "\n";
+});
+
+handle("bnstate2", "GetState of Download2", function() {
+ if (typeof id2 == "undefined") {
+ output.value += "> Download2 is not started yet.\n";
+ return;
+ }
+
+ output.value += "> asked to get state of download2, id:" + id2 + "\n";
+ output.value += "> return: " + tizen.download.getState(id2) + "\n";
+});
+
+</script>
<a href="time.html"><h5>- Time Test</h5></a>
<a href="power.html"><h5>- Power API Test</h5></a>
<a href="bluetooth.html"><h5>- Bluetooth Test</h5></a>
+<a href="download.html"><h5>- Download Test</h5></a>
</body>
Source1001: %{name}.manifest
BuildRequires: python
+BuildRequires: pkgconfig(capi-appfw-application)
BuildRequires: pkgconfig(capi-network-bluetooth)
BuildRequires: pkgconfig(capi-network-connection)
BuildRequires: pkgconfig(capi-system-device)
BuildRequires: pkgconfig(capi-system-info)
BuildRequires: pkgconfig(capi-system-power)
BuildRequires: pkgconfig(capi-system-system-settings)
+BuildRequires: pkgconfig(capi-web-url-download)
BuildRequires: pkgconfig(dbus-glib-1)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libudev)
'system_setting/system_setting.gyp:*',
'time/time.gyp:*',
'tizen/tizen.gyp:*',
+ 'download/download.gyp:*',
],
},
],