diff --git a/v3/examples/raw-message/main.go b/v3/examples/raw-message/main.go index cd879ea5cca..a62662b7a72 100644 --- a/v3/examples/raw-message/main.go +++ b/v3/examples/raw-message/main.go @@ -3,13 +3,18 @@ package main import ( "embed" _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" + "fmt" "log" + + "github.com/wailsapp/wails/v3/pkg/application" ) //go:embed assets var assets embed.FS +// main creates and runs the Wails application "Raw Message Demo" with embedded assets, +// a single webview window named "Window 1", and a RawMessageHandler that logs incoming +// raw messages along with their origin information. It logs and exits if the app fails to run. func main() { app := application.New(application.Options{ @@ -21,8 +26,8 @@ func main() { Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, }, - RawMessageHandler: func(window application.Window, message string) { - println("Raw message received from Window '" + window.Name() + "' with message: " + message) + RawMessageHandler: func(window application.Window, message string, originInfo *application.OriginInfo) { + println(fmt.Sprintf("Raw message received from Window %s with message: %s, origin %s, topOrigin %s, isMainFrame %t", window.Name(), message, originInfo.Origin, originInfo.TopOrigin, originInfo.IsMainFrame)) }, }) @@ -41,4 +46,4 @@ func main() { if err != nil { log.Fatal(err.Error()) } -} +} \ No newline at end of file diff --git a/v3/pkg/application/application_darwin.go b/v3/pkg/application/application_darwin.go index 31459ff55c0..28ddd0cca63 100644 --- a/v3/pkg/application/application_darwin.go +++ b/v3/pkg/application/application_darwin.go @@ -335,7 +335,8 @@ func processApplicationEvent(eventID C.uint, data unsafe.Pointer) { applicationEvents <- event } -//export processWindowEvent +// processWindowEvent enqueues a window event for processing by the application's event loop. +// It is called from C and sends a windowEvent containing the provided window and event IDs to the internal windowEvents channel. func processWindowEvent(windowID C.uint, eventID C.uint) { windowEvents <- &windowEvent{ WindowID: uint(windowID), @@ -343,11 +344,21 @@ func processWindowEvent(windowID C.uint, eventID C.uint) { } } -//export processMessage -func processMessage(windowID C.uint, message *C.char) { +// processMessage enqueues a message from a webview into the internal window message buffer, +// including the message origin and whether it came from the main frame. +// If `origin` is nil, Origin in the queued OriginInfo is set to the empty string. +func processMessage(windowID C.uint, message *C.char, origin *C.char, isMainFrame bool) { + o := "" + if origin != nil { + o = C.GoString(origin) + } windowMessageBuffer <- &windowMessage{ windowId: uint(windowID), message: C.GoString(message), + originInfo: &OriginInfo{ + Origin: o, + IsMainFrame: isMainFrame, + }, } } @@ -465,4 +476,4 @@ func HandleCustomProtocol(urlCString *C.char) { Id: uint(events.Common.ApplicationLaunchedWithUrl), ctx: eventContext, } -} +} \ No newline at end of file diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 3fbb543c68a..1b48113e415 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -62,6 +62,16 @@ static void save_window_id(void *object, uint value) g_object_set_data((GObject *)object, "windowid", GUINT_TO_POINTER((guint)value)); } +static void save_webview_to_content_manager(void *contentManager, void *webview) +{ + g_object_set_data(G_OBJECT((WebKitUserContentManager *)contentManager), "webview", webview); +} + +static WebKitWebView* get_webview_from_content_manager(void *contentManager) +{ + return WEBKIT_WEB_VIEW(g_object_get_data(G_OBJECT(contentManager), "webview")); +} + static guint get_window_id(void *object) { return GPOINTER_TO_UINT(g_object_get_data((GObject *)object, "windowid")); @@ -1102,6 +1112,10 @@ func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy Webvi return } +// windowNewWebview creates a WebKit WebView configured with a user content manager and the requested GPU policy. +// It associates the WebView and its content manager with the provided parent window ID, registers the "external" +// script message handler and the custom "wails" URI scheme (once), sets the application user agent, and returns a +// pointer to the created WebView. func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { c := NewCalloc() defer c.Free() @@ -1109,6 +1123,8 @@ func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { C.webkit_user_content_manager_register_script_message_handler(manager, c.String("external")) webView := C.webkit_web_view_new_with_user_content_manager(manager) + C.save_webview_to_content_manager(unsafe.Pointer(manager), unsafe.Pointer(webView)) + // attach window id to both the webview and contentmanager C.save_window_id(unsafe.Pointer(webView), C.uint(parentId)) C.save_window_id(unsafe.Pointer(manager), C.uint(parentId)) @@ -1639,13 +1655,32 @@ func onProcessRequest(request *C.WebKitURISchemeRequest, data C.uintptr_t) { } } -//export sendMessageToBackend +// sendMessageToBackend forwards a JavaScript message from a WebView to the application's +// window message channel, attaching the originating window ID and page origin. +// +// contentManager is the WebKitUserContentManager associated with the sender WebView. +// result is the WebKitJavascriptResult containing the JavaScript value to forward. +// data is callback user data (unused). +// +// The function extracts the message string and publishes a windowMessage onto +// windowMessageBuffer with the windowId and an OriginInfo containing the page URI. func sendMessageToBackend(contentManager *C.WebKitUserContentManager, result *C.WebKitJavascriptResult, data unsafe.Pointer) { // Get the windowID from the contentManager thisWindowID := uint(C.get_window_id(unsafe.Pointer(contentManager))) + webView := C.get_webview_from_content_manager(unsafe.Pointer(contentManager)) + var origin string + if webView != nil { + currentUri := C.webkit_web_view_get_uri(webView) + if currentUri != nil { + uri := C.g_strdup(currentUri) + defer C.g_free(C.gpointer(uri)) + origin = C.GoString(uri) + } + } + var msg string value := C.webkit_javascript_result_get_js_value(result) message := C.jsc_value_to_string(value) @@ -1654,6 +1689,9 @@ func sendMessageToBackend(contentManager *C.WebKitUserContentManager, result *C. windowMessageBuffer <- &windowMessage{ windowId: thisWindowID, message: msg, + originInfo: &OriginInfo{ + Origin: origin, + }, } } @@ -1926,4 +1964,4 @@ func (w *linuxWebviewWindow) redo() { } func (w *linuxWebviewWindow) delete() { -} +} \ No newline at end of file