Revert "Merge branch 'Adamcake:master' into refactor/front-end"

This reverts commit 093e5aca0e, reversing
changes made to 4f12d36e7a.

Temporary fix to auth window not being able to authenticate
This commit is contained in:
Kmc
2024-07-07 22:45:05 -04:00
parent 093e5aca0e
commit df7b068ff9
10 changed files with 84 additions and 358 deletions

View File

File diff suppressed because one or more lines are too long

2
app/dist/index.html vendored
View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bolt Launcher</title>
<script type="module" crossorigin src="/assets/index-CfEoSnmR.js"></script>
<script type="module" crossorigin src="/assets/index-dPPSjzHg.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B5crSLm9.css">
</head>
<body

View File

@@ -309,7 +309,7 @@ export async function launchOfficialClient(
? bolt.osrsAppInstalledHash
: bolt.rs3AppInstalledHash;
const launch = async (hash?: string, exe?: Promise<ArrayBuffer>) => {
const launch = async (hash?: string, exe?: Blob) => {
const params: Record<string, string> = {};
if (hash) params.hash = hash;
if (jx_session_id) params.jx_session_id = jx_session_id;
@@ -320,7 +320,7 @@ export async function launchOfficialClient(
{
method: 'POST',
headers: { 'Content-Type': 'application/octet-stream' },
body: await exe
body: exe
}
);
response.text().then((text) => logger.info(`Game launch status: '${text.trim()}'`));
@@ -416,6 +416,6 @@ export async function launchOfficialClient(
// stitch all the data together, slice the exe out of it, and launch the game
Promise.all(chunk_promises).then((x) => {
const exeFile = new Blob(x).slice(exeOffset, exeOffset + <number>exeSize);
launch(metafile.id, exeFile.arrayBuffer());
launch(metafile.id, exeFile);
});
}

View File

@@ -1,21 +1,4 @@
#include "resource_handler.hxx"
#include "include/cef_urlrequest.h"
#include "include/internal/cef_types.h"
// returns content-length or -1 if it's malformed or nonexistent
// CEF interprets -1 as "unknown length"
static int64_t GetContentLength(CefRefPtr<CefResponse> response) {
std::string content_length = response->GetHeaderByName("Content-Length").ToString();
if (content_length.size() == 0) {
return -1;
}
int64_t length = 0;
for (auto it = content_length.begin(); it != content_length.end(); it++) {
if (*it < '0' || *it > '9') return -1;
length = (length * 10) + ((int64_t)(*it) - '0');
}
return length;
}
bool Browser::ResourceHandler::Open(CefRefPtr<CefRequest>, bool& handle_request, CefRefPtr<CefCallback>) {
handle_request = true;
@@ -82,103 +65,3 @@ void Browser::ResourceHandler::finish() {
this->file_manager = nullptr;
}
}
Browser::DefaultURLHandler::DefaultURLHandler(CefRefPtr<CefRequest> request): urlrequest_complete(false), headers_checked(false), urlrequest_callback(nullptr), cursor(0) {
this->url_request = CefURLRequest::Create(request, this, nullptr);
}
CefResourceRequestHandler::ReturnValue Browser::DefaultURLHandler::OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefCallback> callback) {
// use CefResourceRequestHandler::OnBeforeResourceLoad to stall asynchronously on the IO thread
// until the request completes, if it hasn't already
if (urlrequest_complete) {
return RV_CONTINUE;
} else {
this->urlrequest_callback = callback;
return RV_CONTINUE_ASYNC;
}
}
CefRefPtr<CefResourceHandler> Browser::DefaultURLHandler::GetResourceHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request) {
return this;
}
bool Browser::DefaultURLHandler::Open(CefRefPtr<CefRequest> request, bool& handle_request, CefRefPtr<CefCallback> callback) {
handle_request = true;
return true;
}
void Browser::DefaultURLHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, int64_t& response_length, CefString& redirectUrl) {
CefRefPtr<CefResponse> url_response = this->url_request->GetResponse();
CefResponse::HeaderMap headers;
url_response->GetHeaderMap(headers);
response->SetHeaderMap(headers);
response->SetStatus(url_response->GetStatus());
response->SetStatusText(url_response->GetStatusText());
response->SetMimeType(url_response->GetMimeType());
response->SetCharset(url_response->GetCharset());
response->SetHeaderByName("Access-Control-Allow-Origin", "*", true);
response_length = GetContentLength(url_response);
}
bool Browser::DefaultURLHandler::Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr<CefResourceReadCallback> callback) {
if (this->cursor == this->data.size()) {
// "To indicate response completion set |bytes_read| to 0 and return false."
bytes_read = 0;
return false;
}
if (this->cursor + bytes_to_read <= this->data.size()) {
// requested read is entirely in bounds
bytes_read = bytes_to_read;
memcpy(data_out, &this->data[this->cursor], bytes_read);
this->cursor += bytes_to_read;
} else {
// read only to end of string
bytes_read = this->data.size() - this->cursor;
memcpy(data_out, &this->data[this->cursor], bytes_read);
this->cursor = this->data.size();
}
return true;
}
bool Browser::DefaultURLHandler::Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr<CefResourceSkipCallback> callback) {
if (this->cursor + bytes_to_skip <= this->data.size()) {
// skip in bounds
bytes_skipped = bytes_to_skip;
this->cursor += bytes_to_skip;
} else {
// skip to end of string
bytes_skipped = this->data.size() - this->cursor;
this->cursor = this->data.size();
}
return true;
}
void Browser::DefaultURLHandler::Cancel() {
this->cursor = this->data.size();
}
void Browser::DefaultURLHandler::OnRequestComplete(CefRefPtr<CefURLRequest> request) {
this->urlrequest_complete = true;
if (this->urlrequest_callback) {
this->urlrequest_callback->Continue();
}
}
void Browser::DefaultURLHandler::OnUploadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) {}
void Browser::DefaultURLHandler::OnDownloadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) {}
void Browser::DefaultURLHandler::OnDownloadData(CefRefPtr<CefURLRequest> request, const void* data, size_t data_length) {
CefRefPtr<CefResponse> response = request->GetResponse();
if (!this->headers_checked && response) {
const int64_t content_length = GetContentLength(response);
if (content_length != -1) this->data.reserve(content_length);
this->headers_checked = true;
}
size_t write_offset = this->data.size();
this->data.resize(write_offset + data_length);
memcpy(this->data.data() + write_offset, data, data_length);
}
bool Browser::DefaultURLHandler::GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback) {
return false;
}

View File

@@ -5,7 +5,6 @@
#include "include/cef_base.h"
#include "include/cef_resource_request_handler.h"
#include "include/cef_urlrequest.h"
#include <string>
namespace Browser {
@@ -56,38 +55,5 @@ namespace Browser {
DISALLOW_COPY_AND_ASSIGN(ResourceHandler);
};
/// Struct for bridging a CefURLRequestClient to a CefResourceHandler
/// https://github.com/chromiumembedded/cef/blob/5735/include/cef_resource_request_handler.h
/// https://github.com/chromiumembedded/cef/blob/5735/include/cef_resource_handler.h
/// https://github.com/chromiumembedded/cef/blob/5735/include/cef_urlrequest.h#L137
struct DefaultURLHandler: public CefResourceRequestHandler, CefResourceHandler, CefURLRequestClient {
DefaultURLHandler(CefRefPtr<CefRequest>);
CefResourceRequestHandler::ReturnValue OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefCallback> callback) override;
CefRefPtr<CefResourceHandler> GetResourceHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request) override;
bool Open(CefRefPtr<CefRequest> request, bool& handle_request, CefRefPtr<CefCallback> callback) override;
void GetResponseHeaders(CefRefPtr<CefResponse> response, int64_t& response_length, CefString& redirectUrl) override;
bool Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr<CefResourceReadCallback> callback) override;
bool Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr<CefResourceSkipCallback> callback) override;
void Cancel() override;
void OnRequestComplete(CefRefPtr<CefURLRequest> request) override;
void OnUploadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) override;
void OnDownloadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) override;
void OnDownloadData(CefRefPtr<CefURLRequest> request, const void* data, size_t data_length) override;
bool GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback) override;
private:
CefRefPtr<CefURLRequest> url_request;
CefRefPtr<CefCallback> urlrequest_callback;
bool urlrequest_complete;
bool headers_checked;
std::vector<uint8_t> data;
size_t cursor;
IMPLEMENT_REFCOUNTING(DefaultURLHandler);
DISALLOW_COPY_AND_ASSIGN(DefaultURLHandler);
};
#endif
}

View File

@@ -454,18 +454,7 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::GetResourceRequestHandle
}
}
if (!browser->IsSame(this->browser) || !frame->IsMain()) {
return nullptr;
}
// default way to handle web requests from the main window is to make a CefURLRequest that's not subject to CORS safety
disable_default_handling = true;
CefRefPtr<CefRequest> new_request = CefRequest::Create();
CefRequest::HeaderMap headers;
request->GetHeaderMap(headers); // doesn't include Referer header
headers.erase("Origin");
new_request->Set(request->GetURL(), request->GetMethod(), request->GetPostData(), headers);
return new DefaultURLHandler(new_request);
return nullptr;
}
void Browser::Launcher::OnBrowserDestroyed(CefRefPtr<CefBrowserView> view, CefRefPtr<CefBrowser> browser) {
@@ -555,26 +544,6 @@ void Browser::Launcher::Refresh() const {
this->browser->GetMainFrame()->LoadURL(this->BuildURL());
}
void Browser::Launcher::ParseQuery(std::string_view query, std::function<void(const std::string_view&, const std::string_view&)> callback) {
size_t pos = 0;
while (true) {
const size_t next_and = query.find('&', pos);
const size_t next_eq = query.find('=', pos);
if (next_eq == std::string_view::npos) break;
else if (next_and != std::string_view::npos && next_eq > next_and) {
pos = next_and + 1;
continue;
}
const bool is_last = next_and == std::string_view::npos;
const auto end = is_last ? query.end() : query.begin() + next_and;
const std::string_view key(query.begin() + pos, query.begin() + next_eq);
const std::string_view val(query.begin() + next_eq + 1, end);
callback(key, val);
if (is_last) break;
pos = next_and + 1;
}
}
CefRefPtr<CefResourceRequestHandler> SaveFileFromPost(CefRefPtr<CefRequest> request, const std::filesystem::path::value_type* path) {
CefRefPtr<CefPostData> post_data = request->GetPostData();
if (post_data->GetElementCount() != 1) {

View File

@@ -4,10 +4,7 @@
#include "../browser.hxx"
#include "../file_manager.hxx"
#include "include/cef_parser.h"
#include <filesystem>
#include <functional>
namespace Browser {
struct Launcher: public Window {
@@ -40,9 +37,6 @@ namespace Browser {
/// inserting their contents into the query params
CefString BuildURL() const;
/// Goes through all the key-value pairs in the given query string and calls the callback for each one.
void ParseQuery(std::string_view query, std::function<void(const std::string_view&, const std::string_view&)> callback);
/*
Functions called by GetResourceRequestHandler. The result will be returned immediately and must not be null.
The request and URL query string are provided for parsing.
@@ -82,23 +76,4 @@ namespace Browser {
};
}
#if defined(_WIN32)
#define PQTOSTRING ToWString
#else
#define PQTOSTRING ToString
#endif
#define PQCHECK(KEY) \
if (key == #KEY) { \
has_##KEY = true; \
KEY = CefURIDecode(std::string(val), true, (cef_uri_unescape_rule_t)(UU_SPACES | UU_PATH_SEPARATORS | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | UU_REPLACE_PLUS_WITH_SPACE)).PQTOSTRING(); \
return; \
}
#define PQBOOL(KEY) \
if (key == #KEY) { \
KEY = (val.size() > 0 && val != "0"); \
return; \
}
#endif

View File

@@ -1,11 +1,14 @@
#include "window_launcher.hxx"
#include "resource_handler.hxx"
#include "include/cef_parser.h"
#include <archive.h>
#include <archive_entry.h>
#include <fcntl.h>
#include <filesystem>
#include <fmt/core.h>
#include <functional>
#include <spawn.h>
// see #34 for why this function exists and why it can't be run between fork-exec or just run `env`.
@@ -38,6 +41,28 @@ bool FindJava(const char* java_home, std::string& out) {
return false;
}
void ParseQuery(std::string_view query, std::function<void(const std::string_view&, const std::string_view&)> callback) {
size_t pos = 0;
while (true) {
const size_t next_and = query.find('&', pos);
const size_t next_eq = query.find('=', pos);
if (next_eq == std::string_view::npos) break;
else if (next_and != std::string_view::npos && next_eq > next_and) {
pos = next_and + 1;
continue;
}
const bool is_last = next_and == std::string_view::npos;
const auto end = is_last ? query.end() : query.begin() + next_and;
const std::string_view key(query.begin() + pos, query.begin() + next_eq);
const std::string_view val(query.begin() + next_eq + 1, end);
callback(key, val);
if (is_last) break;
pos = next_and + 1;
}
}
const cef_uri_unescape_rule_t pqrule = (cef_uri_unescape_rule_t)(UU_SPACES | UU_PATH_SEPARATORS | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | UU_REPLACE_PLUS_WITH_SPACE);
#define PQCHECK(KEY) if (key == #KEY) { has_##KEY = true; KEY = CefURIDecode(std::string(val), true, pqrule).ToString(); return; }
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<CefRequest> request, std::string_view query) {
/* strings that I don't want to be searchable, which also need to be mutable for passing to env functions */
// PULSE_PROP_OVERRIDE=
@@ -77,14 +102,18 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<C
#if defined(BOLT_PLUGINS)
bool plugin_loader = false;
#endif
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
PQCHECK(hash)
PQCHECK(config_uri)
PQCHECK(jx_session_id)
PQCHECK(jx_character_id)
PQCHECK(jx_display_name)
#if defined(BOLT_PLUGINS)
PQBOOL(plugin_loader)
// no reason to URIDecode this
if (key == "plugin_loader" && val == "1") {
plugin_loader = true;
}
#endif
});
@@ -315,7 +344,7 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRuneliteJar(CefRef
bool has_jx_character_id = false;
std::string jx_display_name;
bool has_jx_display_name = false;
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
PQCHECK(rl_path)
PQCHECK(id)
PQCHECK(jx_session_id)
@@ -472,7 +501,7 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchHdosJar(CefRefPtr<
bool has_jx_character_id = false;
std::string jx_display_name;
bool has_jx_display_name = false;
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
PQCHECK(version)
PQCHECK(jx_session_id)
PQCHECK(jx_character_id)

View File

@@ -1,7 +1,6 @@
#include "window_launcher.hxx"
#include "resource_handler.hxx"
#include <iostream>
#include <shellapi.h>
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<CefRequest> request, std::string_view query) {
@@ -10,144 +9,9 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<C
}
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Exe(CefRefPtr<CefRequest> request, std::string_view query) {
const CefRefPtr<CefPostData> post_data = request->GetPostData();
// parse query
std::wstring hash;
bool has_hash = false;
std::wstring config_uri;
bool has_config_uri = false;
std::wstring jx_session_id;
bool has_jx_session_id = false;
std::wstring jx_character_id;
bool has_jx_character_id = false;
std::wstring jx_display_name;
bool has_jx_display_name = false;
#if defined(BOLT_PLUGINS)
bool plugin_loader = false;
#endif
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
PQCHECK(hash)
PQCHECK(config_uri)
PQCHECK(jx_session_id)
PQCHECK(jx_character_id)
PQCHECK(jx_display_name)
#if defined(BOLT_PLUGINS)
PQBOOL(plugin_loader)
#endif
});
// if there was a "hash" in the query string, we need to save the new game exe and the new hash
if (has_hash) {
if (post_data == nullptr || post_data->GetElementCount() != 1) {
// hash param must be accompanied by POST data containing the file it's a hash of,
// so hash but no POST is a bad request
const char* data = "Bad Request";
return new ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 400, "text/plain");
}
std::ofstream file(this->rs3_exe_path, std::ios::out | std::ios::binary);
if (file.fail()) {
const char* data = "Failed to save executable; if the game is already running, close it and try again\n";
return new Browser::ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 500, "text/plain");
}
CefPostData::ElementVector vec;
post_data->GetElements(vec);
size_t exe_size = vec[0]->GetBytesCount();
unsigned char* exe = new unsigned char[exe_size];
vec[0]->GetBytes(exe_size, exe);
file.write((const char*)exe, exe_size);
file.close();
delete[] exe;
}
// create the command line for the new process
std::wstring command_line = std::wstring(L"\"") + this->rs3_exe_path.wstring() + L"\"";
if (has_config_uri) {
command_line += L" --configURI \"";
command_line += config_uri;
command_line += L"\"";
}
// create the environment block for the new process
std::wstring session_key = L"JX_SESSION_ID=";
std::wstring character_key = L"JX_CHARACTER_ID=";
std::wstring name_key = L"JX_DISPLAY_NAME=";
LPWCH env = GetEnvironmentStringsW();
size_t env_size = 0;
while (env[env_size] != '\0') {
while (env[env_size] != '\0') env_size += 1;
env_size += 1;
}
const size_t current_process_env_size = env_size;
if (has_jx_session_id) env_size += session_key.size() + jx_session_id.size() + 1;
if (has_jx_character_id) env_size += character_key.size() + jx_character_id.size() + 1;
if (has_jx_display_name) env_size += name_key.size() + jx_display_name.size() + 1;
wchar_t* new_env = new wchar_t[env_size + 1];
memcpy(&new_env[0], env, current_process_env_size * sizeof(*env));
FreeEnvironmentStringsW(env);
wchar_t* cursor = &new_env[current_process_env_size];
if (has_jx_session_id) {
memcpy(cursor, &session_key[0], session_key.size() * sizeof(session_key[0]));
cursor += session_key.size();
memcpy(cursor, &jx_session_id[0], jx_session_id.size() * sizeof(jx_session_id[0]));
cursor += jx_session_id.size();
*cursor = '\0';
cursor += 1;
}
if (has_jx_character_id) {
memcpy(cursor, &character_key[0], character_key.size() * sizeof(character_key[0]));
cursor += character_key.size();
memcpy(cursor, &jx_character_id[0], jx_character_id.size() * sizeof(jx_character_id[0]));
cursor += jx_character_id.size();
*cursor = '\0';
cursor += 1;
}
if (has_jx_display_name) {
memcpy(cursor, &name_key[0], name_key.size() * sizeof(name_key[0]));
cursor += name_key.size();
memcpy(cursor, &jx_display_name[0], jx_display_name.size() * sizeof(jx_display_name[0]));
cursor += jx_display_name.size();
*cursor = '\0';
cursor += 1;
}
*cursor = '\0';
PROCESS_INFORMATION pi;
STARTUPINFOW si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcessW(
NULL,
&command_line[0],
NULL,
NULL,
false,
CREATE_UNICODE_ENVIRONMENT, // CREATE_SUSPENDED goes here
new_env,
NULL,
&si,
&pi
)) {
delete[] new_env;
const DWORD error = GetLastError();
const std::string error_message = "CreateProcess failed with error " + std::to_string(error) + "\n";
return new ResourceHandler(error_message, 500, "text/plain");
}
delete[] new_env;
if (has_hash) {
std::wofstream file(this->rs3_exe_hash_path, std::ios::out | std::ios::binary);
if (file.fail()) {
const char* data = "OK, but unable to save hash file\n";
return new Browser::ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 200, "text/plain");
}
file << hash;
file.close();
}
const char* data = "OK\n";
return new ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 200, "text/plain");
// TODO
const char* data = ".exe is not supported on this platform\n";
return new ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 400, "text/plain");
}
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3App(CefRefPtr<CefRequest> request, std::string_view query) {

View File

@@ -135,8 +135,31 @@ void BoltFailToObtainLockfile(std::filesystem::path tempdir) {
#if defined(__linux__)
int main(int argc, char* argv[]) {
CefMainArgs main_args(argc, argv);
// Provide CEF with command-line arguments
// Add a flag to disable web security, because a certain company's API endpoints don't have correct
// access control settings; remove this setting if they ever get their stuff together
// Also add a flag to disable GPUCache being saved on disk because it just breaks sometimes?
const char* arg1 = "--disable-web-security";
const char* arg2 = "--disable-gpu-shader-disk-cache";
const size_t arg1_len = strlen(arg1);
const size_t arg2_len = strlen(arg2);
char* arg1_ = new char[arg1_len + 1];
char* arg2_ = new char[arg2_len + 1];
memcpy(arg1_, arg1, arg1_len);
memcpy(arg2_, arg2, arg2_len);
arg1_[arg1_len] = '\0';
arg2_[arg2_len] = '\0';
char** argv_ = new char*[argc + 2];
memcpy(argv_, argv, argc * sizeof(char*));
argv_[argc] = arg1_;
argv_[argc + 1] = arg2_;
CefMainArgs main_args(argc + 2, argv_);
int ret = BoltRunAnyProcess(main_args);
delete[] argv_;
delete[] arg2_;
delete[] arg1_;
return ret;
}
@@ -237,9 +260,15 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t* lpCmdLine, i
fmt::print("Exiting with error: CommandLineToArgvW failed\n");
return 1;
}
const wchar_t* const arg = L"--disable-web-security";
const wchar_t* subp_arg = L"--type=";
bool has_arg = false;
bool is_subprocess = false;
for(size_t i = 0; i < argc; i += 1) {
// check if arg is --disable-web-security
if (wcsstr(argv[i], arg)) {
has_arg = true;
}
// check if arg begins with --type=
if (wcsncmp(argv[i], subp_arg, wcslen(subp_arg)) == 0) {
is_subprocess = true;
@@ -252,13 +281,24 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t* lpCmdLine, i
int ret = BoltRunAnyProcess(CefMainArgs(hInstance));
CefShutdown();
return ret;
} else {
} else if (has_arg) {
// CefApp struct - this implements handlers used by multiple processes
Browser::App cef_app_;
CefRefPtr<Browser::App> cef_app = &cef_app_;
int ret = BoltRunBrowserProcess(CefMainArgs(hInstance), cef_app);
CefShutdown();
return ret;
} else {
wchar_t module_name[1024];
GetModuleFileNameW(NULL, module_name, 1024);
std::wstring command_line(lpCmdLine);
command_line += std::wstring(L" ");
command_line += std::wstring(arg);
PROCESS_INFORMATION process_info;
STARTUPINFOW startup_info;
GetStartupInfoW(&startup_info);
CreateProcessW(module_name, command_line.data(), NULL, NULL, 0, 0, NULL, NULL, &startup_info, &process_info);
return 0;
}
}