#include <vector>
#include <string>
#include <map>
-
#include "common/logger.h"
#include "common/assert.h"
public:
ParsedInstance();
virtual ~ParsedInstance();
-
protected:
void RegisterHandler(const std::string& name, const NativeHandler& func);
void RegisterSyncHandler(const std::string& name, const NativeHandler& func);
class ParsedDataInstance : public ParsedInstance {
public:
+ using ParsedInstance::RegisterSyncHandler;
void RegisterHandler(const std::string& name, const NativeDataHandler& func);
void RegisterSyncHandler(const std::string& name, const NativeDataHandler& func);
private:
FilesystemFile::FilesystemFile(const std::string& path_)
: path(path_) {}
-bool FilesystemFile::Read(FilesystemBuffer* data,
+bool FilesystemFile::Read(uint8_t* data_p,
size_t offset,
- size_t length) {
- LoggerD("Enter");
- if (!data) {
- LoggerE("Missing output buffer");
- return false;
+ size_t length,
+ size_t* readed) {
+ LoggerE("entered");
+ size_t temp_read = 0;
+ if (!readed) {
+ readed = &temp_read;
}
-
- data->resize(length);
FILE* file = fopen(path.c_str(), "r");
if (!file) {
LoggerE("Cannot open file %s to read!", path.c_str());
return false;
}
- size_t readed = 0;
- uint8_t* data_p = data->data();
size_t data_size = length;
- while (readed < data->size()) {
- size_t part = fread(data_p, 1, data_size, file);
+ while (*readed < data_size) {
+ size_t part = fread(data_p, 1, length, file);
- readed += part;
+ *readed += part;
data_p += part;
data_size -= part;
- LoggerD("Readed part %li bytes", readed);
+ LoggerD("Readed part %li bytes", *readed);
if (ferror(file)) {
LoggerE("Error during file write!");
break;
}
}
- LoggerD("Readed %li bytes", readed);
- data->resize(readed);
+ LoggerD("Readed %li bytes", *readed);
return true;
}
-bool FilesystemFile::Write(const FilesystemBuffer& data, size_t offset) {
- LoggerD("Enter");
+bool FilesystemFile::Write(uint8_t* data_p, size_t data_size, size_t offset,
+ size_t* written) {
+ LoggerD("Enter %s", path.c_str());
FILE* file = fopen(path.c_str(), "r+");
if (!file) {
LoggerE("Cannot open file %s to write!", path.c_str());
int status;
status = fseek(file, offset, SEEK_SET);
- LoggerD("Offset is %li, writing %i bytes", offset, data.size());
+ LoggerD("Offset is %li, writing %i bytes", offset, data_size);
if (status) {
LoggerE("Cannot perform seek!");
return false;
}
- size_t written = 0;
- uint8_t* data_p = const_cast<uint8_t*>(data.data());
- size_t data_size = data.size();
- while (written < data.size()) {
+ while (*written < data_size) {
size_t part = fwrite(data_p, 1, data_size, file);
if (ferror(file)) {
return false;
}
- written += part;
+ *written += part;
data_p += part;
data_size -= part;
}
LoggerE("Cannot sync file!");
return false;
}
- LoggerD("Written %li bytes", written);
+ LoggerD("Written %li bytes", *written);
return true;
}
+
+
} // namespace filesystem
} // namespace extension
public:
FilesystemFile(const std::string& path_);
- bool Read(FilesystemBuffer* data, size_t offset, size_t length);
- bool Write(const FilesystemBuffer& data, size_t offset);
+ bool Read(u_int8_t* data_p, size_t offset, size_t length,
+ size_t* readed);
+ bool Write(uint8_t* data_p, size_t data_size, size_t offset, size_t* written);
};
} // namespace filesystem
#include "filesystem/filesystem_instance.h"
+#include <glib.h>
#include <functional>
#include "common/picojson.h"
REGISTER_SYNC("File_createSync", FileCreateSync);
REGISTER_ASYNC("File_readDir", ReadDir);
REGISTER_ASYNC("File_rename", FileRename);
- REGISTER_ASYNC("File_read", FileRead);
REGISTER_SYNC("File_readSync", FileReadSync);
- REGISTER_ASYNC("File_write", FileWrite);
REGISTER_SYNC("File_writeSync", FileWriteSync);
REGISTER_SYNC("Filesystem_fetchVirtualRoots", FilesystemFetchVirtualRoots);
REGISTER_SYNC("FileSystemManager_addStorageStateChangeListener",
&FilesystemManager::Rename, &fsm, oldPath, newPath, onSuccess, onError));
}
-void FilesystemInstance::FileRead(const picojson::value& args,
- picojson::object& out) {
+void FilesystemInstance::FileReadSync(const common::ParsedDataRequest& req,
+ common::ParsedDataResponse& res) {
LoggerD("enter");
- CHECK_EXIST(args, "callbackId", out)
+ const picojson::value& args = req.args();
+ picojson::object& out = res.object();
CHECK_EXIST(args, "location", out)
CHECK_EXIST(args, "offset", out)
CHECK_EXIST(args, "length", out)
- double callback_id = args.get("callbackId").get<double>();
const std::string& location = args.get("location").get<std::string>();
size_t offset = static_cast<size_t>(args.get("offset").get<double>());
size_t length = static_cast<size_t>(args.get("length").get<double>());
+ const bool is_base64 = args.get("is_base64").get<bool>();
- auto onSuccess = [this, callback_id](const std::string& data) {
+ auto onSuccess = [this, &out, &length, &res, is_base64](const std::string& data, uint8_t* data_p, size_t readed) {
LoggerD("enter");
- picojson::value response = picojson::value(picojson::object());
- picojson::object& obj = response.get<picojson::object>();
- obj["callbackId"] = picojson::value(callback_id);
- ReportSuccess(picojson::value(data), obj);
- Instance::PostMessage(this, response.serialize().c_str());
- };
-
- auto onError = [this, callback_id](FilesystemError e) {
- LoggerD("enter");
- picojson::value response = picojson::value(picojson::object());
- picojson::object& obj = response.get<picojson::object>();
- obj["callbackId"] = picojson::value(callback_id);
- PrepareError(e, obj);
- Instance::PostMessage(this, response.serialize().c_str());
- };
-
- FilesystemManager& fsm = FilesystemManager::GetInstance();
- common::TaskQueue::GetInstance().Async(std::bind(&FilesystemManager::FileRead,
- &fsm,
- location,
- offset,
- length,
- onSuccess,
- onError));
-}
-
-void FilesystemInstance::FileReadSync(const picojson::value& args,
- picojson::object& out) {
- LoggerD("enter");
- CHECK_EXIST(args, "location", out)
- CHECK_EXIST(args, "offset", out)
- CHECK_EXIST(args, "length", out)
-
- const std::string& location = args.get("location").get<std::string>();
- size_t offset = static_cast<size_t>(args.get("offset").get<double>());
- size_t length = static_cast<size_t>(args.get("length").get<double>());
-
- auto onSuccess = [this, &out](const std::string& data) {
- LoggerD("enter");
- ReportSuccess(picojson::value(data), out);
+ if (data_p) {
+ if (is_base64) {
+ gchar* encoded = g_base64_encode(data_p, length);
+ free(data_p);
+ // encoded will be freeed by runtime.
+ res.SetBuffer(reinterpret_cast<uint8_t*>(encoded), strlen(encoded) + 1);
+ } else {
+ res.SetBuffer(data_p, length);
+ }
+ out["data_size"] = picojson::value(static_cast<double>(readed));
+ ReportSuccess(out);
+ }
};
auto onError = [this, &out](FilesystemError e) {
location, offset, length, onSuccess, onError);
}
-void FilesystemInstance::FileWrite(const picojson::value& args,
- picojson::object& out) {
- LoggerD("enter");
- CHECK_EXIST(args, "callbackId", out)
- CHECK_EXIST(args, "location", out)
- CHECK_EXIST(args, "data", out)
- CHECK_EXIST(args, "offset", out)
-
- double callback_id = args.get("callbackId").get<double>();
- const std::string& location = args.get("location").get<std::string>();
- const std::string& data = args.get("data").get<std::string>();
- size_t offset = static_cast<size_t>(args.get("location").get<double>());
-
- auto onSuccess = [this, callback_id]() {
- LoggerD("enter");
- picojson::value response = picojson::value(picojson::object());
- picojson::object& obj = response.get<picojson::object>();
- obj["callbackId"] = picojson::value(callback_id);
- ReportSuccess(obj);
- Instance::PostMessage(this, response.serialize().c_str());
- };
-
- auto onError = [this, callback_id](FilesystemError e) {
- LoggerD("enter");
- picojson::value response = picojson::value(picojson::object());
- picojson::object& obj = response.get<picojson::object>();
- obj["callbackId"] = picojson::value(callback_id);
- PrepareError(e, obj);
- Instance::PostMessage(this, response.serialize().c_str());
- };
-
- FilesystemManager& fsm = FilesystemManager::GetInstance();
- common::TaskQueue::GetInstance().Async(
- std::bind(&FilesystemManager::FileWrite,
- &fsm,
- location,
- data,
- offset,
- onSuccess,
- onError));
-}
-
-void FilesystemInstance::FileWriteSync(const picojson::value& args,
- picojson::object& out) {
+void FilesystemInstance::FileWriteSync(const common::ParsedDataRequest& req, common::ParsedDataResponse& res) {
LoggerD("enter");
+ const picojson::value& args = req.args();
+ picojson::object& out = res.object();
CHECK_EXIST(args, "location", out)
- CHECK_EXIST(args, "data", out)
CHECK_EXIST(args, "offset", out)
const std::string& location = args.get("location").get<std::string>();
- const std::string& data = args.get("data").get<std::string>();
+ const bool is_base64 = args.get("is_base64").get<bool>();
size_t offset = static_cast<size_t>(args.get("offset").get<double>());
- auto onSuccess = [this, &out]() {
+ auto onSuccess = [this, &out](size_t written) {
LoggerD("enter");
+ out["data_size"] = picojson::value(static_cast<double>(written));
ReportSuccess(out);
};
LoggerD("enter");
PrepareError(e, out);
};
-
- FilesystemManager::GetInstance().FileWrite(
- location, data, offset, onSuccess, onError);
+ uint8_t* data_p = NULL;
+ size_t data_size = 0;
+ if (is_base64) {
+ data_p = g_base64_decode(reinterpret_cast<char*>(req.buffer()),
+ &data_size);
+ } else {
+ data_p = req.buffer();
+ data_size = req.buffer_length();
+ }
+ if (data_size > 0)
+ FilesystemManager::GetInstance().FileWrite(
+ location, data_p, data_size, offset, onSuccess, onError);
+ if (is_base64 && data_p) {
+ free(data_p);
+ }
}
void FilesystemInstance::FileStat(const picojson::value& args,
#include "common/extension.h"
#include "filesystem_utils.h"
+#include <thread>
+#include <mutex>
#include "filesystem_manager.h"
namespace extension {
namespace filesystem {
-class FilesystemInstance : public common::ParsedInstance,
+class FilesystemInstance : public common::ParsedDataInstance,
FilesystemStateChangeListener {
public:
FilesystemInstance();
void FileStat(const picojson::value& args, picojson::object& out);
void FileStatSync(const picojson::value& args, picojson::object& out);
void FileRead(const picojson::value& args, picojson::object& out);
- void FileReadSync(const picojson::value& args, picojson::object& out);
+ void FileReadSync(const common::ParsedDataRequest& req, common::ParsedDataResponse& res);
void FileWrite(const picojson::value& args, picojson::object& out);
- void FileWriteSync(const picojson::value& args, picojson::object& out);
+ void FileWriteSync(const common::ParsedDataRequest& req, common::ParsedDataResponse& res);
void FilesystemFetchVirtualRoots(const picojson::value& args,
picojson::object& out);
void FileSystemManagerFetchStorages(const picojson::value& args,
const std::string& path,
size_t offset,
size_t length,
- const std::function<void(const std::string&)>& success_cb,
+ const std::function<void(const std::string&, uint8_t*, size_t)>& success_cb,
const std::function<void(FilesystemError)>& error_cb) {
LoggerD("enter");
+ uint8_t* data_p = nullptr;
FilesystemFile file(path);
- FilesystemBuffer buffer;
- if (!file.Read(&buffer, offset, length)) {
+ std::string out_data;
+ size_t readed = 0;
+ data_p = (uint8_t*)calloc(1, sizeof(uint8_t) * length + 1);
+ if (!data_p || !file.Read(data_p, offset, length, &readed)) {
LoggerE("Cannot read file %s", path.c_str());
error_cb(FilesystemError::Other);
return;
}
-
- std::string out_data = buffer.EncodeData();
- success_cb(out_data);
+ success_cb(out_data, data_p, readed);
}
-void FilesystemManager::FileWrite(
- const std::string& path,
- const std::string& data,
- size_t offset,
- const std::function<void()>& success_cb,
- const std::function<void(FilesystemError)>& error_cb) {
-
+void FilesystemManager::FileWrite(const std::string& path,
+ uint8_t* data_p,
+ size_t data_size,
+ size_t offset,
+ const std::function<void(size_t written)>& success_cb,
+ const std::function<void(FilesystemError)>& error_cb) {
LoggerD("enter");
FilesystemFile file(path);
- FilesystemBuffer buffer;
- // Decode buffer data
- if (!buffer.DecodeData(data)) {
- LoggerE("Cannot decode file data!");
- error_cb(FilesystemError::Other);
- return;
- }
-
- if (file.Write(buffer, offset)) {
- success_cb();
+ size_t written = 0;
+ if (file.Write(data_p, data_size, offset, &written)) {
+ success_cb(written);
} else {
LoggerE("Cannot write to file %s!", path.c_str());
error_cb(FilesystemError::Other);
void FileRead(const std::string& path,
size_t offset,
size_t length,
- const std::function<void(const std::string&)>& success_cb,
+ const std::function<void(const std::string&, uint8_t*, size_t)>& success_cb,
const std::function<void(FilesystemError)>& error_cb);
void FileWrite(const std::string& path,
- const std::string& data,
+ uint8_t* data_p,
+ size_t data_size,
size_t offset,
- const std::function<void()>& success_cb,
+ const std::function<void(size_t data_size)>& success_cb,
const std::function<void(FilesystemError)>& error_cb);
void CopyTo(const std::string& originFilePath,
location: commonFS_.toRealPath(this.fullPath),
offset: 0,
length: 1024,
- encoding: args.encoding
+ encoding: args.encoding,
+ is_base64: false
};
function readFile() {
var result, encoded, str = '';
do {
- result = native_.callSync('File_readSync', data);
+ result = native_.callSyncData('File_readSync', data);
if (native_.isFailure(result)) {
setTimeout(function() {
native_.callIfPossible(args.onerror, native_.getErrorObject(result));
}, 0);
return;
}
- encoded = native_.getResultObject(result);
- if (encoded.length) {
- str += Base64.decode(encoded);
- data.offset += data.length;
- }
- } while (encoded.length);
+ str += result.output;
+ data.offset += result.data_size;
+ } while (result.data_size);
setTimeout(function() {
native_.callIfPossible(args.onsuccess, str);
var data = {
location: commonFS_.toRealPath(this._file.fullPath),
offset: this.position || 0,
- length: args.charCount > _count ? _count : args.charCount
+ length: args.charCount > _count ? _count : args.charCount,
+ is_base64: false,
};
- var result = native_.callSync('File_readSync', data);
- if (native_.isFailure(result)) {
+ var result = native_.callSyncData('File_readSync', data);
+ if (native_.isFailure(result.reply)) {
throw new WebAPIException(WebAPIException.IO_ERR, 'Could not read');
}
- var encoded = native_.getResultObject(result);
- var decoded = Base64.decode(encoded);
+ this.position = this.position + result.reply.data_size;
- return decoded;
+ return result.output;
};
FileStream.prototype.readBytes = function() {
var data = {
location: commonFS_.toRealPath(this._file.fullPath),
offset: this.position || 0,
- length: args.byteCount > _count ? _count : args.byteCount
+ length: args.byteCount > _count ? _count : args.byteCount,
+ is_base64: false,
};
- var result = native_.callSync('File_readSync', data);
- if (native_.isFailure(result)) {
+ var result = native_.callSyncData('File_readSync', data, "octet");
+ if (native_.isFailure(result.reply)) {
throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Could not read');
}
- var encoded = native_.getResultObject(result);
- var decoded = Base64.decode(encoded);
var bytes = [];
-
- for (var i = 0; i < decoded.length; ++i) {
- bytes.push(decoded.charCodeAt(i));
+ for (var i = 0; i < result.output.length; ++i) {
+ bytes.push(result.output.charCodeAt(i));
}
+ this.position = this.position + result.reply.data_size;
return bytes;
};
var data = {
location: commonFS_.toRealPath(this._file.fullPath),
offset: this.position || 0,
- length: args.byteCount > _count ? _count : args.byteCount
+ length: args.byteCount > _count ? _count : args.byteCount,
+ is_base64: true
};
- var result = native_.callSync('File_readSync', data);
- if (native_.isFailure(result)) {
+ var result = native_.callSyncData('File_readSync', data);
+ if (native_.isFailure(result.reply)) {
throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Could not read');
}
- var encoded = native_.getResultObject(result);
+ this.position = this.position + result.reply.data_size;
- return encoded;
+ return result.output;
};
FileStream.prototype.write = function() {
_checkClosed(this);
_checkWriteAccess(this._mode);
-
if (!arguments.length) {
throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
'Argument "stringData" missing');
var data = {
location: commonFS_.toRealPath(this._file.fullPath),
offset: this.position,
- data: Base64.encode(args.stringData)
+ length: args.stringData.length,
+ is_base64: false,
};
-
- var result = native_.callSync('File_writeSync', data);
-
- if (native_.isFailure(result)) {
+ var result = native_.callSyncData('File_writeSync', data, "string", args.stringData);
+ if (native_.isFailure(result.reply)) {
throw new WebAPIException(WebAPIException.IO_ERR, 'Could not write');
}
- this.position = args.stringData.length;
+ this.position = this.position + result.reply.data_size;
};
FileStream.prototype.writeBytes = function() {
var args = validator_.validateArgs(arguments, [
{
name: 'byteData',
- type: types_.ARRAY,
- values: types_.OCTET
+ type: types_.ARRAY
}
]);
-
_checkClosed(this);
_checkWriteAccess(this._mode);
-
if (!arguments.length) {
throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
'Argument "byteData" missing');
var data = {
location: commonFS_.toRealPath(this._file.fullPath),
offset: this.position,
- data: Base64.encode(String.fromCharCode.apply(String, args.byteData))
+ length: args.byteData.length,
+ is_base64: false,
};
- var result = native_.callSync('File_writeSync', data);
+ var result = native_.callSyncData('File_writeSync', data, "octet", args.byteData);
- if (native_.isFailure(result)) {
+ if (native_.isFailure(result.reply)) {
throw new WebAPIException(WebAPIException.IO_ERR, 'Could not write');
}
+ this.position = this.position + result.reply.data_size;
+
};
function _isBase64(str) {
var data = {
location: commonFS_.toRealPath(this._file.fullPath),
offset: this.position,
- data: args.base64Data
+ is_base64: true
};
- var result = native_.callSync('File_writeSync', data);
+ var result = native_.callSyncData('File_writeSync', data, "string", args.base64Data);
if (native_.isFailure(result)) {
throw new WebAPIException(WebAPIException.IO_ERR, 'Could not write');
}
+ this.position = this.position + result.reply.data_size;
};
!_type.isFunction(extension.postMessage) ||
!_type.isFunction(extension.internal.sendSyncMessage) ||
!_type.isFunction(extension.sendSyncData) ||
- !_type.isFunction(extension.setDataListener) ||
!_type.isFunction(extension.sendRuntimeMessage) ||
!_type.isFunction(extension.sendRuntimeAsyncMessage) ||
!_type.isFunction(extension.sendRuntimeSyncMessage) ||
console.error('Missing callback or listener identifier. Ignoring message.');
}.bind(this));
-
- extension_.setDataListener(function(msg, chunk_id) {
- var msg = JSON.parse(msg);
- msg.chunk_id = chunk_id;
- var id;
-
- if (msg.hasOwnProperty(this.CALLBACK_ID_KEY)) {
- id = msg[this.CALLBACK_ID_KEY];
- delete msg[this.CALLBACK_ID_KEY];
-
- if (!_type.isFunction(this.callbacks_[id])) {
- console.error('Wrong callback identifier. Ignoring message.');
- return;
- }
-
- this.callbacks_[id](msg);
- delete this.callbacks_[id];
-
- return;
- }
-
- if (msg.hasOwnProperty(this.LISTENER_ID_KEY)) {
- id = msg[this.LISTENER_ID_KEY];
- delete msg[this.LISTENER_ID_KEY];
-
- if (!_type.isFunction(this.listeners_[id])) {
- console.error('Wrong listener identifier. Ignoring message.');
- return;
- }
-
- this.listeners_[id](msg);
-
- return;
- }
-
- console.error('Missing callback or listener identifier. Ignoring message.');
-
- }.bind(this));
};
NativeManager.prototype.call = function(cmd, args, callback) {
return JSON.parse(this.extension.internal.sendSyncMessage(request));
};
-NativeManager.prototype.callSyncData = function(cmd, args, chunk) {
+NativeManager.prototype.callSyncData = function(cmd, args, type, chunk) {
+ if (!type) type = "string";
var request = JSON.stringify({
cmd: cmd,
args: args || {}
});
var response = this.extension.sendSyncData(request, chunk);
response.reply = JSON.parse(response.reply);
+ response.output = this.extension.receiveChunkData(response.chunk_id, "string");
return response;
};