[Metadata] Added getArtwork method of MetadataFileHandle 64/245064/6
authorPiotr Kosko <p.kosko@samsung.com>
Wed, 30 Sep 2020 06:23:20 +0000 (08:23 +0200)
committerPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Tue, 24 Nov 2020 07:56:37 +0000 (08:56 +0100)
[ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-271

[Verification]
Code compiles without errors.
Checked in chrome console with below code.
Precondition: sample.mp3 with artwork need to be pushed on device

// test artwork
var path = "videos/sample.mp3";
function showBlob(bbb) {
    var elem = document.getElementById("blobImage") || document.createElement("img");
    elem.setAttribute("id", "blobImage");
    elem.setAttribute("height", "240");
    elem.setAttribute("width", "240");
    elem.setAttribute("alt", "invalid blob");
    document.getElementById("test").appendChild(elem)

    var objectURL = URL.createObjectURL(bbb);
    elem.src = objectURL;
}
var fileHandle = tizen.metadata.createFileHandle(path);
var artwork = fileHandle.getArtwork();
console.log(artwork);
showBlob(artwork)

Change-Id: Ia0cbe5ade542ad71224a91c0c1a4618072b5538e

src/metadata/metadata_api.js
src/metadata/metadata_file_handle.cc
src/metadata/metadata_file_handle.h
src/metadata/metadata_instance.cc
src/metadata/metadata_instance.h

index fc3897b..66a1fa6 100755 (executable)
@@ -125,5 +125,38 @@ MetadataFileHandle.prototype.release = function() {
     return native_.getResultObject(result);
 };
 
+// below section copied from filesystem
+// TODO move this to utils?
+/*
+ * Create new array-like object of numbers: UTF-16 char codes from string.
+ * As type pass Array, Uint8Array, etc.
+ * Useful for passing data through crosswalk.
+ */
+function StringToArray(str, type) {
+    var len = str.length;
+    var output = new type(len);
+    for (var i = 0; i < len; i++) {
+        output[i] = str.charCodeAt(i);
+    }
+    return output;
+}
+////////////////////////////////////////////////////
+
+MetadataFileHandle.prototype.getArtwork = function() {
+    var data = {
+        uri: this.uri,
+        id: this._id
+    };
+
+    var result = native_.callSync('MetadataFileHandleGetArtwork', data);
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+    var resultData = native_.getResultObject(result);
+    var encodedData = StringToArray(resultData.encodedData, Uint8Array);
+
+    return new Blob([encodedData], { type: resultData.mimeType });
+};
+
 // Exports
 exports = new MetadataManager();
index 5f9dba9..1e40e4e 100644 (file)
@@ -19,6 +19,7 @@
 #include "common/logger.h"
 #include "common/platform_enum.h"
 #include "common/platform_exception.h"
+#include "common/scope_exit.h"
 
 namespace extension {
 namespace metadata {
@@ -191,5 +192,34 @@ PlatformResult MetadataFileHandle::Get(const std::string& type, std::string* res
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+PlatformResult MetadataFileHandle::GetArtwork(std::vector<std::uint8_t>* artwork_array,
+                                              std::string* mime_type_str) {
+  ScopeLogger();
+  int size = 0;
+  void* artwork = nullptr;
+  char* mime_type = nullptr;
+  SCOPE_EXIT {
+    free(artwork);
+    free(mime_type);
+  };
+
+  int native_res = metadata_extractor_get_artwork(handle_, &artwork, &size, &mime_type);
+  if (METADATA_EXTRACTOR_ERROR_NONE != native_res) {
+    LoggerE("Error during getting metadata: %d", native_res);
+    return convertErrorCode(native_res);
+  }
+  LoggerD("Artwork size %d", size);
+
+  // convert artwork to vector
+  std::uint8_t* uint8_artwork = (std::uint8_t*)artwork;
+  std::vector<std::uint8_t> out_buf(uint8_artwork, uint8_artwork + size);
+
+  // set results
+  *artwork_array = std::move(out_buf);
+  *mime_type_str = mime_type ? mime_type : "";
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // namespace metadata
 }  // namespace extension
index bb16e18..67d31c5 100644 (file)
@@ -38,6 +38,8 @@ class MetadataFileHandle {
   common::PlatformResult Initialize(const std::string& uri);
   common::PlatformResult Get(const std::string& type, std::string* result);
 
+  common::PlatformResult GetArtwork(std::vector<std::uint8_t>* data, std::string* mime_type);
+
  private:
   metadata_extractor_h handle_;
   int id_;
index 5a90e2e..5e1db6b 100644 (file)
@@ -34,6 +34,7 @@ MetadataInstance::MetadataInstance() : next_handle_id_(1) {
 
   REGISTER_METHOD(MetadataManagerCreateFileHandle);
   REGISTER_METHOD(MetadataFileHandleGet);
+  REGISTER_METHOD(MetadataFileHandleGetArtwork);
   REGISTER_METHOD(MetadataFileHandleRelease);
 #undef REGISTER_METHOD
 }
@@ -58,16 +59,8 @@ void MetadataInstance::MetadataManagerCreateFileHandle(const picojson::value& ar
   handles_map_.insert(std::pair<int, MetadataFileHandle>(next_handle_id_++, std::move(m)));
 }
 
-void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojson::object& out) {
+PlatformResult MetadataInstance::InitializeHandleIfNeeded(const std::string& uri, const int id) {
   ScopeLogger();
-  const std::string& uri = args.get("uri").get<std::string>();
-  const int id = static_cast<int>(args.get("id").get<double>());
-  const std::string& type = args.get("type").get<std::string>();
-
-  LoggerD("File: %s getting metadata type: %s", uri.c_str(), type.c_str());
-
-  std::string value;
-
   auto it = handles_map_.find(id);
   if (handles_map_.end() == it) {
     LoggerD("Handle does not exist in map, creating new one");
@@ -77,13 +70,29 @@ void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojs
     if (!res) {
       // if everything works fine with a file, handle should be created successfully, as this is a
       // re-creation. In case of errors, just return an AbortError
-      LogAndReportError(
-          PlatformResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file."), &out);
-      return;
+      return LogAndCreateResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file.");
     }
     // store it in the map
     handles_map_.insert(std::pair<int, MetadataFileHandle>(id, std::move(m)));
   }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  const std::string& uri = args.get("uri").get<std::string>();
+  const int id = static_cast<int>(args.get("id").get<double>());
+  const std::string& type = args.get("type").get<std::string>();
+
+  LoggerD("File: %s getting metadata type: %s", uri.c_str(), type.c_str());
+
+  std::string value;
+
+  auto res = InitializeHandleIfNeeded(uri, id);
+  if (!res) {
+    LogAndReportError(res, &out);
+    return;
+  }
 
   try {
     MetadataFileHandle& m = handles_map_.at(id);
@@ -102,6 +111,63 @@ void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojs
   ReportSuccess(picojson::value(value), out);
 }
 
+// TODO copied from filesystem
+// move to common??
+/* Write to str buf bytes as if they were UTF-8 codepoints */
+static void encode_binary_in_string(const std::vector<std::uint8_t>& buf, std::string& str) {
+  ScopeLogger();
+  str.reserve(str.size() + buf.size());
+
+  for (std::uint8_t byte : buf) {
+    if (byte < 128) {
+      str += byte;
+      continue;
+    }
+    str += 0xC0 | (byte >> 6);
+    str += 0x80 | (byte & 0x3F);
+  }
+}
+///////////////////////////////////
+
+void MetadataInstance::MetadataFileHandleGetArtwork(const picojson::value& args,
+                                                    picojson::object& out) {
+  ScopeLogger();
+  const std::string& uri = args.get("uri").get<std::string>();
+  const int id = static_cast<int>(args.get("id").get<double>());
+
+  auto res = InitializeHandleIfNeeded(uri, id);
+  if (!res) {
+    LogAndReportError(res, &out);
+    return;
+  }
+
+  std::vector<std::uint8_t> data;
+  std::string mime_type;
+  try {
+    MetadataFileHandle& m = handles_map_.at(id);
+
+    auto res = m.GetArtwork(&data, &mime_type);
+    if (!res) {
+      LogAndReportError(res, &out);
+      return;
+    }
+  } catch (...) {
+    // this should never happen
+    LogAndReportError(
+        PlatformResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file."), &out);
+    return;
+  }
+
+  picojson::value result_artwork = picojson::value(picojson::object());
+  picojson::object& result_artwork_obj = result_artwork.get<picojson::object>();
+
+  result_artwork_obj["encodedData"] = picojson::value(picojson::string_type, true);
+  encode_binary_in_string(data, result_artwork_obj["encodedData"].get<std::string>());
+  result_artwork_obj["mimeType"] = picojson::value(mime_type);
+
+  ReportSuccess(result_artwork, out);
+}
+
 void MetadataInstance::MetadataFileHandleRelease(const picojson::value& args,
                                                  picojson::object& out) {
   ScopeLogger();
index 694dbc1..68eeddc 100644 (file)
@@ -30,7 +30,9 @@ class MetadataInstance : public common::ParsedInstance {
 
  private:
   void MetadataManagerCreateFileHandle(const picojson::value& args, picojson::object& out);
+  common::PlatformResult InitializeHandleIfNeeded(const std::string& uri, const int id);
   void MetadataFileHandleGet(const picojson::value& args, picojson::object& out);
+  void MetadataFileHandleGetArtwork(const picojson::value& args, picojson::object& out);
   void MetadataFileHandleRelease(const picojson::value& args, picojson::object& out);
 
   std::map<int, MetadataFileHandle> handles_map_;