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();
#include "common/logger.h"
#include "common/platform_enum.h"
#include "common/platform_exception.h"
+#include "common/scope_exit.h"
namespace extension {
namespace metadata {
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
REGISTER_METHOD(MetadataManagerCreateFileHandle);
REGISTER_METHOD(MetadataFileHandleGet);
+ REGISTER_METHOD(MetadataFileHandleGetArtwork);
REGISTER_METHOD(MetadataFileHandleRelease);
#undef REGISTER_METHOD
}
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");
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);
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();