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:
108
.roo/mcp.json
Normal file
108
.roo/mcp.json
Normal 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user