[download] Advanced features
authorDeqing Huang <deqing.huang@intel.com>
Mon, 12 Aug 2013 11:18:26 +0000 (19:18 +0800)
committerDeqing Huang <deqing.huang@intel.com>
Tue, 20 Aug 2013 08:36:40 +0000 (16:36 +0800)
download/download.gyp
download/download_api.js
download/download_context.cc
download/download_context.h
download/download_utils.h [new file with mode: 0644]
examples/download.html

index daeb051..0a7a45c 100644 (file)
@@ -12,6 +12,7 @@
         'download_context.h',
         'download_context_desktop.cc',
         'download_context_mobile.cc',
+        'download_utils.h',
       ],
       'conditions': [
         ['extension_host_os=="mobile"', {
index 619721b..8402d8d 100644 (file)
@@ -4,7 +4,11 @@
 
 var repliedMsg;
 var currentUID = 0;
+var requests = {};
 var startListeners = [];
+var networkTypeCallbacks = [];
+var mimeTypeCallbacks = [];
+var httpHeaderCallbacks = [];
 
 var postMessage = function(msg) {
   extension.postMessage(JSON.stringify(msg));
@@ -133,24 +137,21 @@ var errorMap = {
   },
 };
 
-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 == "DownloadReplyNetworkType") {
+    networkTypeCallbacks[m.uid](m.networkType);
+  } else if (m.cmd == "DownloadReplyMIMEType") {
+    mimeTypeCallbacks[m.uid](m.mimeType);
   } 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,
@@ -158,19 +159,21 @@ extension.setMessageListener(function(msg) {
   }
 });
 
-tizen.DownloadRequest = function(url, destination, filename) {
+tizen.DownloadRequest = function(url, destination, filename, networkType) {
   this.url = url;
   this.uid = (++currentUID).toString();
-  typeof destination != 'undefined' && (this.destination = destination);
-  typeof filename != 'undefined' && (this.filename = filename);
+  typeof destination != "undefined" && (this.destination = destination);
+  typeof filename != "undefined" && (this.filename = filename);
+  typeof networkType != "undefined" && (this.networkType = networkType);
+  this.httpHeader = {};
 }
 
 exports.start = function(request, listener) {
   if (!(request instanceof tizen.DownloadRequest)) {
-    console.log(
-        "tizen.download.start(): argument of invalid type " + typeof(request));
+    console.log("tizen.download.start(): argument of invalid type " + typeof(request));
     return;
   }
+  requests[request.uid] = request;
   startListeners[request.uid] = listener;
   postMessage({
     "cmd": "DownloadStart",
@@ -178,15 +181,23 @@ exports.start = function(request, listener) {
     "uid": request.uid,
     "destination": request.destination,
     "filename": request.filename,
+    "networkType": request.networkType,
+    "httpHeader": request.httpHeader,
   });
   return request.uid;
 }
 
 exports.setListener = function(downloadId, listener) {
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
   startListeners[request.uid] = listener;
 }
 
 exports.pause = function(downloadId) {
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
   postMessage({
     "cmd": "DownloadPause",
     "uid": downloadId,
@@ -194,6 +205,9 @@ exports.pause = function(downloadId) {
 }
 
 exports.resume = function(downloadId) {
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
   postMessage({
     "cmd": "DownloadResume",
     "uid": downloadId,
@@ -201,13 +215,70 @@ exports.resume = function(downloadId) {
 }
 
 exports.cancel = function(downloadId) {
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
   postMessage({
     "cmd": "DownloadCancel",
     "uid": downloadId,
   });
 }
 
-// TODO(hdq): Use sync message to get state from manager.
+exports.getDownloadRequest = function(downloadId) {
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
+  return requests[downloadId];
+}
+
+exports.getNetworkType = function(downloadId, callback) {
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
+  networkTypeCallbacks[downloadId] = callback;
+  postMessage({
+    "cmd": "DownloadGetNetworkType",
+    "uid": downloadId,
+  });
+}
+
+exports.getMIMEType = function(downloadId, callback) {
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
+  mimeTypeCallbacks[downloadId] = callback;
+  postMessage({
+    "cmd": "DownloadGetMIMEType",
+    "uid": downloadId,
+  });
+}
+
 exports.getState = function(downloadId) {
-  return downloadState[downloadId];
+  if (typeof requests[downloadId] == "undefined") {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
+  var reply = JSON.parse(_sendSyncMessage({
+    "cmd": "DownloadGetState",
+    "uid": downloadId,
+  }));
+  if (reply["error"] != "DOWNLOAD_ERROR_NONE") {
+    switch (reply["error"]) {
+    case "DOWNLOAD_ERROR_INVALID_PARAMETER":
+      // TODO(hdq): Spec said to throw "InvalidValuesError" here, but there is no such value in WebAPIException
+      throw new tizen.WebAPIException(tizen.WebAPIException.SYNTAX_ERR);
+      break;
+    case "DOWNLOAD_ERROR_ID_NOT_FOUND":
+      throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+      break;
+    default:
+      throw new tizen.WebAPIException(tizen.WebAPIException.NOT_SUPPORTED_ERR);
+    }
+  } else {
+    delete reply["error"];
+    return reply["state"];
+  }
 }
+
+var _sendSyncMessage = function(msg) {
+  return extension.internal.sendSyncMessage(JSON.stringify(msg));
+};
index 02a2e8e..a719483 100644 (file)
@@ -3,15 +3,19 @@
 // found in the LICENSE file.
 
 #include "download/download_context.h"
+#include "download/download_utils.h"
 
 #include "common/picojson.h"
 
+using download_utils::EnumToPChar;
+using download_utils::ToString;
+
 #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))); \
+                    EnumToPChar(retval), __FILE__, __LINE__); \
+    OnFailedInfo(args, ToString(EnumToPChar(retval))); \
     return; \
   } \
 } while (0)
@@ -20,8 +24,8 @@
   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))); \
+                    EnumToPChar(retval), __FILE__, __LINE__); \
+    OnFailedInfo(args, ToString(EnumToPChar(retval))); \
     y; \
   } \
 } while (0)
@@ -51,61 +55,6 @@ 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;
 
@@ -125,7 +74,29 @@ void DownloadContext::HandleMessage(const char* message) {
     HandleGeneral(v, download_start, "HandleResume");
   else if (cmd == "DownloadCancel")
     HandleGeneral(v, download_cancel, "HandleCancel");
-  // TODO(hdq): add getstate
+  else if (cmd == "DownloadGetNetworkType")
+    HandleGetNetworkType(v);
+  else if (cmd == "DownloadGetMIMEType")
+    HandleGetMIMEType(v);
+  else
+    fprintf(stderr, "Not supported async command %s\n", cmd.c_str());
+}
+
+void DownloadContext::HandleSyncMessage(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 == "DownloadGetState")
+    HandleGetState(v);
+  else
+    fprintf(stderr, "Not supported sync command %s\n", cmd.c_str());
 }
 
 void DownloadContext::OnStateChanged(int download_id,
@@ -147,7 +118,7 @@ void DownloadContext::OnStateChanged(int download_id,
   case DOWNLOAD_STATE_FAILED: {
       download_error_e error;
       CHECK(download_get_error(download_id, &error), args);
-      args->context->OnFailedInfo(args, ToString(ConvertErrorToString(error)));
+      args->context->OnFailedInfo(args, ToString(EnumToPChar(error)));
     }
     break;
   default:
@@ -234,12 +205,21 @@ void DownloadContext::OnFailedInfo(void* user_param,
 void DownloadContext::HandleStart(const picojson::value& msg) {
   // Add to Downloads map
   DownloadItemRefPtr d(new DownloadItem);
-  d->url  = msg.get("url").to_str();
+  std::string uid = msg.get("uid").to_str();
+  d->uid = uid;
+
+  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;
+
+  std::string network_type = msg.get("networkType").to_str();
+  if (network_type == "CELLULAR")
+    d->networkType = DOWNLOAD_NETWORK_DATA_NETWORK;
+  else if (network_type == "WIFI")
+    d->networkType = DOWNLOAD_NETWORK_WIFI;
+  else
+    d->networkType = DOWNLOAD_NETWORK_ALL;
 
   DownloadArgs* args = new DownloadArgs(uid, this);
   args_.push_back(args);
@@ -250,14 +230,24 @@ void DownloadContext::HandleStart(const picojson::value& msg) {
                                       static_cast<void* >(args)), args);
   CHECK(download_set_progress_cb(d->downloadID, OnProgressInfo,
                                  static_cast<void*>(args)), args);
+  CHECK(download_set_url(d->downloadID, d->url.c_str()), 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);
   }
+  CHECK(download_set_network_type(d->downloadID, d->networkType), args);
+
+  if (msg.get("httpHeader").is<picojson::object>()) {
+    picojson::object obj = msg.get("httpHeader").get<picojson::object>();
+    for (picojson::object::const_iterator it = obj.begin();
+         it != obj.end(); ++it) {
+      CHECK(download_add_http_header_field(d->downloadID,
+            it->first.c_str(), it->second.to_str().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);
 }
 
@@ -265,16 +255,91 @@ 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);
+  int downloadID;
+  DownloadArgs* args;
+  if (!GetDownloadID(msg, downloadID, &args))
     return false;
+  CHECK_DO(fn(downloadID), args, return false);
+  return true;
+}
+
+void DownloadContext::HandleGetState(const picojson::value& msg) {
+  std::string uid;
+  int downloadID = -1;
+  std::string retStr("DOWNLOAD_ERROR_NONE");
+  download_state_e state;
+
+  if (!GetID(msg, uid, downloadID)) {
+    retStr = "DOWNLOAD_ERROR_ID_NOT_FOUND";
+  } else {
+    int ret = download_get_state(downloadID, &state);
+    if (ret != DOWNLOAD_ERROR_NONE)
+      retStr = EnumToPChar(ret);
   }
 
-  DownloadArgs* args = new DownloadArgs(uid, this);
-  args_.push_back(args);
-  int downloadID = downloads_[uid]->downloadID;
-  CHECK_DO(fn(downloadID), args, return false);
+  picojson::value::object o;
+  o["state"] = picojson::value(EnumToPChar(state));
+  o["error"] = picojson::value(retStr);
+  picojson::value v(o);
+  api_->SetSyncReply(v.serialize().c_str());
+}
+
+void DownloadContext::HandleGetNetworkType(const picojson::value& msg) {
+  int downloadID;
+  DownloadArgs* args;
+  if (!GetDownloadID(msg, downloadID, &args))
+    return;
+
+  download_network_type_e networkType;
+  CHECK(download_get_network_type(downloadID, &networkType), args);
+
+  picojson::value::object o;
+  o["cmd"] = picojson::value("DownloadReplyNetworkType");
+  o["uid"] = picojson::value(args->download_uid);
+  o["networkType"] = picojson::value(EnumToPChar(networkType));
+  picojson::value v(o);
+  args->context->api_->PostMessage(v.serialize().c_str());
+}
+
+void DownloadContext::HandleGetMIMEType(const picojson::value& msg) {
+  int downloadID;
+  DownloadArgs* args;
+  if (!GetDownloadID(msg, downloadID, &args))
+    return;
+
+  char* mimeType = 0;
+  CHECK(download_get_mime_type(downloadID, &mimeType), args);
+
+  picojson::value::object o;
+  o["cmd"] = picojson::value("DownloadReplyMIMEType");
+  o["uid"] = picojson::value(args->download_uid);
+  o["mimeType"] = picojson::value(mimeType);
+  picojson::value v(o);
+  args->context->api_->PostMessage(v.serialize().c_str());
+
+  if (mimeType)
+    free(mimeType);
+}
+
+bool DownloadContext::GetDownloadID(const picojson::value& msg,
+                                    int& downloadID, DownloadArgs** args) {
+  std::string uid;
+  if (!GetID(msg, uid, downloadID))
+    return false;
+  *args = new DownloadArgs(uid, this);
+  args_.push_back(*args);
+  return true;
+}
+
+bool DownloadContext::GetID(const picojson::value& msg,
+                            std::string& uid,
+                            int& downloadID) const {
+  uid = msg.get("uid").to_str();
+  if (uid == "null") {
+    fprintf(stderr, "ERROR: Undefined download UID\n");
+    return false;
+  }
+  downloadID = downloads_.find(uid)->second->downloadID;
   return true;
 }
 
index 3a169be..5a1cee4 100644 (file)
@@ -12,6 +12,7 @@
 #include <sstream>
 
 #include "common/extension_adapter.h"
+#include "common/utils.h"
 #include "web/download.h"
 
 namespace picojson {
@@ -27,7 +28,7 @@ class DownloadContext {
   static const char name[];
   static const char* GetJavaScript();
   void HandleMessage(const char* message);
-  void HandleSyncMessage(const char* message) {}
+  void HandleSyncMessage(const char* message);
 
  private:
   void HandleStart(const picojson::value& msg);
@@ -35,6 +36,9 @@ class DownloadContext {
   bool HandleGeneral(const picojson::value& msg,
                      FnType fn,
                      const char* fn_name);
+  void HandleGetState(const picojson::value& msg);
+  void HandleGetNetworkType(const picojson::value& msg);
+  void HandleGetMIMEType(const picojson::value& msg);
   struct DownloadArgs {
     std::string download_uid;
     DownloadContext* context;
@@ -59,10 +63,12 @@ class DownloadContext {
   ContextAPI* api_;
 
   struct DownloadItem {
+    std::string uid;
     std::string url;
     std::string destination;
     std::string filename;
-    std::string uid;
+    download_network_type_e networkType;
+    std::string httpHeader;
 
     int downloadID;
     char* file_type;
@@ -78,8 +84,7 @@ class DownloadContext {
     }
 
    private:
-    explicit DownloadItem(DownloadItem const&);
-    void operator= (DownloadItem const&);
+    DISALLOW_COPY_AND_ASSIGN(DownloadItem);
   };
   typedef std::tr1::shared_ptr<DownloadItem> DownloadItemRefPtr;
   typedef std::map<std::string, DownloadItemRefPtr> DownloadItemMap;
@@ -89,19 +94,14 @@ class DownloadContext {
   // 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();
-  }
+  bool GetDownloadID(const picojson::value& msg,
+                     int& downloadID, DownloadArgs** args);
+  bool GetID(const picojson::value& msg,
+             std::string& uid, int& downloadID) const;
   std::string GetUID(int downloadID) const;
-  static const char* ConvertErrorToString(int error);  // download_error_e
 
  private:
-  explicit DownloadContext(DownloadContext const&);
-  void operator=(DownloadContext const&);
+  DISALLOW_COPY_AND_ASSIGN(DownloadContext);
 };
 
 #endif  // DOWNLOAD_DOWNLOAD_CONTEXT_H_
diff --git a/download/download_utils.h b/download/download_utils.h
new file mode 100644 (file)
index 0000000..0e3a9c8
--- /dev/null
@@ -0,0 +1,115 @@
+// 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_UTILS_H_
+#define DOWNLOAD_DOWNLOAD_UTILS_H_
+
+#include <string>
+#include <algorithm>
+
+namespace download_utils {
+
+template <typename T>
+static std::string ToString(T a) {
+  std::ostringstream ss;
+  ss << a;
+  return ss.str();
+}
+
+const char* EnumToPChar(int error) {  // enum download_error_e
+  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";
+  }
+}
+
+const char* EnumToPChar(download_state_e state) {
+  switch (state) {
+  case DOWNLOAD_STATE_NONE:
+    return "DOWNLOAD_STATE_NONE";
+  case DOWNLOAD_STATE_READY:
+    return "DOWNLOAD_STATE_READY";
+  case DOWNLOAD_STATE_QUEUED:
+    return "DOWNLOAD_STATE_QUEUED";
+  case DOWNLOAD_STATE_DOWNLOADING:
+    return "DOWNLOAD_STATE_DOWNLOADING";
+  case DOWNLOAD_STATE_PAUSED:
+    return "DOWNLOAD_STATE_PAUSED";
+  case DOWNLOAD_STATE_COMPLETED:
+    return "DOWNLOAD_STATE_COMPLETED";
+  case DOWNLOAD_STATE_FAILED:
+    return "DOWNLOAD_STATE_FAILED";
+  case DOWNLOAD_STATE_CANCELED:
+    return "DOWNLOAD_STATE_CANCELED";
+  default:
+    return "DOWNLOAD_UNKNOWN_STATE";
+  }
+}
+
+const char* EnumToPChar(download_network_type_e net_type) {
+  switch (net_type) {
+  case DOWNLOAD_NETWORK_DATA_NETWORK:
+    return "DOWNLOAD_NETWORK_DATA_NETWORK";
+  case DOWNLOAD_NETWORK_WIFI:
+    return "DOWNLOAD_NETWORK_WIFI";
+  case DOWNLOAD_NETWORK_WIFI_DIRECT:
+    return "DOWNLOAD_NETWORK_WIFI_DIRECT";
+  case DOWNLOAD_NETWORK_ALL:
+    return "DOWNLOAD_NETWORK_ALL";
+  default:
+    return "DOWNLOAD_UNKNOWN_NETWORK_TYPE";
+  }
+}
+
+}  // namespace download_utils
+
+#endif  // DOWNLOAD_DOWNLOAD_UTILS_H_
index a07631c..3e48baf 100644 (file)
@@ -7,6 +7,7 @@
   </style>
   <span contenteditable="true" id="download1"></span><br>
   <span contenteditable="true" id="download2"></span><br>
+  <span contenteditable="true" id="download_http_header"></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="b1cancel">Click 1</button>
   <button id="b2cancel">Click 2</button><br>
   <button id="bnstate1">Click 1</button>
-  <button id="bnstate2">Click 2</button>
+  <button id="bnstate2">Click 2</button><br>
+  <button id="bnnetworktype1">Click 1</button>
+  <button id="bnnetworktype2">Click 2</button><br>
+  <button id="bnmimetype1">Click 1</button>
+  <button id="bnmimetype2">Click 2</button><br>
+  <button id="bngetrequest1">Click</button>
+  <button id="bngetrequest2">Click</button><br>
+  <button id="bnhttpheader">Click</button><br>
 </body>
 
 <script>
@@ -34,6 +42,8 @@ var listener = {
       document.getElementById("download1").innerHTML = "Download1 received " + receivedSize + "/" + totalSize + " bytes"
     else if (urls[id] == url2)
       document.getElementById("download2").innerHTML = "Download2 received " + receivedSize + "/" + totalSize + " bytes"
+    else if (urls[id] == url_httpheader)
+      document.getElementById("download_http_header").innerHTML = "Download (Test for HTTP header) received " + receivedSize + "/" + totalSize + " bytes"
     else
       output.value += "> listener::onprogress - unexpected call: id " + id + ", size " + receivedSize + "/" + totalSize + "\n";
   },
@@ -58,7 +68,9 @@ var listener = {
 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 }
+// Test downloading with specific HTTP header
+var url_httpheader = "http://download.tizen.org/tools/README.txt";
+var urls = { "1" : url1, "2" : url2, "3" : url_httpheader }
 
 var r1, id1, r2, id2;
 var paused1=false;
@@ -94,6 +106,7 @@ handle("button1", "Pause Download1", function() {
 
 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";
@@ -147,7 +160,11 @@ handle("bnstate1", "GetState of Download1", function() {
   }
 
   output.value += "> asked to get state of download1, id:" + id1 + "\n";
-  output.value += "> return: " + tizen.download.getState(id1) + "\n";
+  try {
+    output.value += "> return: " + tizen.download.getState(id1) + "\n";
+  } catch (err) {
+    output.value += "> received exception: " + err.name + "\n";
+  }
 });
 
 handle("bnstate2", "GetState of Download2", function() {
@@ -156,8 +173,95 @@ handle("bnstate2", "GetState of Download2", function() {
     return;
   }
 
-  output.value += "> asked to get state of download2, id:" + id2 + "\n";
-  output.value += "> return: " + tizen.download.getState(id2) + "\n";
+  output.value += "> asked to get state of download1, id:" + id2 + "\n";
+  try {
+    output.value += "> return: " + tizen.download.getState(id2) + "\n";
+  } catch (err) {
+    output.value += "> received exception: " + err.name + "\n";
+  }
+});
+
+var networkTypeCallback = function(networkType) {
+  output.value += "> received networkType: " + networkType + "\n";
+}
+
+handle("bnnetworktype1", "GetNetworkType of Download1", function() {
+  if (typeof id2 == "undefined") {
+    output.value += "> Download1 is not started yet.\n";
+    return;
+  }
+
+  output.value += "> asked to get network type of download1, id:" + id1 + "\n";
+  tizen.download.getNetworkType(id1, networkTypeCallback);
+});
+
+handle("bnnetworktype2", "GetNetworkType of Download2", function() {
+  if (typeof id2 == "undefined") {
+    output.value += "> Download2 is not started yet.\n";
+    return;
+  }
+
+  output.value += "> asked to get network type of download2, id:" + id2 + "\n";
+  tizen.download.getNetworkType(id2, networkTypeCallback);
+});
+
+var mimeCallback = function(mimeType) {
+  output.value += "> received mimeType: " + mimeType + "\n";
+}
+
+handle("bnmimetype1", "GetMIMEType of Download1", function() {
+  if (typeof id1 == "undefined") {
+    output.value += "> Download1 is not started yet.\n";
+    return;
+  }
+
+  output.value += "> asked to get MIME type of download1, id:" + id1 + "\n";
+  tizen.download.getMIMEType(id1, mimeCallback);
+});
+
+handle("bnmimetype2", "GetMIMEType of Download2", function() {
+  if (typeof id2 == "undefined") {
+    output.value += "> Download2 is not started yet.\n";
+    return;
+  }
+
+  output.value += "> asked to get MIME type of download2, id:" + id2 + "\n";
+  tizen.download.getMIMEType(id2, mimeCallback);
 });
 
+handle("bngetrequest1", "Get download request 1", function() {
+  if (typeof id1 == "undefined") {
+    output.value += "> Download1 is not started yet.\n";
+    return;
+  }
+
+  output.value += "> asked to get download request 1, id:" + id1 + "\n";
+  output.value += "> returned request's url is: "+tizen.download.getDownloadRequest(id1).url + "\n";
+});
+
+handle("bngetrequest2", "Get download request 2", function() {
+  if (typeof id2 == "undefined") {
+    output.value += "> Download2 is not started yet.\n";
+    return;
+  }
+
+  output.value += "> asked to get download request 2, id:" + id2 + "\n";
+  output.value += "> returned request's url is: "+tizen.download.getDownloadRequest(id2).url + "\n";
+});
+
+handle("bnhttpheader", "Start Download with specific HTTP header", function() {
+  var req = new tizen.DownloadRequest(url_httpheader); // Test http header
+  req.httpHeader["Pragma"] = "no-cache";
+  req.httpHeader["Cookie"] = "version=1; Skin=new";
+  req.httpHeader["X-Agent"] = "Tizen Sample App";
+
+  output.value += "> asked to start download " + url_httpheader + " with http headers:\n";
+  for (var key in req.httpHeader) {
+    output.value += ">   " + key + ": " + req.httpHeader[key] + "\n";
+  }
+  var id_httpheader = tizen.download.start(req, listener);
+  urls[id_httpheader] = url_httpheader;
+});
+
+
 </script>