Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Plugin settings rendering #200

Merged
merged 41 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
639390d
feat: Slightly Better Russian Translation (#187)
dotFelixan Dec 16, 2024
4ce6b5d
fix: Use correct classes for Field (#189)
ricewind012 Dec 17, 2024
a29c7df
fix: Fix plugin JS being removed from webkit when a new theme is sele…
shdwmtr Dec 19, 2024
1de0352
chore(release): bump version to v2.16.0 [skip ci]
invalid-email-address Dec 19, 2024
3e7d93e
chore(release): 2.16.0 [skip ci]
semantic-release-bot Dec 19, 2024
d25461d
fix: Properly handle theme config with invalid props.
shdwmtr Dec 19, 2024
8817735
fix: Catch installer socket being used instead of crashing.
shdwmtr Dec 19, 2024
07dc66c
fix: Fix unix pathing
shdwmtr Dec 20, 2024
9b7e1e5
fix: Fix crashing on new installs
shdwmtr Dec 20, 2024
4b085a2
chore(release): bump version to v2.16.1 [skip ci]
invalid-email-address Dec 20, 2024
0bc733d
chore(release): 2.16.1 [skip ci]
semantic-release-bot Dec 20, 2024
bfafcb7
fix: Fix installer crashes (again)
shdwmtr Dec 21, 2024
cae007a
chore(release): bump version to v2.16.2 [skip ci]
invalid-email-address Dec 21, 2024
eb2a567
chore(release): 2.16.2 [skip ci]
semantic-release-bot Dec 21, 2024
fb4053d
fix: Fix installer script
shdwmtr Dec 21, 2024
8990389
Merge branch 'main' of https://github.com/shdwmtr/millennium
shdwmtr Dec 21, 2024
71dabc6
fix: Add proxy support for web requests within Steam.
shdwmtr Dec 25, 2024
e2cd49d
fix: Fix webkit and CSP related issues. closes #197, #196, #194
shdwmtr Dec 27, 2024
2c91a95
fix: Fix webkit issues, Close #194, #196
shdwmtr Dec 28, 2024
2573215
fix: Fix webkit patcher edge cases on redirects
shdwmtr Dec 28, 2024
af602c3
feat: Add system accent color to webkit
shdwmtr Dec 28, 2024
65708de
chore: Rename pipe
shdwmtr Dec 28, 2024
d0ff106
chore: Remove debug logs
shdwmtr Dec 28, 2024
43b280a
chore: Fix linux
shdwmtr Dec 28, 2024
b9a6d0d
fix: Fix webkit patcher skipping non-secure requests.
shdwmtr Dec 29, 2024
861c845
Fix: prevent artifact builder from bumping the version
shdwmtr Dec 29, 2024
284a2a2
chore(release): bump version to v2.17.0 [skip ci]
invalid-email-address Dec 29, 2024
1f94b71
chore(release): 2.17.0 [skip ci]
semantic-release-bot Dec 29, 2024
4614cc8
fix: Fix workshop pages not rendering HTML.
shdwmtr Dec 29, 2024
6608125
chore(release): bump version to v2.17.1 [skip ci]
invalid-email-address Dec 29, 2024
2501c85
chore(release): 2.17.1 [skip ci]
semantic-release-bot Dec 29, 2024
7d0fbcf
fix: Fix overlay browser not loading on pages without a response phrase.
shdwmtr Dec 29, 2024
1ca25a5
chore(release): bump version to v2.17.2 [skip ci]
invalid-email-address Dec 29, 2024
900b7eb
chore(release): 2.17.2 [skip ci]
semantic-release-bot Dec 29, 2024
24de43b
feat: Add embedded updater
shdwmtr Dec 31, 2024
558a779
chore: CMake cleanup
shdwmtr Dec 31, 2024
aa4f054
fix: allow frontend function to send booleans & numbers to backend (#…
BossSloth Dec 31, 2024
e138118
feat(ipc): add support for fetching frontend settings from webkit con…
BossSloth Jan 2, 2025
9054c95
chore: integrate new settings framework in example plugin
BossSloth Jan 2, 2025
5423f61
feat: render plugin settings modal based on plugin settings object
BossSloth Jan 4, 2025
44ed4a4
fix: settings not receiving in other context when using tabs
BossSloth Jan 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: Add embedded updater
  • Loading branch information
shdwmtr committed Dec 31, 2024
commit 24de43b8a22f116922c05b12e5538f7045370130
6 changes: 3 additions & 3 deletions src/api/executor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ PyObject* CallFrontendMethod(PyObject* self, PyObject* args, PyObject* kwargs)
return JavaScript::EvaluateFromSocket(
// Check the the frontend code is actually loaded aside from SteamUI
fmt::format(
"if (typeof MillenniumFrontEndError === 'undefined') {{ class MillenniumFrontEndError extends Error {{ constructor(message) {{ super(message); this.name = 'MillenniumFrontEndError'; }} }} }}"
"if (typeof PLUGIN_LIST === 'undefined' || !PLUGIN_LIST?.['{}']) throw new MillenniumFrontEndError('frontend not loaded yet!');\n\n{}",
"if (typeof window !== 'undefined' && typeof window.MillenniumFrontEndError === 'undefined') {{ window.MillenniumFrontEndError = class MillenniumFrontEndError extends Error {{ constructor(message) {{ super(message); this.name = 'MillenniumFrontEndError'; }} }} }}"
"if (typeof PLUGIN_LIST === 'undefined' || !PLUGIN_LIST?.['{}']) throw new window.MillenniumFrontEndError('frontend not loaded yet!');\n\n{}",
pluginName,
script
)
)
);
}

Expand Down
5 changes: 2 additions & 3 deletions src/core/co_initialize/co_stub.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,7 @@ void OnBackendLoad(uint16_t ftpPort, uint16_t ipcPort)

auto socketEmitterThread = std::thread([&]
{
JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg",
[&] (const nlohmann::json& eventMessage, int listenerId)
JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg", "OnBackendLoad", [&](const nlohmann::json& eventMessage, std::string listenerId)
{
std::unique_lock<std::mutex> lock(mtx);

Expand Down Expand Up @@ -349,7 +348,7 @@ const void CoInitializer::InjectFrontendShims(uint16_t ftpPort, uint16_t ipcPort

Logger.Log("Preparing to inject frontend shims...");

JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg", [&](const nlohmann::json& eventMessage, int listenerId)
JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg", "InjectFrontendShims", [&](const nlohmann::json& eventMessage, std::string listenerId)
{
std::lock_guard<std::mutex> lock(mtx);

Expand Down
18 changes: 8 additions & 10 deletions src/core/ffi/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ namespace JavaScript {
Types type;
};

using EventHandler = std::function<void(const nlohmann::json& eventMessage, int listenerId)>;
using EventHandler = std::function<void(const nlohmann::json& eventMessage, std::string listenerId)>;

class SharedJSMessageEmitter {
private:
SharedJSMessageEmitter() {}

std::unordered_map<std::string, std::vector<std::pair<int, EventHandler>>> events;
std::unordered_map<std::string, std::vector<std::pair<std::string, EventHandler>>> events;
std::unordered_map<std::string, std::vector<nlohmann::json>> missedMessages; // New data structure for missed messages
int nextListenerId = 0;

public:
SharedJSMessageEmitter(const SharedJSMessageEmitter&) = delete;
Expand All @@ -77,22 +76,21 @@ namespace JavaScript {
return InstanceRef;
}

int OnMessage(const std::string& event, EventHandler handler) {
int listenerId = nextListenerId++;
events[event].push_back(std::make_pair(listenerId, handler));
std::string OnMessage(const std::string& event, const std::string name, EventHandler handler) {
events[event].push_back(std::make_pair(name, handler));

// Deliver any missed messages
auto it = missedMessages.find(event);
if (it != missedMessages.end()) {
for (const auto message : it->second) {
handler(message, listenerId);
handler(message, name);
}
missedMessages.erase(it); // Clear missed messages once delivered
}
return listenerId;
return name;
}

void RemoveListener(const std::string& event, int listenerId) {
void RemoveListener(const std::string& event, std::string listenerId) {
auto it = events.find(event);
if (it != events.end()) {
auto& handlers = it->second;
Expand All @@ -113,7 +111,7 @@ namespace JavaScript {
try {
handler.second(data, handler.first);
} catch (const std::bad_function_call& e) {
Logger.Warn("Failed to emit message. exception: {}", e.what());
Logger.Warn("Failed to emit message on {}. exception: {}", handler.first, e.what());
}
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/core/ffi/javascript.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const EvalResult ExecuteOnSharedJsContext(std::string javaScriptEval)
throw std::runtime_error("couldn't send message to socket");
}

int listenerId = JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg", [&](const nlohmann::json& eventMessage, int listenerId)
std::string listenerId = JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg", "ExecuteOnSharedJsContext", [&](const nlohmann::json& eventMessage, std::string listenerId)
{
std::lock_guard<std::mutex> lock(mtx); // Lock mutex for safe access

Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/csp_bypass.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const void BypassCSP(void)
// The CSP is implemented by the web server and enforced by the web browser.
// The CSP is a set of rules that the web server sends to the web browser to tell it what content is allowed to be loaded

JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg", [&] (const nlohmann::json& message, int listenerId)
JavaScript::SharedJSMessageEmitter::InstanceRef().OnMessage("msg", "BypassCSP", [&](const nlohmann::json& message, std::string listenerId)
{
try
{
Expand Down
91 changes: 0 additions & 91 deletions src/git/vcs.h

This file was deleted.

38 changes: 9 additions & 29 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,21 @@
#include <signal.h>
#include <cxxabi.h>
#include <pipes/terminal_pipe.h>
#include <git/vcs.h>
#include <api/executor.h>

class Preload
const static void VerifyEnvironment()
{
public:
Preload()
{
this->VerifyEnvironment();
}

~Preload() { }
const auto filePath = SystemIO::GetSteamPath() / ".cef-enable-remote-debugging";

const void VerifyEnvironment()
// Steam's CEF Remote Debugger isn't exposed to port 8080
if (!std::filesystem::exists(filePath))
{
const auto filePath = SystemIO::GetSteamPath() / ".cef-enable-remote-debugging";

// Steam's CEF Remote Debugger isn't exposed to port 8080
if (!std::filesystem::exists(filePath))
{
std::ofstream(filePath).close();
std::ofstream(filePath).close();

Logger.Log("Successfully enabled CEF remote debugging, you can now restart Steam...");
std::exit(1);
}
Logger.Log("Successfully enabled CEF remote debugging, you can now restart Steam...");
std::exit(1);
}

const void Start()
{
CheckForUpdates();
}
};
}

void OnTerminate()
{
Expand Down Expand Up @@ -100,10 +83,7 @@ const static void EntryMain()
uint16_t ftpPort = Crow::CreateAsyncServer();

const auto startTime = std::chrono::system_clock::now();
{
std::unique_ptr<Preload> preload = std::make_unique<Preload>();
preload->Start();
}
VerifyEnvironment();

std::shared_ptr<PluginLoader> loader = std::make_shared<PluginLoader>(startTime, ftpPort);
SetPluginLoader(loader);
Expand Down
11 changes: 11 additions & 0 deletions win32/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.10)

set(BUILD_SHARED_LIBS OFF)

# Set the project name
project(ShimDll)

Expand All @@ -16,9 +18,18 @@ elseif(UNIX AND NOT GITHUB_ACTION_BUILD)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "$ENV{HOME}/.millennium/")
endif()

find_package(CURL REQUIRED) # used for web requests.
find_package(unofficial-minizip CONFIG REQUIRED) # used for extracting zip files

add_compile_definitions(
CURL_STATICLIB
)

# Add the executable
add_library(ShimDll SHARED main.cc)

target_link_libraries(ShimDll CURL::libcurl unofficial::minizip::minizip)

set_target_properties(ShimDll PROPERTIES OUTPUT_NAME "user32")
set_target_properties(ShimDll PROPERTIES PREFIX "")
set_target_properties(ShimDll PROPERTIES NO_EXPORT TRUE)
Expand Down
82 changes: 82 additions & 0 deletions win32/http.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <curl/curl.h>
#include <fstream>
#include <iostream>
#include <bits/this_thread_sleep.h>

size_t write_file_callback(void* contents, size_t size, size_t nmemb, void* userp) {
std::ofstream* file = static_cast<std::ofstream*>(userp);
size_t totalSize = size * nmemb;
file->write(static_cast<char*>(contents), totalSize);
return totalSize;
}

size_t write_callback(char* ptr, size_t size, size_t nmemb, std::string* data) {
data->append(ptr, size * nmemb);
return size * nmemb;
}

bool download_file(const std::string& url, const std::string& outputFilePath) {
CURL* curl;
CURLcode res;
std::ofstream outputFile;

curl = curl_easy_init();
if (!curl) {
std::cerr << "Failed to initialize CURL." << std::endl;
return false;
}

outputFile.open(outputFilePath, std::ios::binary);
if (!outputFile.is_open()) {
std::cerr << "Failed to open file: " << outputFilePath << std::endl;
curl_easy_cleanup(curl);
return false;
}

curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outputFile);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Millennium/1.0");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "CURL error: " << curl_easy_strerror(res) << std::endl;
outputFile.close();
curl_easy_cleanup(curl);
return false;
}

// Clean up
outputFile.close();
curl_easy_cleanup(curl);
return true;
}

const std::string get(const char* url, bool retry = true) {
CURL* curl;
CURLcode res;
std::string response;
curl = curl_easy_init();

if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Millennium/1.0");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Follow redirects

while (true) {
res = curl_easy_perform(curl);

if (!retry || res == CURLE_OK) {
break;
}

std::cerr << "res: " << res << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(3));
}
curl_easy_cleanup(curl);
}
return response;
}
Loading
Loading