diff --git a/client/src/bindings/WebView.cpp b/client/src/bindings/WebView.cpp index d59b4744c..86b3521ac 100644 --- a/client/src/bindings/WebView.cpp +++ b/client/src/bindings/WebView.cpp @@ -124,69 +124,209 @@ static void Constructor(const v8::FunctionCallbackInfo& info) V8_CHECK_CONSTRUCTOR(); V8_CHECK_ARGS_LEN_MIN_MAX(1, 4); - V8_ARG_TO_STRING(1, url); - alt::IResource* altres = V8ResourceImpl::GetResource(isolate->GetEnteredOrMicrotaskContext()); V8_CHECK(altres, "invalid resource"); alt::IWebView* view = nullptr; - if(info.Length() == 4) + if (info.Length() == 1 && info[0]->IsObject()) { - V8_ARG_TO_BOOLEAN(2, isOverlayBool); - V8_ARG_TO_OBJECT(3, pos); - V8_ARG_TO_OBJECT(4, size); - - V8_OBJECT_GET_INT(pos, "x", posX); - V8_OBJECT_GET_INT(pos, "y", posY); + V8_ARG_TO_OBJECT(1, params); + using values_t = std::unordered_map>; + std::optional values = V8Helpers::CppValue>(params); + V8_CHECK(values.has_value(), "Params are empty"); + V8_CHECK(!values->empty(), "Params are empty"); + + alt::WebViewHeaders headers; + std::vector cookies; + int posX = 0; + int posY = 0; + int sizeX = 0; + int sizeY = 0; + int drawableHash = 0; + std::string targetTextureStr; + bool isOverlay = false; + bool onTextureView = false; + V8_TO_STRING(values->at("url"), url); + + if (values->contains("pos")) + { + V8_TO_OBJECT(values->at("pos"), pos); + V8_OBJECT_GET_INT(pos, "x", v8posX); + V8_OBJECT_GET_INT(pos, "y", v8posY); + posX = v8posX; + posY = v8posY; + } + if (values->contains("size")) + { + V8_TO_OBJECT(values->at("size"), size); + V8_OBJECT_GET_INT(size, "x", v8sizeX); + V8_OBJECT_GET_INT(size, "y", v8sizeY); + sizeX = v8sizeX; + sizeY = v8sizeY; + } + if (values->contains("isOverlay")) + { + V8_TO_BOOLEAN(values->at("isOverlay"), v8isOverlay); + isOverlay = v8isOverlay; + } + if (values->contains("drawableHash")) + { + V8_CHECK(values->contains("targetTexture"), "targetTexture should be specified for drawableHash"); + V8_TO_INTEGER(values->at("drawableHash"), v8drawableHash); + drawableHash = v8drawableHash; + onTextureView = true; + } + if (values->contains("targetTexture")) + { + V8_CHECK(values->contains("drawableHash"), "drawableHash should be specified for targetTexture"); + V8_TO_STRING(values->at("targetTexture"), v8targetTexture); + targetTextureStr = v8targetTexture; + } + if (values->contains("headers")) + { + V8_TO_OBJECT(values->at("headers"), v8headers); + auto headers_opt = V8Helpers::CppValue(v8headers); + V8_CHECK(headers_opt.has_value(), "headers object is empty"); + headers = std::move(headers_opt).value(); + } + if (values->contains("cookies")) + { + V8_TO_ARRAY(values->at("cookies"), v8cookies); + auto cookies_opt = V8Helpers::CppValue>(v8cookies); + V8_CHECK(cookies_opt.has_value(), "cookies array is empty"); + for (auto& cookie: cookies_opt.value()) + { + + V8_TO_OBJECT(cookie, v8cookie); + auto cookie_opt = V8Helpers::CppValue>(v8cookie); + V8_CHECK(cookie_opt.has_value(), "cookie object is empty"); + + V8_OBJECT_GET_STRING(v8cookie, "url", cookie_url); + V8_OBJECT_GET_STRING(v8cookie, "name", cookie_name); + V8_OBJECT_GET_STRING(v8cookie, "value", cookie_value); + + V8_CHECK(cookie_name.find("__altv_") == 0, "Cookie name should start with '__altv_'"); + WebViewCookie new_cookie {}; + new_cookie.url = std::move(cookie_url); + new_cookie.name = std::move(cookie_name); + new_cookie.value = std::move(cookie_value); + if (cookie_opt->contains("httpOnly")) + { + V8_TO_BOOLEAN(cookie_opt->at("httpOnly"), v8http_only); + new_cookie.httpOnly = v8http_only; + } + if (cookie_opt->contains("secure")) + { + V8_TO_BOOLEAN(cookie_opt->at("secure"), v8secure); + new_cookie.secure = v8secure; + } + if (cookie_opt->contains("domain")) + { + V8_TO_STRING(cookie_opt->at("domain"), v8domain); + new_cookie.domain = std::move(v8domain); + } + if (cookie_opt->contains("path")) + { + V8_TO_STRING(cookie_opt->at("path"), v8path); + new_cookie.path = std::move(v8path); + } + if (cookie_opt->contains("sameSite")) + { + V8_TO_STRING(cookie_opt->at("sameSite"), v8same_site); + V8_CHECK(v8same_site == "NO_RESTRICTION" || v8same_site == "LAX_MODE" || v8same_site == "STRICT_MODE", + "sameSite value should be one of ['NO_RESTRICTION', 'LAX_MODE', 'STRICT_MODE']"); + new_cookie.sameSite = std::move(v8same_site); + } + if (cookie_opt->contains("priority")) + { + V8_TO_STRING(cookie_opt->at("priority"), v8priority); + V8_CHECK(v8priority == "LOW" || v8priority == "MEDIUM" || v8priority == "HIGH", "priority value should be one of ['LOW', 'MEDIUM', 'HIGH']"); + new_cookie.priority = std::move(v8priority); + } + if (cookie_opt->contains("expires")) + { + V8_TO_INTEGER(cookie_opt->at("expires"), v8expires); + new_cookie.expires = v8expires; + } + + V8_CHECK(!(new_cookie.httpOnly && new_cookie.secure), "HTTP only and secure cannot be combined"); + + cookies.emplace_back(std::move(new_cookie)); + } + } - V8_OBJECT_GET_INT(size, "x", sizeX); - V8_OBJECT_GET_INT(size, "y", sizeY); + if (onTextureView) + { + auto texture = alt::ICore::Instance().GetTextureFromDrawable(drawableHash, targetTextureStr); + V8_CHECK(texture != nullptr, "Texture not found"); - view = alt::ICore::Instance().CreateWebView(url, { posX, posY }, { sizeX, sizeY }, true, isOverlayBool, altres); - } - else if(info.Length() == 3 && info[2]->IsObject()) + view = alt::ICore::Instance().CreateWebView(url, (uint32_t)drawableHash, targetTextureStr, altres, headers, cookies); + V8_CHECK(view, "Interactive WebView cannot be created"); + } else + { + view = alt::ICore::Instance().CreateWebView(url, { posX, posY }, { sizeX, sizeY }, true, isOverlay, altres, headers, cookies); + } + } else { - V8_ARG_TO_OBJECT(2, pos); - V8_ARG_TO_OBJECT(3, size); + V8_ARG_TO_STRING(1, url); + if(info.Length() == 4) + { + V8_ARG_TO_BOOLEAN(2, isOverlayBool); + V8_ARG_TO_OBJECT(3, pos); + V8_ARG_TO_OBJECT(4, size); - V8_OBJECT_GET_INT(pos, "x", posX); - V8_OBJECT_GET_INT(pos, "y", posY); + V8_OBJECT_GET_INT(pos, "x", posX); + V8_OBJECT_GET_INT(pos, "y", posY); - V8_OBJECT_GET_INT(size, "x", sizeX); - V8_OBJECT_GET_INT(size, "y", sizeY); + V8_OBJECT_GET_INT(size, "x", sizeX); + V8_OBJECT_GET_INT(size, "y", sizeY); - view = alt::ICore::Instance().CreateWebView(url, { posX, posY }, { sizeX, sizeY }, true, false, altres); - } - else if(info.Length() == 3) - { - V8_ARG_TO_INT(2, drawableHash); - V8_ARG_TO_STRING(3, targetTextureStr); + view = alt::ICore::Instance().CreateWebView(url, { posX, posY }, { sizeX, sizeY }, true, isOverlayBool, altres); + } + else if(info.Length() == 3 && info[2]->IsObject()) + { + V8_ARG_TO_OBJECT(2, pos); + V8_ARG_TO_OBJECT(3, size); - auto texture = alt::ICore::Instance().GetTextureFromDrawable(drawableHash, targetTextureStr); - V8_CHECK(texture != nullptr, "Texture not found"); + V8_OBJECT_GET_INT(pos, "x", posX); + V8_OBJECT_GET_INT(pos, "y", posY); - view = alt::ICore::Instance().CreateWebView(url, (uint32_t)drawableHash, targetTextureStr, altres); - V8_CHECK(view, "Interactive WebView cannot be created"); - } - else if(info.Length() == 2 && info[1]->IsObject()) - { - V8_ARG_TO_OBJECT(2, pos); + V8_OBJECT_GET_INT(size, "x", sizeX); + V8_OBJECT_GET_INT(size, "y", sizeY); - V8_OBJECT_GET_INT(pos, "x", posX); - V8_OBJECT_GET_INT(pos, "y", posY); + view = alt::ICore::Instance().CreateWebView(url, { posX, posY }, { sizeX, sizeY }, true, false, altres); + } + else if(info.Length() == 3) + { + V8_ARG_TO_INT(2, drawableHash); + V8_ARG_TO_STRING(3, targetTextureStr); - view = alt::ICore::Instance().CreateWebView(url, { posX, posY }, { 0, 0 }, true, false, altres); - } - else if(info.Length() == 2) - { - V8_ARG_TO_BOOLEAN(2, isOverlayBool); + auto texture = alt::ICore::Instance().GetTextureFromDrawable(drawableHash, targetTextureStr); + V8_CHECK(texture != nullptr, "Texture not found"); - view = alt::ICore::Instance().CreateWebView(url, { 0, 0 }, { 0, 0 }, true, isOverlayBool, altres); - } - else - { - view = alt::ICore::Instance().CreateWebView(url, { 0, 0 }, { 0, 0 }, true, false, altres); + view = alt::ICore::Instance().CreateWebView(url, (uint32_t)drawableHash, targetTextureStr, altres); + V8_CHECK(view, "Interactive WebView cannot be created"); + } + else if(info.Length() == 2 && info[1]->IsObject()) + { + V8_ARG_TO_OBJECT(2, pos); + + V8_OBJECT_GET_INT(pos, "x", posX); + V8_OBJECT_GET_INT(pos, "y", posY); + + view = alt::ICore::Instance().CreateWebView(url, { posX, posY }, { 0, 0 }, true, false, altres); + } + else if(info.Length() == 2) + { + V8_ARG_TO_BOOLEAN(2, isOverlayBool); + + view = alt::ICore::Instance().CreateWebView(url, { 0, 0 }, { 0, 0 }, true, isOverlayBool, altres); + } + else + { + view = alt::ICore::Instance().CreateWebView(url, { 0, 0 }, { 0, 0 }, true, false, altres); + } } V8_BIND_BASE_OBJECT(view, "Failed to create WebView"); @@ -205,6 +345,68 @@ static void SetExtraHeader(const v8::FunctionCallbackInfo& info) view->SetExtraHeader(name, value); } +static void SetCookie(const v8::FunctionCallbackInfo& info) +{ + V8_GET_ISOLATE_CONTEXT(); + + V8_GET_THIS_BASE_OBJECT(view, alt::IWebView); + + V8_CHECK_ARGS_LEN(1); + V8_ARG_TO_OBJECT(1, cookie); + + auto cookie_opt = V8Helpers::CppValue>(cookie); + V8_CHECK(cookie_opt.has_value(), "cookie object is empty"); + + V8_OBJECT_GET_STRING(cookie, "url", cookie_url); + V8_OBJECT_GET_STRING(cookie, "name", cookie_name); + V8_OBJECT_GET_STRING(cookie, "value", cookie_value); + + V8_CHECK(cookie_name.find("__altv_") == 0, "Cookie name should start with '__altv_'"); + WebViewCookie new_cookie {}; + new_cookie.url = std::move(cookie_url); + new_cookie.name = std::move(cookie_name); + new_cookie.value = std::move(cookie_value); + if (cookie_opt->contains("httpOnly")) + { + V8_TO_BOOLEAN(cookie_opt->at("httpOnly"), v8http_only); + new_cookie.httpOnly = v8http_only; + } + if (cookie_opt->contains("secure")) + { + V8_TO_BOOLEAN(cookie_opt->at("secure"), v8secure); + new_cookie.secure = v8secure; + } + if (cookie_opt->contains("domain")) + { + V8_TO_STRING(cookie_opt->at("domain"), v8domain); + new_cookie.domain = std::move(v8domain); + } + if (cookie_opt->contains("path")) + { + V8_TO_STRING(cookie_opt->at("path"), v8path); + new_cookie.path = std::move(v8path); + } + if (cookie_opt->contains("sameSite")) + { + V8_TO_STRING(cookie_opt->at("sameSite"), v8same_site); + new_cookie.sameSite = std::move(v8same_site); + } + if (cookie_opt->contains("priority")) + { + V8_TO_STRING(cookie_opt->at("priority"), v8priority); + new_cookie.priority = std::move(v8priority); + } + if (cookie_opt->contains("expires")) + { + V8_TO_INTEGER(cookie_opt->at("expires"), v8expires); + new_cookie.expires = v8expires; + } + + V8_CHECK(!(new_cookie.httpOnly && new_cookie.secure), "HTTP only and secure cannot be combined"); + + view->SetCookie(new_cookie); +} + static void SetZoomLevel(const v8::FunctionCallbackInfo& info) { V8_GET_ISOLATE_CONTEXT(); @@ -345,6 +547,7 @@ extern V8Class v8WebView("WebView", V8Helpers::SetMethod(isolate, tpl, "unfocus"); V8Helpers::SetMethod(isolate, tpl, "setExtraHeader", &SetExtraHeader); + V8Helpers::SetMethod(isolate, tpl, "setCookie", &SetCookie); V8Helpers::SetMethod(isolate, tpl, "setZoomLevel", &SetZoomLevel); V8Helpers::SetMethod(isolate, tpl, "reload", &Reload); diff --git a/shared/deps/cpp-sdk b/shared/deps/cpp-sdk index f18e52bbb..30b5e35ab 160000 --- a/shared/deps/cpp-sdk +++ b/shared/deps/cpp-sdk @@ -1 +1 @@ -Subproject commit f18e52bbb7fd9cc57efa66f6c40449b41cdc13a0 +Subproject commit 30b5e35ab7081f7e8ff7ac2bc0568aa7cf38e6be diff --git a/shared/helpers/Macros.h b/shared/helpers/Macros.h index 68d21e3e2..2f67a2d3a 100644 --- a/shared/helpers/Macros.h +++ b/shared/helpers/Macros.h @@ -126,6 +126,10 @@ v8::Local val; \ V8_CHECK(V8Helpers::SafeToObject((v8Val), ctx, val), "Failed to convert value to object") +#define V8_TO_ARRAY(v8Val, val) \ + v8::Local val; \ + V8_CHECK(V8Helpers::SafeToArray((v8Val), ctx, val), "Failed to convert value to array") + #define V8_TO_VECTOR3(v8Val, val) \ alt::Vector3f val; \ V8_CHECK(V8Helpers::SafeToVector3((v8Val), ctx, val), "Failed to convert value to Vector3")