26#include <include/cef_app.h>
27#include <include/cef_browser.h>
28#include <include/cef_client.h>
29#include <include/cef_command_line.h>
30#include <include/cef_request_handler.h>
31#include <include/cef_ssl_info.h>
32#include <include/views/cef_browser_view.h>
33#include <include/views/cef_browser_view_delegate.h>
34#include <include/views/cef_window.h>
35#include <include/views/cef_window_delegate.h>
36#include <include/wrapper/cef_helpers.h>
37#include <include/cef_callback.h>
38#include <glibmm/miscutils.h>
52#include <unordered_set>
58#include <glibmm/i18n.h>
59#include <nlohmann/json.hpp>
61#define BASTIONGUARD_LOCAL_WARNING_IP "127.0.0.2"
62#define BASTIONGUARD_WARNING_DEFAULT_HTTP 81
64namespace fs = std::filesystem;
72 unsetenv(
"http_proxy");
73 unsetenv(
"https_proxy");
74 unsetenv(
"ftp_proxy");
75 unsetenv(
"all_proxy");
76 unsetenv(
"HTTP_PROXY");
77 unsetenv(
"HTTPS_PROXY");
78 unsetenv(
"FTP_PROXY");
79 unsetenv(
"ALL_PROXY");
101 fd_ = ::open(path, O_CREAT | O_RDWR, 0600);
103 if (flock(
fd_, LOCK_EX | LOCK_NB) != 0) {
108 std::string pid = std::to_string(getpid());
109 ::write(
fd_, pid.c_str(), pid.size());
130 std::transform(s.begin(), s.end(), s.begin(),
131 [](
unsigned char c){ return static_cast<char>(std::tolower(c)); });
137 if (!d.empty() && d[0] ==
'.') d.erase(0, 1);
138 if (d.rfind(
"www.", 0) == 0) d.erase(0, 4);
139 auto p = d.find(
':');
140 if (p != std::string::npos) d.erase(p);
146 auto pos = s.find(
"://");
147 if (pos != std::string::npos) s.erase(0, pos + 3);
149 if (pos != std::string::npos) s.erase(pos);
151 if (pos != std::string::npos) s = s.substr(pos + 1);
155static void load_list_file(
const std::string& path, std::vector<std::string>& out) {
156 if (!fs::exists(path)) {
157 std::cerr <<
_(
"[SecureBrowser] ⚠ File non trovato: ") << path <<
"\n";
162 std::ifstream f(path, std::ios::binary);
164 std::cerr <<
_(
"[SecureBrowser] ⚠ Impossibile aprire: ") << path <<
"\n";
168 std::string data((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
169 data.erase(std::remove(data.begin(), data.end(),
'\0'), data.end());
171 nlohmann::json j = nlohmann::json::parse(data,
nullptr,
true,
true);
173 auto push_domain = [&](
const std::string& d_raw) {
175 if (!d.empty()) out.push_back(d);
179 if (j.contains(
"list") && j[
"list"].is_array()) {
180 for (
const auto& v : j[
"list"]) {
181 if (v.is_string()) push_domain(v.get<std::string>());
183 }
else if (j.contains(
"domains") && j[
"domains"].is_array()) {
184 for (
const auto& v : j[
"domains"]) {
185 if (v.is_string()) push_domain(v.get<std::string>());
187 }
else if (j.contains(
"whitelist") && j[
"whitelist"].is_array()) {
188 for (
const auto& v : j[
"whitelist"]) {
189 if (v.is_string()) push_domain(v.get<std::string>());
192 }
else if (j.is_array()) {
193 for (
const auto& v : j) {
194 if (v.is_string()) push_domain(v.get<std::string>());
198 std::cerr <<
_(
"[SecureBrowser] ✅ Caricati ") << out.size()
199 <<
_(
" domini trusted da ") << path <<
"\n";
200 }
catch (
const std::exception& e) {
201 std::cerr << Glib::ustring::compose(
202 _(
"[SecureBrowser] ❌ Errore parsing JSON (%1): %2"),
210 static std::unordered_set<std::string> trusted_domains;
211 static bool initialized =
false;
214 std::vector<std::string> tmp;
215 std::cerr <<
_(
"[SecureBrowser] 🔍 Caricamento domini trusted...\n");
216 load_list_file(
"/usr/share/BastionGuard/data/bank/banks.json", tmp);
218 const char* home = std::getenv(
"HOME");
220 load_list_file(std::string(home) +
"/.local/share/BastionGuard/banks.json", tmp);
221 load_list_file(std::string(home) +
"/.config/BastionGuard/whitelist.json", tmp);
224 for (
auto& d : tmp) {
228 std::cerr <<
_(
"[SecureBrowser] ✅ Cache inizializzata: ")
229 << trusted_domains.size() <<
_(
" domini trusted.\n");
231 if (trusted_domains.count(
"intesasanpaolo.com"))
232 std::cerr <<
_(
"[SecureBrowser] 🔎 Verifica: 'intesasanpaolo.com' presente in cache.\n");
234 std::cerr <<
_(
"[SecureBrowser] 🔎 Verifica: 'intesasanpaolo.com' NON presente in cache.\n");
241 if (trusted_domains.count(h)) {
242 std::cerr <<
_(
"[SecureBrowser] 🟢 Trusted (match diretto): ") << h <<
"\n";
246 auto dot = h.find(
'.');
247 while (dot != std::string::npos) {
248 std::string parent = h.substr(dot + 1);
249 if (trusted_domains.count(parent)) {
250 std::cerr << Glib::ustring::compose(
251 _(
"[SecureBrowser] 🟢 Trusted (match parent '%1'): %2"),
257 dot = h.find(
'.', dot + 1);
260 std::cerr <<
_(
"[SecureBrowser] 🔴 NON trusted: ") << h <<
"\n";
265public CefLifeSpanHandler,
266public CefDisplayHandler,
267public CefRequestHandler {
274 CEF_REQUIRE_UI_THREAD();
276 std::cout <<
_(
"[SecureBrowser] 🌐 Browser creato.\n");
279 void OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString&)
override {
280 CEF_REQUIRE_UI_THREAD();
285 CEF_REQUIRE_UI_THREAD();
290 [&](
auto& b){ return b->IsSame(browser); }
296 std::cout <<
_(
"[SecureBrowser] 🔒 Tutte le finestre chiuse — uscita loop.\n");
297 CefQuitMessageLoop();
302 CefRefPtr<CefFrame> frame,
303 CefRefPtr<CefRequest> request,
306 CEF_REQUIRE_UI_THREAD();
308 const std::string url = request->GetURL();
311 std::cout <<
_(
"[SecureBrowser] 🌍 URL richiesto: ") << url <<
"\n";
312 std::cout <<
_(
"[SecureBrowser] 🧩 Host estratto: ") << host <<
"\n";
314 if (host ==
"127.0.0.2" || host ==
"127.0.0.1" || host ==
"localhost") {
315 std::cout <<
_(
"[SecureBrowser] ✅ Dominio locale consentito.\n");
319 const bool is_main_frame = frame && frame->IsMain();
323 const bool https_url = url.rfind(
"https://", 0) == 0;
328 if (https_url && (bank_ok || pay_ok)) {
329 std::cout <<
_(
"[SecureBrowser] 🟢 Navigazione attendibile: ") << host <<
"\n";
332 }
else if (https_url) {
338 std::cout <<
_(
"[SecureBrowser] 🚫 Navigazione bloccata verso dominio non trusted: ") << host <<
"\n";
344 cef_errorcode_t cert_error,
345 const CefString& request_url,
346 CefRefPtr<CefSSLInfo>,
347 CefRefPtr<CefCallback> callback)
override {
348 CEF_REQUIRE_UI_THREAD();
350 const std::string url = request_url;
353 std::cout <<
_(
"[SecureBrowser] ⛔ Cert error (") << cert_error
354 <<
_(
") per dominio: ") << host <<
"\n";
358 if (browser && browser->GetMainFrame())
360 if (callback) callback->Cancel();
366 const std::string& host) {
367 std::string safe_host;
368 for (
char c : host) {
369 if (c ==
'<') safe_host +=
"<";
370 else if (c ==
'>') safe_host +=
">";
371 else if (c ==
'&') safe_host +=
"&";
372 else if (c ==
'"') safe_host +=
""";
376 const std::string html =
377 "<!DOCTYPE html><html><head><meta charset='UTF-8'>"
379 "body{margin:0;height:100vh;display:flex;align-items:center;"
380 "justify-content:center;background:#1a1a2e;font-family:system-ui,sans-serif;}"
381 ".card{background:#16213e;border:1px solid #0f3460;border-radius:12px;"
382 "padding:40px 36px;max-width:460px;text-align:center;color:#e0e0e0;}"
383 "h1{color:#e94560;font-size:1.3rem;margin:0 0 16px;}"
384 "p{color:#a0a0b0;font-size:.9rem;line-height:1.6;margin:0 0 24px;}"
385 ".domain{font-family:monospace;color:#4fc3f7;background:#0d1b2a;"
386 "padding:4px 10px;border-radius:4px;}"
387 "button{background:#0f3460;color:#fff;border:none;border-radius:8px;"
388 "padding:10px 24px;font-size:.9rem;cursor:pointer;}"
389 "button:hover{background:#1a4a80;}"
390 "</style></head><body>"
392 "<h1>🛡️ BastionGuard — Navigazione bloccata</h1>"
393 "<p>Il dominio <span class='domain'>" + safe_host +
"</span> "
394 "non è accessibile dalla sessione sicura.<br><br>"
395 "Chiudi questa finestra e aprilo nel tuo browser normale.</p>"
396 "<button onclick='window.close()'>Chiudi</button>"
397 "</div></body></html>";
400 for (
unsigned char c : html) {
401 if (std::isalnum(c) || c ==
'-' || c ==
'_' || c ==
'.' ||
402 c ==
'!' || c ==
'~' || c ==
'*' || c ==
'\'' ||
403 c ==
'(' || c ==
')') {
404 encoded +=
static_cast<char>(c);
407 std::snprintf(buf,
sizeof(buf),
"%%%02X", c);
412 if (browser && browser->GetMainFrame())
413 browser->GetMainFrame()->LoadURL(
"data:text/html," + encoded);
417 static const char kJS[] = R
"JS(
419 if (document.getElementById('BastionGuard_wm')) return;
420 const wm = document.createElement('div');
421 wm.id = 'BastionGuard_wm';
422 wm.textContent = '🟢 BastionGuard Secure Browser';
423 Object.assign(wm.style, {
427 background: 'rgba(46,125,50,0.9)',
429 fontFamily: 'system-ui, sans-serif',
433 borderRadius: '10px',
434 zIndex: '2147483647',
435 pointerEvents: 'none',
436 boxShadow: '0 2px 6px rgba(0,0,0,0.3)'
438 if (document.body) document.body.appendChild(wm);
442 CefRefPtr<CefFrame> frame = browser->GetMainFrame();
443 if (frame && frame->IsValid())
444 frame->ExecuteJavaScript(kJS, frame->GetURL(), 0);
447 std::vector<CefRefPtr<CefBrowser>>
browsers_;
468 CEF_REQUIRE_UI_THREAD();
471 window->AddChildView(
view_);
472 window->SetBounds(CefRect(160, 120, 1000, 720));
473 view_->SetBounds(CefRect(0, 0, 1000, 720));
474 window->SetTitle(
"BastionGuard Secure Browser");
476 view_->RequestFocus();
478 std::cout <<
_(
"[SecureBrowser] 🪟 Popup CEF mostrato nella sessione sicura.\n");
482 CEF_REQUIRE_UI_THREAD();
497 CefRefPtr<CefBrowserView>,
498 const CefBrowserSettings&,
499 CefRefPtr<CefClient>,
506 CefRefPtr<CefBrowserView>,
507 CefRefPtr<CefBrowserView> popup_browser_view,
508 bool is_devtools)
override {
509 CEF_REQUIRE_UI_THREAD();
511 if (is_devtools || !popup_browser_view)
514 CefWindow::CreateTopLevelWindow(
525class ClamApp :
public CefApp,
public CefBrowserProcessHandler {
536 if (std::getenv(
"BG_CEF_PERSIST_SESSION"))
537 cmd->AppendSwitch(
"persist-session-cookies");
539 cmd->AppendSwitch(
"incognito");
541 cmd->AppendSwitch(
"disable-extensions");
542 cmd->AppendSwitch(
"disable-sync");
543 cmd->AppendSwitch(
"disable-component-update");
544 cmd->AppendSwitch(
"disable-print-preview");
551 cmd->AppendSwitch(
"disable-popup-blocking");
553 cmd->AppendSwitchWithValue(
"disable-features",
"TranslateUI");
554 cmd->AppendSwitchWithValue(
"ssl-certificates-file",
"/etc/ssl/certs/ca-certificates.crt");
556 cmd->AppendSwitchWithValue(
"dns-over-https-mode",
"automatic");
557 cmd->AppendSwitchWithValue(
558 "dns-over-https-servers",
559 "https://cloudflare-dns.com/dns-query,https://dns.google/dns-query"
562 cmd->AppendSwitch(
"no-proxy-server");
563 cmd->AppendSwitchWithValue(
"proxy-server",
"direct://");
564 cmd->AppendSwitch(
"proxy-bypass-list=*");
566 cmd->AppendSwitch(
"enable-gpu");
567 cmd->AppendSwitch(
"disable-gpu-compositing");
568 cmd->AppendSwitch(
"use-gl=desktop");
581 auto eq = [](
const char* a,
const char* b) ->
bool {
582 return a && b && std::strcmp(a, b) == 0;
585 const char* internal_be = std::getenv(
"BastionGuard_CEF_BACKEND");
586 const char* ozone_be = std::getenv(
"OZONE_PLATFORM");
587 const char* sess_type = std::getenv(
"XDG_SESSION_TYPE");
588 const char* wl_disp = std::getenv(
"WAYLAND_DISPLAY");
589 const char* x_disp = std::getenv(
"DISPLAY");
592 const char* picked_by;
594 if (eq(internal_be,
"wayland")) { want_wayland =
true; picked_by =
"BastionGuard_CEF_BACKEND"; }
595 else if (eq(internal_be,
"x11")) { want_wayland =
false; picked_by =
"BastionGuard_CEF_BACKEND"; }
596 else if (eq(ozone_be,
"wayland")) { want_wayland =
true; picked_by =
"OZONE_PLATFORM"; }
597 else if (eq(ozone_be,
"x11")) { want_wayland =
false; picked_by =
"OZONE_PLATFORM"; }
598 else if (eq(sess_type,
"wayland")) { want_wayland =
true; picked_by =
"XDG_SESSION_TYPE"; }
599 else if (eq(sess_type,
"x11")) { want_wayland =
false; picked_by =
"XDG_SESSION_TYPE"; }
600 else if (wl_disp && *wl_disp) { want_wayland =
true; picked_by =
"WAYLAND_DISPLAY"; }
601 else if (x_disp && *x_disp) { want_wayland =
false; picked_by =
"DISPLAY"; }
602 else { want_wayland =
false; picked_by =
"default(x11)"; }
604 std::cerr <<
"[SecureBrowser] Ozone backend: "
605 << (want_wayland ?
"wayland" :
"x11")
606 <<
" (via " << picked_by <<
")\n";
608 cmd->AppendSwitchWithValue(
610 "UseOzonePlatform,VaapiVideoDecoder,UseSkiaRenderer,DnsOverHttps"
614 cmd->AppendSwitchWithValue(
"ozone-platform",
"wayland");
615 cmd->AppendSwitch(
"enable-webrtc-pipewire-capturer");
617 cmd->AppendSwitchWithValue(
"ozone-platform",
"x11");
619 cmd->AppendSwitchWithValue(
"ozone-platform-hint",
"x11");
622 cmd->AppendSwitch(
"no-default-browser-check");
623 cmd->AppendSwitch(
"no-first-run");
624 cmd->AppendSwitch(
"disable-crash-reporter");
625 cmd->AppendSwitch(
"disable-background-networking");
626 cmd->AppendSwitch(
"disable-breakpad");
638 std::cerr <<
_(
"[SecureBrowser] CEF disabilitato su questa build o distribuzione.\n");
642 if (!std::getenv(
"BG_SANDBOX"))
645 bool expected =
false;
646 if (!
g_cef_started.compare_exchange_strong(expected,
true)) {
647 std::cerr <<
_(
"[SecureBrowser] ⚠️ Richiesta duplicata nello stesso processo.\n");
653 std::cerr <<
_(
"[SecureBrowser] ℹ️ Istanza già attiva. Rifiuto nuovo avvio.\n");
658 auto fail = [&](
const std::string& msg) ->
bool {
659 std::cerr << msg <<
"\n";
664 std::cout <<
_(
"[SecureBrowser] 🧩 Avvio sandbox Blink/CEF per URL: ") << url << std::endl;
668 setenv(
"SSL_CERT_DIR",
"/etc/ssl/certs", 1);
669 setenv(
"SSL_CERT_FILE",
"/etc/ssl/certs/ca-certificates.crt", 1);
670 setenv(
"NSS_CERT_FILE",
"/etc/ssl/certs/ca-certificates.crt", 1);
671 setenv(
"NSS_CERT_DIR",
"/etc/ssl/certs", 1);
673 const std::string cef_dir =
"/usr/share/BastionGuard/cef";
674 const std::string cache_dir = Glib::get_home_dir() +
"/.cache/BastionGuard/cef_sandbox";
676 fs::create_directories(cache_dir, ec);
678 std::cerr <<
_(
"[SecureBrowser] ⚠️ Creazione cache_dir fallita: ") << ec.message() <<
"\n";
684 setenv(
"BG_CEF_PERSIST_SESSION",
"1", 1);
686 CefMainArgs args(argc, argv);
689 auto try_init_cef = [&](
const char* backend) ->
bool {
690 if (backend) setenv(
"BastionGuard_CEF_BACKEND", backend, 1);
692 CefSettings settings;
693 settings.no_sandbox =
true;
694 settings.windowless_rendering_enabled =
false;
695 settings.log_severity = LOGSEVERITY_WARNING;
696 settings.background_color = CefColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
698 CefString(&settings.resources_dir_path) = cef_dir;
699 CefString(&settings.locales_dir_path) = cef_dir +
"/locales";
700 CefString(&settings.cache_path) = cache_dir;
705 settings.persist_session_cookies =
true;
707 bool init_ok = CefInitialize(args, settings, app,
nullptr);
709 std::cerr <<
_(
"[SecureBrowser] ❌ CefInitialize returned false for backend: ")
710 << (backend ? backend :
"auto") <<
"\n";
725 auto pick_backend = []() ->
const char* {
726 if (
const char* b = std::getenv(
"BastionGuard_CEF_BACKEND")) {
727 if (std::strcmp(b,
"wayland") == 0 || std::strcmp(b,
"x11") == 0)
730 if (
const char* o = std::getenv(
"OZONE_PLATFORM")) {
731 if (std::strcmp(o,
"wayland") == 0 || std::strcmp(o,
"x11") == 0)
734 if (
const char* s = std::getenv(
"XDG_SESSION_TYPE")) {
735 if (std::strcmp(s,
"wayland") == 0)
return "wayland";
736 if (std::strcmp(s,
"x11") == 0)
return "x11";
738 if (std::getenv(
"WAYLAND_DISPLAY"))
return "wayland";
739 if (std::getenv(
"DISPLAY"))
return "x11";
743 const char* backend_pref = pick_backend();
744 std::cerr <<
_(
"[SecureBrowser] backend preferito: ") << backend_pref <<
"\n";
746 bool ok = try_init_cef(backend_pref);
750 if (!ok && std::strcmp(backend_pref,
"wayland") == 0 &&
751 std::getenv(
"DISPLAY") && !std::getenv(
"BG_CEF_X11_FALLBACK")) {
752 std::cerr <<
_(
"[SecureBrowser] ⚠️ CEF Wayland fallito → re-exec con X11.\n");
753 setenv(
"BG_CEF_X11_FALLBACK",
"1", 1);
754 setenv(
"BastionGuard_CEF_BACKEND",
"x11", 1);
755 setenv(
"OZONE_PLATFORM",
"x11", 1);
756 setenv(
"GDK_BACKEND",
"x11", 1);
757 unsetenv(
"WAYLAND_DISPLAY");
759 if (argv && argv[0]) {
760 std::vector<char*> reargv;
761 for (
int i = 0; i < argc; ++i) reargv.push_back(argv[i]);
762 reargv.push_back(
nullptr);
763 execvp(argv[0], reargv.data());
764 std::perror(
"execvp(x11 fallback)");
769 return fail(
_(
"[SecureBrowser] ❌ CefInitialize fallito definitivamente."));
773 CefRefPtr<SecureBrowserViewDelegate> view_delegate =
776 CefBrowserSettings bset;
777 bset.javascript = STATE_ENABLED;
778 bset.webgl = STATE_ENABLED;
780 CefRefPtr<CefBrowserView> mainView =
781 CefBrowserView::CreateBrowserView(
782 handler, url, bset,
nullptr,
nullptr, view_delegate);
786 return fail(
_(
"[SecureBrowser] ❌ CreateBrowserView() ha restituito nullptr."));
789 class WindowDelegate :
public CefWindowDelegate {
791 explicit WindowDelegate(CefRefPtr<CefBrowserView>
main) : mainView_(
main) {}
793 void OnWindowCreated(CefRefPtr<CefWindow> window)
override {
794 window->AddChildView(mainView_);
795 window->SetBounds(CefRect(100, 100, 1200, 800));
796 mainView_->SetBounds(CefRect(0, 0, 1200, 800));
797 window->SetTitle(
"BastionGuard Secure Browser");
801 void OnWindowDestroyed(CefRefPtr<CefWindow>)
override {
802 CefQuitMessageLoop();
805 IMPLEMENT_REFCOUNTING(WindowDelegate);
808 CefRefPtr<CefBrowserView> mainView_;
811 CefWindow::CreateTopLevelWindow(
new WindowDelegate(mainView));
813 std::cout <<
_(
"[SecureBrowser] ✅ Finestra sandbox creata, avvio message loop.\n");
819 std::cout <<
_(
"[SecureBrowser] ✅ Sandbox chiusa correttamente.\n");
833 static const std::unordered_set<std::string> builtin = {
834 "stripe.com",
"paypal.com",
"paypalobjects.com",
"adyen.com",
835 "checkout.com",
"klarna.com",
"worldpay.com",
"braintreegateway.com",
836 "nexi.it",
"nexigroup.com",
"sisalpay.it",
"satispay.com",
837 "sumup.com",
"square.com",
"squareup.com",
"mollie.com",
838 "gocardless.com",
"wise.com",
"revolut.com",
"skrill.com",
839 "neteller.com",
"paysafecard.com",
"amazonpay.com",
840 "wallet.google.com",
"pay.google.com",
843 if (builtin.count(hb))
return true;
844 auto d = hb.find(
'.');
845 while (d != std::string::npos) {
846 if (builtin.count(hb.substr(d + 1)))
return true;
847 d = hb.find(
'.', d + 1);
851 static std::unordered_set<std::string> payment_domains;
852 static bool initialized =
false;
855 std::vector<std::string> tmp;
856 std::cerr <<
_(
"[SecureBrowser] 🔍 Caricamento domini pagamenti...\n");
858 load_list_file(
"/usr/share/BastionGuard/data/payments/payments.json", tmp);
860 const char* home = std::getenv(
"HOME");
862 load_list_file(std::string(home) +
"/.local/share/BastionGuard/payments/payments.json", tmp);
863 load_list_file(std::string(home) +
"/.config/BastionGuard/payments.json", tmp);
866 for (
auto& d : tmp) {
870 std::cerr <<
_(
"[SecureBrowser] ✅ Cache pagamenti inizializzata: ")
871 << payment_domains.size() <<
_(
" domini.\n");
878 if (payment_domains.count(h)) {
879 std::cerr <<
_(
"[SecureBrowser] 🟢 Payment trusted (match diretto): ") << h <<
"\n";
883 auto dot = h.find(
'.');
884 while (dot != std::string::npos) {
885 std::string parent = h.substr(dot + 1);
886 if (payment_domains.count(parent)) {
887 std::cerr <<
_(
"[SecureBrowser] 🟢 Payment trusted (match parent '")
888 << parent <<
"'): " << h <<
"\n";
891 dot = h.find(
'.', dot + 1);
899 std::cerr <<
_(
"[SecureBrowser] Notifiche CEF disabilitate su questa build o distribuzione.\n");
903 static std::atomic<bool> s_running{
false};
904 bool expected =
false;
905 if (!s_running.compare_exchange_strong(expected,
true)) {
906 std::cerr <<
_(
"[SecureBrowser] open_notify: già in esecuzione, ignoro\n");
912 std::cerr <<
_(
"[SecureBrowser] open_notify: istanza notifica già attiva\n");
917 std::cout <<
_(
"[SecureBrowser] 🛡️ Apertura finestra notifica: ") << url <<
"\n";
921 setenv(
"SSL_CERT_DIR",
"/etc/ssl/certs", 1);
922 setenv(
"SSL_CERT_FILE",
"/etc/ssl/certs/ca-certificates.crt", 1);
924 const std::string cef_dir =
"/usr/share/BastionGuard/cef";
925 const std::string cache_dir = Glib::get_home_dir() +
"/.cache/BastionGuard/cef_notify";
927 fs::create_directories(cache_dir, ec);
929 CefMainArgs args(argc ? argc : 0, argv);
932 CefSettings settings;
933 settings.no_sandbox =
true;
934 settings.windowless_rendering_enabled =
false;
935 settings.log_severity = LOGSEVERITY_DISABLE;
936 settings.background_color = CefColorSetARGB(0xFF, 0x07, 0x09, 0x0F);
938 CefString(&settings.resources_dir_path) = cef_dir;
939 CefString(&settings.locales_dir_path) = cef_dir +
"/locales";
940 CefString(&settings.cache_path) = cache_dir;
942 if (!CefInitialize(args, settings, app,
nullptr)) {
943 std::cerr <<
_(
"[SecureBrowser] ❌ open_notify: CefInitialize fallito\n");
948 class NotifyHandler :
public CefClient,
949 public CefLifeSpanHandler,
950 public CefDisplayHandler {
952 CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler()
override {
return this; }
953 CefRefPtr<CefDisplayHandler> GetDisplayHandler()
override {
return this; }
955 void OnAfterCreated(CefRefPtr<CefBrowser>)
override {}
957 void OnBeforeClose(CefRefPtr<CefBrowser>)
override {
958 CEF_REQUIRE_UI_THREAD();
959 CefQuitMessageLoop();
962 IMPLEMENT_REFCOUNTING(NotifyHandler);
965 CefRefPtr<NotifyHandler> handler =
new NotifyHandler();
966 CefBrowserSettings bset;
967 bset.javascript = STATE_ENABLED;
969 CefRefPtr<CefBrowserView> view =
970 CefBrowserView::CreateBrowserView(handler, url, bset,
nullptr,
nullptr,
nullptr);
973 std::cerr <<
_(
"[SecureBrowser] ❌ open_notify: CreateBrowserView fallito\n");
979 class NotifyWindowDelegate :
public CefWindowDelegate {
981 explicit NotifyWindowDelegate(CefRefPtr<CefBrowserView> v) : view_(v) {}
983 void OnWindowCreated(CefRefPtr<CefWindow> w)
override {
984 w->AddChildView(view_);
985 w->SetBounds(CefRect(200, 200, 560, 420));
986 view_->SetBounds(CefRect(0, 0, 560, 420));
987 w->SetTitle(
_(
"BastionGuard — Protected Session"));
991 void OnWindowDestroyed(CefRefPtr<CefWindow>)
override {
992 CefQuitMessageLoop();
995 IMPLEMENT_REFCOUNTING(NotifyWindowDelegate);
998 CefRefPtr<CefBrowserView> view_;
1001 CefWindow::CreateTopLevelWindow(
new NotifyWindowDelegate(view));
1002 CefRunMessageLoop();
1006 std::cout <<
_(
"[SecureBrowser] ✅ Finestra notifica chiusa.\n");
static void load_list_file(const std::string &path, std::vector< std::string > &out)
static bool is_trusted_domain(const std::string &host)
static std::string clean_domain(std::string d)
static std::string to_lower(std::string s)
int main(int argc, char *argv[])
static std::unique_ptr< LocalWarningServer > g_warning_server
#define BASTIONGUARD_WARNING_DEFAULT_HTTP
static bool is_trusted_domain(const std::string &host)
static void clear_proxy_env()
void start_local_warning_server()
#define BASTIONGUARD_LOCAL_WARNING_IP
static std::string host_from_url(const std::string &url)
static bool is_payment_domain(const std::string &host)
static std::atomic< bool > g_cef_started
IMPLEMENT_REFCOUNTING(ClamApp)
ClamApp(bool start_minimized)
void OnBeforeCommandLineProcessing(const CefString &, CefRefPtr< CefCommandLine > cmd) override
CefRefPtr< CefBrowserProcessHandler > GetBrowserProcessHandler() override
InstanceLock(const char *path)
CefRefPtr< CefBrowserViewDelegate > GetDelegateForPopupBrowserView(CefRefPtr< CefBrowserView >, const CefBrowserSettings &, CefRefPtr< CefClient >, bool) override
IMPLEMENT_REFCOUNTING(SecureBrowserViewDelegate)
bool OnPopupBrowserViewCreated(CefRefPtr< CefBrowserView >, CefRefPtr< CefBrowserView > popup_browser_view, bool is_devtools) override
static void open_notify(const std::string &url, int argc, char **argv)
static bool open(const std::string &url, int argc, char **argv)
static CefRefPtr< CefApp > createApp()
static bool get_secure_payments_enabled()
void OnTitleChange(CefRefPtr< CefBrowser > browser, const CefString &) override
void OnBeforeClose(CefRefPtr< CefBrowser > browser) override
static void load_block_page_inline(CefRefPtr< CefBrowser > browser, const std::string &host)
bool OnBeforeBrowse(CefRefPtr< CefBrowser > browser, CefRefPtr< CefFrame > frame, CefRefPtr< CefRequest > request, bool, bool) override
std::vector< CefRefPtr< CefBrowser > > browsers_
void OnAfterCreated(CefRefPtr< CefBrowser > browser) override
bool OnCertificateError(CefRefPtr< CefBrowser > browser, cef_errorcode_t cert_error, const CefString &request_url, CefRefPtr< CefSSLInfo >, CefRefPtr< CefCallback > callback) override
CefRefPtr< CefDisplayHandler > GetDisplayHandler() override
IMPLEMENT_REFCOUNTING(SimpleHandler)
CefRefPtr< CefLifeSpanHandler > GetLifeSpanHandler() override
void inject_watermark(CefRefPtr< CefBrowser > browser)
CefRefPtr< CefRequestHandler > GetRequestHandler() override