#include "fchost_storage_js.h" #include <memory> // static storage objects (not threadsafe, probably doesn't matter, since they'll execute within a JS context) static std::unique_ptr<FCHostPersistentStorage> persist; static std::unique_ptr<FCHostSessionStorage> session; // storage handler js hook implementations #define REGJSFUNC(x) { \ CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(x, handler); \ object->SetValue(x, func, V8_PROPERTY_ATTRIBUTE_NONE); } static void AttachStorageFunctions(CefRefPtr<CefV8Value> object, CefRefPtr<CefV8Handler> handler) { REGJSFUNC("size"); REGJSFUNC("keys"); REGJSFUNC("has"); REGJSFUNC("get"); REGJSFUNC("set"); REGJSFUNC("remove"); REGJSFUNC("clear"); } void FCHostStorageRegister(const std::filesystem::path& persistPath, CefRefPtr<CefV8Value> object) { // New context, reset everything (don't try to run more than one app at once!) if (persist) persist.reset(NULL); if (session) session.reset(NULL); persist = std::make_unique<FCHostPersistentStorage>(persistPath); session = std::make_unique<FCHostSessionStorage>(); CefRefPtr<CefV8Handler> sess_handler = new FCHostStorageHandler(false); CefRefPtr<CefV8Value> obj_sess = CefV8Value::CreateObject(nullptr, nullptr); object->SetValue("FCHostSession", obj_sess, V8_PROPERTY_ATTRIBUTE_NONE); AttachStorageFunctions(obj_sess, sess_handler); CefRefPtr<CefV8Handler> pers_handler = new FCHostStorageHandler(true); CefRefPtr<CefV8Value> obj_pers = CefV8Value::CreateObject(nullptr, nullptr); object->SetValue("FCHostPersistent", obj_pers, V8_PROPERTY_ATTRIBUTE_NONE); AttachStorageFunctions(obj_pers, pers_handler); } // individual execution objects for session/persistent storage bool FCHostStorageHandler::Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) { // alias pointer only, no ownership FCHostSessionStorage* storage = persistent ? persist.get() : session.get(); if (name == "size") { // no arguments retval = CefV8Value::CreateInt(static_cast<int32>(storage->size())); return true; } else if (name == "keys") { // no arguments retval = storage->keys(); return true; } else if (name == "has") { // one string argument if (arguments.size() < 1 || !arguments[0]->IsString()) return false; retval = CefV8Value::CreateBool(storage->has(arguments[0]->GetStringValue())); return true; } else if (name == "get") { // one string argument if (arguments.size() < 1 || !arguments[0]->IsString()) return false; retval = storage->get(arguments[0]->GetStringValue()); return true; } else if (name == "set") { // two arguments - one string, one "whatever" if (arguments.size() < 2 || !arguments[0]->IsString()) return false; storage->set(arguments[0]->GetStringValue(), arguments[1]); retval = CefV8Value::CreateBool(true); return true; } else if (name == "remove") { // one string argument if (arguments.size() < 1 || !arguments[0]->IsString()) return false; retval = CefV8Value::CreateBool(storage->remove(arguments[0]->GetStringValue())); return true; } else if (name == "clear") { // no arguments storage->clear(); return true; } return false; }