Files
navegator_dashboard/chrome_launcher.cpp
T
2026-05-09 18:11:21 +02:00

133 lines
3.5 KiB
C++

#include "chrome_launcher.h"
#include <cstdio>
#include <string>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
namespace navegator {
namespace {
#ifdef _WIN32
const char* kChromePaths[] = {
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
};
bool file_exists_w(const char* path) {
DWORD attrs = GetFileAttributesA(path);
return (attrs != INVALID_FILE_ATTRIBUTES) && !(attrs & FILE_ATTRIBUTE_DIRECTORY);
}
std::string find_chrome() {
for (const char* p : kChromePaths) {
if (file_exists_w(p)) return p;
}
return "";
}
// Quote para argv en CreateProcess (rules de MSVCR / Chromium):
// envolver en " y escapar las " internas con \" y los \ que preceden a " con \\.
std::string quote_arg(const std::string& a) {
if (a.empty()) return "\"\"";
bool needs = a.find_first_of(" \t\"") != std::string::npos;
if (!needs) return a;
std::string out = "\"";
int backslashes = 0;
for (char c : a) {
if (c == '\\') {
++backslashes;
out += c;
} else if (c == '"') {
// Duplicar las \\ acumuladas + escapar la "
for (int i = 0; i < backslashes; ++i) out += '\\';
backslashes = 0;
out += "\\\"";
} else {
backslashes = 0;
out += c;
}
}
// Cerrar: duplicar \\ pendientes.
for (int i = 0; i < backslashes; ++i) out += '\\';
out += '"';
return out;
}
#endif
} // namespace
LaunchResult launch_chrome(const LaunchOpts& opts) {
LaunchResult r;
#ifndef _WIN32
(void)opts;
r.error = "launch_chrome: solo Windows en v0";
return r;
#else
std::string chrome = opts.chrome_path.empty() ? find_chrome() : opts.chrome_path;
if (chrome.empty()) {
r.error = "chrome.exe no encontrado en Program Files";
return r;
}
if (opts.user_data_dir.empty()) {
r.error = "user_data_dir obligatorio para aislar perfil";
return r;
}
// Crear el directorio si no existe (ignoramos errores, Chrome se queja si no puede).
CreateDirectoryA(opts.user_data_dir.c_str(), nullptr);
char port_buf[32];
std::snprintf(port_buf, sizeof(port_buf), "--remote-debugging-port=%d", opts.port);
std::string cmd;
cmd = quote_arg(chrome);
cmd += " ";
cmd += quote_arg(port_buf);
cmd += " --remote-allow-origins=*";
cmd += " ";
cmd += quote_arg(std::string("--user-data-dir=") + opts.user_data_dir);
cmd += " --no-first-run --no-default-browser-check";
if (opts.headless) {
cmd += " --headless=new --disable-gpu";
}
if (!opts.start_url.empty()) {
cmd += " ";
cmd += quote_arg(opts.start_url);
} else {
cmd += " about:blank";
}
STARTUPINFOA si{};
si.cb = sizeof(si);
PROCESS_INFORMATION pi{};
// CreateProcess modifica el commandline buffer — copia mutable.
std::string mutable_cmd = cmd;
BOOL ok = CreateProcessA(
nullptr,
mutable_cmd.data(),
nullptr, nullptr, FALSE,
CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
nullptr, nullptr, &si, &pi);
if (!ok) {
DWORD err = GetLastError();
char buf[64];
std::snprintf(buf, sizeof(buf), "CreateProcess failed (err=%lu)", (unsigned long)err);
r.error = buf;
return r;
}
r.ok = true;
r.pid = (uint32_t)pi.dwProcessId;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return r;
#endif
}
} // namespace navegator