Persist session state and single-instance

Add session persistence and single-instance handling. Introduces browser/session_state.{h,cpp} to load/save a simple JSON session_state.json (limits restored tabs to 50, basic JSON parsing, atomic write via a .tmp rename). TabManager gains RestoreTabs and ActiveTabIndex to restore and track tabs. NebulaController now calls PersistSession on tab/title/activate/close events, flushes cookies on shutdown, and sets CEF runtime style to Alloy for embedded child browsers and devtools. run.cpp adds a named mutex to prevent multiple instances, enables persistent session cookies, and tweaks initial URL handling. Added GetSessionStatePath() to ui/paths and updated CMakeLists.txt to include the new source file.
This commit is contained in:
2026-05-14 20:48:48 +12:00
parent 406d73c10f
commit 8eb5c1a3b2
10 changed files with 365 additions and 3 deletions
+27 -1
View File
@@ -9,10 +9,30 @@
namespace nebula::app {
namespace {
constexpr wchar_t kMainInstanceMutexName[] = L"Local\\NebulaBrowserMainInstance";
void EnableDpiAwareness() {
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
class ScopedHandle {
public:
explicit ScopedHandle(HANDLE handle) : handle_(handle) {}
~ScopedHandle() {
if (handle_) {
CloseHandle(handle_);
}
}
ScopedHandle(const ScopedHandle&) = delete;
ScopedHandle& operator=(const ScopedHandle&) = delete;
bool valid() const { return handle_ != nullptr; }
private:
HANDLE handle_ = nullptr;
};
} // namespace
int RunNebula(HINSTANCE instance, int show_command) {
@@ -26,8 +46,14 @@ int RunNebula(HINSTANCE instance, int show_command) {
return subprocess_exit_code;
}
ScopedHandle main_instance_mutex(CreateMutexW(nullptr, TRUE, kMainInstanceMutexName));
if (main_instance_mutex.valid() && GetLastError() == ERROR_ALREADY_EXISTS) {
return 0;
}
CefSettings settings;
settings.no_sandbox = true;
settings.persist_session_cookies = true;
// A persistent profile is required for the GPU shader cache and several
// hardware acceleration features. Without these Chromium silently falls
@@ -50,7 +76,7 @@ int RunNebula(HINSTANCE instance, int show_command) {
command_line->InitFromString(GetCommandLineW());
std::string initial_url = command_line->GetSwitchValue("url");
if (nebula::ui::IsEmptyOrChromiumNewTabUrl(initial_url)) {
if (!initial_url.empty() && nebula::ui::IsChromiumNewTabUrl(initial_url)) {
initial_url = nebula::ui::GetHomeUrl();
}