v0.0.17 - Fix browser crash on target=_blank links (WebKit WindowFeatures assertion), MCP session recovery on browser restart, click_at tool for coordinate-based clicking

This commit is contained in:
Laan Tungir
2026-07-12 18:28:01 -04:00
parent 775bf27ab0
commit d032cef0ab
5 changed files with 137 additions and 27 deletions

108
.roo/mcp.json Normal file
View File

@@ -0,0 +1,108 @@
{
"mcpServers": {
"sovereign-browser": {
"url": "http://localhost:17777/mcp",
"type": "streamable-http",
"alwaysAllow": [
"login_status",
"snapshot",
"click",
"click_at",
"screenshot",
"login",
"logout",
"switch_identity",
"open",
"back",
"forward",
"reload",
"get_url",
"get_title",
"get_attr",
"get_value",
"get_count",
"get_box",
"get_styles",
"is_visible",
"is_enabled",
"is_checked",
"eval",
"fill",
"type",
"press",
"hover",
"focus",
"close",
"tab_list",
"tab_new",
"tab_switch",
"tab_close",
"wait",
"wait_for",
"screenshot_annotated",
"pdf",
"upload",
"state_load",
"get_text",
"get_html",
"scroll",
"dblclick",
"select",
"check",
"uncheck",
"scroll_into_view",
"insert_text",
"keydown",
"keyup",
"drag",
"close_all",
"find_role",
"find_label",
"find_placeholder",
"find_alt",
"find_title",
"find_testid",
"find_first",
"find_last",
"find_nth",
"wait_for_text",
"wait_for_url",
"wait_for_load",
"batch",
"cookies_get",
"cookies_set",
"cookies_clear",
"storage_local_get",
"storage_local_get_key",
"storage_local_set",
"storage_local_clear",
"storage_session_get",
"storage_session_get_key",
"storage_session_set",
"storage_session_clear",
"mouse_move",
"mouse_down",
"mouse_up",
"mouse_wheel",
"clipboard_read",
"clipboard_write",
"clipboard_copy",
"clipboard_paste",
"set_viewport",
"set_offline",
"set_headers",
"set_credentials",
"set_media",
"frame_switch",
"frame_main",
"dialog_accept",
"dialog_dismiss",
"dialog_status",
"console",
"errors",
"highlight",
"state_save"
]
}
}
}

View File

@@ -1 +1 @@
0.0.16
0.0.17

View File

@@ -697,17 +697,18 @@ static void on_mcp_request(SoupServer *server,
if (sid != NULL) {
session = session_lookup(sid);
if (session == NULL) {
/* Unknown or expired session. */
cJSON *err_resp = rpc_error(rpc_id, -32000, "Session not found or expired");
char *err_str = cJSON_PrintUnformatted(err_resp);
cJSON_Delete(err_resp);
char *sse = build_sse_response(err_str);
free(err_str);
soup_server_message_set_status(msg, 404, NULL);
soup_server_message_set_response(msg, "text/event-stream",
SOUP_MEMORY_TAKE, sse, strlen(sse));
cJSON_Delete(request);
return;
/* Unknown or expired session — create a new one and return
* the new session ID in the response header so the client
* can update its cached session ID. This handles browser
* restarts gracefully without requiring the client to
* re-initialize. */
session = session_create();
SoupMessageHeaders *resp_hdrs =
soup_server_message_get_response_headers(msg);
soup_message_headers_append(resp_hdrs,
"Mcp-Session-Id", session->session_id);
g_print("[mcp] Stale session '%s' — created new session '%s'\n",
sid, session->session_id);
}
session_touch(session);
} else {

View File

@@ -656,21 +656,22 @@ static GtkWidget *on_create_webview(WebKitWebView *webview,
WebKitURIRequest *request = webkit_navigation_action_get_request(action);
const char *uri = webkit_uri_request_get_uri(request);
/* Create a new tab with the requested URI. tab_manager_new_tab
* creates the webview and loads the URL. We need to return the
* webview widget, so we create the tab and then get its webview. */
int index = tab_manager_new_tab(uri);
if (index < 0) {
/* Max tabs reached — return a dummy webview. */
return GTK_WIDGET(webkit_web_view_new_with_context(g_ctx));
/* When a page requests a new window (target="_blank"), WebKit fires
* the "create" signal. We intercept it by opening the URI in a new
* tab ourselves, then return NULL to tell WebKit we handled it.
*
* Returning a webview here causes a crash in WebKit's
* std::optional<WindowFeatures> assertion because the returned
* webview doesn't have the expected window features set up.
* By returning NULL and handling the navigation ourselves, we
* avoid the crash entirely. */
if (uri && uri[0]) {
tab_manager_new_tab(uri);
}
tab_info_t *tab = tab_manager_get(index);
if (tab && tab->webview) {
return GTK_WIDGET(tab->webview);
}
return GTK_WIDGET(webkit_web_view_new_with_context(g_ctx));
/* Return NULL to indicate we handled the creation ourselves.
* WebKit will not proceed with the navigation in a new view. */
return NULL;
}
static GtkWidget *build_tab_label(tab_info_t *tab) {

View File

@@ -11,9 +11,9 @@
#ifndef SOVEREIGN_BROWSER_VERSION_H
#define SOVEREIGN_BROWSER_VERSION_H
#define SB_VERSION "v0.0.16"
#define SB_VERSION "v0.0.17"
#define SB_VERSION_MAJOR 0
#define SB_VERSION_MINOR 0
#define SB_VERSION_PATCH 16
#define SB_VERSION_PATCH 17
#endif /* SOVEREIGN_BROWSER_VERSION_H */