Chandra
view release on metacpan or search on metacpan
include/webview-edge.c view on Meta::CPAN
static HMODULE dll = NULL;
static int tried = 0;
if (tried) return dll;
tried = 1;
/* Try loading WebView2Loader.dll from various locations */
dll = LoadLibraryA("WebView2Loader.dll");
if (dll) return dll;
/* Try application directory */
char path[MAX_PATH];
if (GetModuleFileNameA(NULL, path, MAX_PATH)) {
char *slash = strrchr(path, '\\');
if (slash) {
strcpy(slash + 1, "WebView2Loader.dll");
dll = LoadLibraryA(path);
if (dll) return dll;
}
}
/* Try System32 */
if (GetSystemDirectoryA(path, MAX_PATH)) {
strcat(path, "\\WebView2Loader.dll");
dll = LoadLibraryA(path);
}
return dll;
}
static int webview2_available(void) {
HMODULE dll = webview2_load_dll();
if (!dll) return 0;
GetAvailableCoreWebView2BrowserVersionStringFunc getVersion =
(GetAvailableCoreWebView2BrowserVersionStringFunc)GetProcAddress(dll, "GetAvailableCoreWebView2BrowserVersionString");
if (!getVersion) return 0;
LPWSTR version = NULL;
HRESULT hr = getVersion(NULL, &version);
if (SUCCEEDED(hr) && version) {
CoTaskMemFree(version);
return 1;
}
return 0;
}
/* ---- Handler vtables and implementations ---- */
/* WebMessageHandler */
static HRESULT STDMETHODCALLTYPE wmh_QueryInterface(ICoreWebView2WebMessageReceivedEventHandler *This, REFIID riid, void **ppv) {
(void)riid;
*ppv = This;
This->lpVtbl->AddRef(This);
return S_OK;
}
static ULONG STDMETHODCALLTYPE wmh_AddRef(ICoreWebView2WebMessageReceivedEventHandler *This) {
WebMessageHandler *h = (WebMessageHandler *)This;
return InterlockedIncrement(&h->ref);
}
static ULONG STDMETHODCALLTYPE wmh_Release(ICoreWebView2WebMessageReceivedEventHandler *This) {
WebMessageHandler *h = (WebMessageHandler *)This;
LONG ref = InterlockedDecrement(&h->ref);
if (ref == 0) {
GlobalFree(h);
}
return ref;
}
static HRESULT STDMETHODCALLTYPE wmh_Invoke(
ICoreWebView2WebMessageReceivedEventHandler *This,
ICoreWebView2 *sender,
ICoreWebView2WebMessageReceivedEventArgs *args) {
(void)sender;
WebMessageHandler *h = (WebMessageHandler *)This;
LPWSTR message = NULL;
HRESULT hr = args->lpVtbl->TryGetWebMessageAsString(args, &message);
if (SUCCEEDED(hr) && message && h->w && h->w->external_invoke_cb) {
/* Convert wide string to UTF-8 */
int len = WideCharToMultiByte(CP_UTF8, 0, message, -1, NULL, 0, NULL, NULL);
char *utf8 = (char *)GlobalAlloc(GPTR, len);
if (utf8) {
WideCharToMultiByte(CP_UTF8, 0, message, -1, utf8, len, NULL, NULL);
h->w->external_invoke_cb(h->w, utf8);
GlobalFree(utf8);
}
CoTaskMemFree(message);
}
return S_OK;
}
static ICoreWebView2WebMessageReceivedEventHandlerVtbl wmh_vtbl = {
wmh_QueryInterface, wmh_AddRef, wmh_Release, wmh_Invoke
};
/* EnvironmentHandler */
static HRESULT STDMETHODCALLTYPE eh_QueryInterface(ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler *This, REFIID riid, void **ppv) {
(void)riid;
*ppv = This;
This->lpVtbl->AddRef(This);
return S_OK;
}
static ULONG STDMETHODCALLTYPE eh_AddRef(ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler *This) {
EnvironmentHandler *h = (EnvironmentHandler *)This;
return InterlockedIncrement(&h->ref);
}
static ULONG STDMETHODCALLTYPE eh_Release(ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler *This) {
EnvironmentHandler *h = (EnvironmentHandler *)This;
LONG ref = InterlockedDecrement(&h->ref);
if (ref == 0) {
GlobalFree(h);
}
return ref;
}
/* Forward declaration for controller creation */
static void webview2_create_controller(struct webview *w);
static HRESULT STDMETHODCALLTYPE eh_Invoke(
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler *This,
HRESULT result,
ICoreWebView2Environment *environment) {
EnvironmentHandler *h = (EnvironmentHandler *)This;
if (FAILED(result) || !environment) {
return S_OK;
}
if (h->w && h->w->priv.webview2) {
h->w->priv.webview2->environment = environment;
environment->lpVtbl->AddRef(environment);
webview2_create_controller(h->w);
}
return S_OK;
}
static ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl eh_vtbl = {
eh_QueryInterface, eh_AddRef, eh_Release, eh_Invoke
};
/* ControllerHandler */
static HRESULT STDMETHODCALLTYPE ch_QueryInterface(ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *This, REFIID riid, void **ppv) {
(void)riid;
*ppv = This;
This->lpVtbl->AddRef(This);
return S_OK;
}
static ULONG STDMETHODCALLTYPE ch_AddRef(ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *This) {
ControllerHandler *h = (ControllerHandler *)This;
return InterlockedIncrement(&h->ref);
}
static ULONG STDMETHODCALLTYPE ch_Release(ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *This) {
ControllerHandler *h = (ControllerHandler *)This;
LONG ref = InterlockedDecrement(&h->ref);
if (ref == 0) {
GlobalFree(h);
}
return ref;
}
static HRESULT STDMETHODCALLTYPE ch_Invoke(
ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *This,
HRESULT result,
ICoreWebView2Controller *controller) {
ControllerHandler *h = (ControllerHandler *)This;
if (FAILED(result) || !controller) {
return S_OK;
}
if (!h->w || !h->w->priv.webview2) {
return S_OK;
}
webview2 *wv2 = h->w->priv.webview2;
wv2->controller = controller;
controller->lpVtbl->AddRef(controller);
/* Get the CoreWebView2 */
ICoreWebView2 *webview = NULL;
controller->lpVtbl->get_CoreWebView2(controller, &webview);
if (!webview) {
return S_OK;
}
wv2->webview = webview;
/* Configure settings */
ICoreWebView2Settings *settings = NULL;
webview->lpVtbl->get_Settings(webview, &settings);
if (settings) {
settings->lpVtbl->put_IsScriptEnabled(settings, TRUE);
settings->lpVtbl->put_IsWebMessageEnabled(settings, TRUE);
settings->lpVtbl->put_AreDefaultContextMenusEnabled(settings, h->w->debug ? TRUE : FALSE);
settings->lpVtbl->put_AreDevToolsEnabled(settings, h->w->debug ? TRUE : FALSE);
settings->lpVtbl->Release(settings);
}
/* Add web message handler */
WebMessageHandler *wmh = (WebMessageHandler *)GlobalAlloc(GPTR, sizeof(WebMessageHandler));
if (wmh) {
wmh->lpVtbl = &wmh_vtbl;
wmh->ref = 1;
wmh->w = h->w;
webview->lpVtbl->add_WebMessageReceived(webview, (ICoreWebView2WebMessageReceivedEventHandler *)wmh, &wv2->message_token);
wmh->lpVtbl->Release((ICoreWebView2WebMessageReceivedEventHandler *)wmh);
}
/* Inject bridge script */
static const wchar_t bridge_js[] =
L"window.external = window.external || {};"
L"window.external.invoke = function(s) {"
L" window.chrome.webview.postMessage(s);"
( run in 2.192 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )