mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 04:22:15 +08:00
[chore] Use webview2 package (#2687)
* [v2 windows] Use external webview2 package * Update CHANGELOG
This commit is contained in:
parent
41edd78953
commit
f2ab205415
@ -35,6 +35,7 @@ require (
|
||||
github.com/tidwall/sjson v1.1.7
|
||||
github.com/tkrajina/go-reflector v0.5.6
|
||||
github.com/wailsapp/mimetype v1.4.1
|
||||
github.com/wailsapp/go-webview2 v1.0.1
|
||||
github.com/wzshiming/ctc v1.2.3
|
||||
golang.org/x/mod v0.8.0
|
||||
golang.org/x/net v0.10.0
|
||||
@ -59,6 +60,7 @@ require (
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.5 // indirect
|
||||
|
@ -250,6 +250,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/wailsapp/go-webview2 v1.0.1 h1:dEJIeEApW/MhO2tTMISZBFZPuW7kwrFA1NtgFB1z1II=
|
||||
github.com/wailsapp/go-webview2 v1.0.1/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
|
@ -21,9 +21,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/bep/debounce"
|
||||
"github.com/wailsapp/go-webview2/pkg/edge"
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
|
||||
|
@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 John Chadwick
|
||||
Some portions Copyright (c) 2017 Serge Zaitsev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,27 +0,0 @@
|
||||
# go-webview2
|
||||
|
||||
This is a proof of concept for embedding Webview2 into Go without CGo. It is based
|
||||
on [webview/webview](https://github.com/webview/webview) and provides a compatible API.
|
||||
|
||||
## Notice
|
||||
|
||||
Because this version doesn't currently have an EdgeHTML fallback, it will not work unless you have a Webview2 runtime
|
||||
installed. In addition, it requires the Webview2Loader DLL in order to function. Adding an EdgeHTML fallback should be
|
||||
technically possible but will likely require much worse hacks since the API is not strictly COM to my knowledge.
|
||||
|
||||
## Demo
|
||||
|
||||
For now, you'll need to install the Webview2 runtime, as it does not ship with Windows.
|
||||
|
||||
[WebView2 runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)
|
||||
|
||||
After that, you should be able to run go-webview2 directly:
|
||||
|
||||
```
|
||||
go run go-webview2/cmd/demo
|
||||
```
|
||||
|
||||
This will use go-winloader to load an embedded copy of WebView2Loader.dll.
|
||||
|
||||
If this does not work, please try running from a directory that has an appropriate copy of `WebView2Loader.dll` for your
|
||||
GOARCH. If _that_ worked, *please* file a bug so we can figure out what's wrong with go-winloader :)
|
@ -1,157 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
ole32 = windows.NewLazySystemDLL("ole32")
|
||||
Ole32CoInitializeEx = ole32.NewProc("CoInitializeEx")
|
||||
|
||||
kernel32 = windows.NewLazySystemDLL("kernel32")
|
||||
Kernel32GetCurrentThreadID = kernel32.NewProc("GetCurrentThreadId")
|
||||
|
||||
shlwapi = windows.NewLazySystemDLL("shlwapi")
|
||||
shlwapiSHCreateMemStream = shlwapi.NewProc("SHCreateMemStream")
|
||||
|
||||
user32 = windows.NewLazySystemDLL("user32")
|
||||
User32LoadImageW = user32.NewProc("LoadImageW")
|
||||
User32GetSystemMetrics = user32.NewProc("GetSystemMetrics")
|
||||
User32RegisterClassExW = user32.NewProc("RegisterClassExW")
|
||||
User32CreateWindowExW = user32.NewProc("CreateWindowExW")
|
||||
User32DestroyWindow = user32.NewProc("DestroyWindow")
|
||||
User32ShowWindow = user32.NewProc("ShowWindow")
|
||||
User32UpdateWindow = user32.NewProc("UpdateWindow")
|
||||
User32SetFocus = user32.NewProc("SetFocus")
|
||||
User32GetMessageW = user32.NewProc("GetMessageW")
|
||||
User32TranslateMessage = user32.NewProc("TranslateMessage")
|
||||
User32DispatchMessageW = user32.NewProc("DispatchMessageW")
|
||||
User32DefWindowProcW = user32.NewProc("DefWindowProcW")
|
||||
User32GetClientRect = user32.NewProc("GetClientRect")
|
||||
User32PostQuitMessage = user32.NewProc("PostQuitMessage")
|
||||
User32SetWindowTextW = user32.NewProc("SetWindowTextW")
|
||||
User32PostThreadMessageW = user32.NewProc("PostThreadMessageW")
|
||||
User32GetWindowLongPtrW = user32.NewProc("GetWindowLongPtrW")
|
||||
User32SetWindowLongPtrW = user32.NewProc("SetWindowLongPtrW")
|
||||
User32AdjustWindowRect = user32.NewProc("AdjustWindowRect")
|
||||
User32SetWindowPos = user32.NewProc("SetWindowPos")
|
||||
)
|
||||
|
||||
const (
|
||||
SystemMetricsCxIcon = 11
|
||||
SystemMetricsCyIcon = 12
|
||||
)
|
||||
|
||||
const (
|
||||
SWShow = 5
|
||||
)
|
||||
|
||||
const (
|
||||
SWPNoZOrder = 0x0004
|
||||
SWPNoActivate = 0x0010
|
||||
SWPNoMove = 0x0002
|
||||
SWPFrameChanged = 0x0020
|
||||
)
|
||||
|
||||
const (
|
||||
WMDestroy = 0x0002
|
||||
WMMove = 0x0003
|
||||
WMSize = 0x0005
|
||||
WMClose = 0x0010
|
||||
WMQuit = 0x0012
|
||||
WMGetMinMaxInfo = 0x0024
|
||||
WMNCLButtonDown = 0x00A1
|
||||
WMMoving = 0x0216
|
||||
WMApp = 0x8000
|
||||
)
|
||||
|
||||
const (
|
||||
GWLStyle = -16
|
||||
)
|
||||
|
||||
const (
|
||||
WSOverlapped = 0x00000000
|
||||
WSMaximizeBox = 0x00020000
|
||||
WSThickFrame = 0x00040000
|
||||
WSCaption = 0x00C00000
|
||||
WSSysMenu = 0x00080000
|
||||
WSMinimizeBox = 0x00020000
|
||||
WSOverlappedWindow = (WSOverlapped | WSCaption | WSSysMenu | WSThickFrame | WSMinimizeBox | WSMaximizeBox)
|
||||
)
|
||||
|
||||
type WndClassExW struct {
|
||||
CbSize uint32
|
||||
Style uint32
|
||||
LpfnWndProc uintptr
|
||||
CnClsExtra int32
|
||||
CbWndExtra int32
|
||||
HInstance windows.Handle
|
||||
HIcon windows.Handle
|
||||
HCursor windows.Handle
|
||||
HbrBackground windows.Handle
|
||||
LpszMenuName *uint16
|
||||
LpszClassName *uint16
|
||||
HIconSm windows.Handle
|
||||
}
|
||||
|
||||
type Rect struct {
|
||||
Left int32
|
||||
Top int32
|
||||
Right int32
|
||||
Bottom int32
|
||||
}
|
||||
|
||||
type MinMaxInfo struct {
|
||||
PtReserved Point
|
||||
PtMaxSize Point
|
||||
PtMaxPosition Point
|
||||
PtMinTrackSize Point
|
||||
PtMaxTrackSize Point
|
||||
}
|
||||
|
||||
type Point struct {
|
||||
X, Y int32
|
||||
}
|
||||
|
||||
type Msg struct {
|
||||
Hwnd syscall.Handle
|
||||
Message uint32
|
||||
WParam uintptr
|
||||
LParam uintptr
|
||||
Time uint32
|
||||
Pt Point
|
||||
LPrivate uint32
|
||||
}
|
||||
|
||||
func Utf16PtrToString(p *uint16) string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
// Find NUL terminator.
|
||||
end := unsafe.Pointer(p)
|
||||
n := 0
|
||||
for *(*uint16)(end) != 0 {
|
||||
end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
|
||||
n++
|
||||
}
|
||||
s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
|
||||
return string(utf16.Decode(s))
|
||||
}
|
||||
|
||||
func SHCreateMemStream(data []byte) (uintptr, error) {
|
||||
ret, _, err := shlwapiSHCreateMemStream.Call(
|
||||
uintptr(unsafe.Pointer(&data[0])),
|
||||
uintptr(len(data)),
|
||||
)
|
||||
if ret == 0 {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
@ -1,239 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package combridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var (
|
||||
comIfcePointersL sync.RWMutex
|
||||
comIfcePointers = map[uintptr]*comObject{} // Map from ComInterfacePointer to the Go ComObject
|
||||
)
|
||||
|
||||
// Resolve the GoInterface of the specified ComInterfacePointer
|
||||
func Resolve[T IUnknown](ifceP uintptr) T {
|
||||
comIfcePointersL.RLock()
|
||||
comObj := comIfcePointers[ifceP]
|
||||
comIfcePointersL.RUnlock()
|
||||
|
||||
var n T
|
||||
if comObj != nil {
|
||||
t := comObj.resolve(ifceP)
|
||||
if t != nil {
|
||||
n = t.(T)
|
||||
}
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// New returns a new ComObject which implements the specified Com Interface, com calls will be redirected
|
||||
// to the specified go interface.
|
||||
func New[T IUnknown](obj T) *ComObject[T] {
|
||||
cObj := new(
|
||||
ifceDef[T]{obj},
|
||||
)
|
||||
return newComObject[T](cObj)
|
||||
}
|
||||
|
||||
// New2 returns a new ComObject which implements the two specified Com Interfaces, com calls will be redirected
|
||||
// to those interfaces accordingly.
|
||||
// This is needed if a ComObject should implement two interfaces that are not descendants of each other,
|
||||
// then you get multiple inheritance.
|
||||
func New2[T IUnknown, T2 IUnknown](obj T, obj2 T2) *ComObject[T] {
|
||||
cObj := new(
|
||||
ifceDef[T]{obj},
|
||||
ifceDef[T2]{obj2},
|
||||
)
|
||||
return newComObject[T](cObj)
|
||||
}
|
||||
|
||||
// new returns a new ComObject which implements multiple specified Com Interfaces, com calls will be redirected
|
||||
// to the specified go interfaces accordingly.
|
||||
// This is needed if a ComObject should implement multiple interfaces that are not descendants of each other,
|
||||
// then you get multiple inheritance.
|
||||
func new(impls ...ifceImpl) *comObject {
|
||||
impls = append([]ifceImpl{ifceDef[IUnknown]{}}, impls...)
|
||||
|
||||
cObj := &comObject{
|
||||
refCount: 1,
|
||||
ifces: map[string]int{},
|
||||
ifcesImpl: make([]comInterfaceDesc, len(impls)),
|
||||
}
|
||||
|
||||
for i, ifceDef := range impls {
|
||||
vtable, err := ifceDef.ifce()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
needsImplement := false
|
||||
for table := vtable; table != nil; table = table.Parent {
|
||||
guid := table.ComGUID
|
||||
if i, found := cObj.ifces[guid]; found {
|
||||
// This Interface is already implemented
|
||||
if guid == iUnknownGUID {
|
||||
// IUnknown is a special interface and never has an user specific implementation
|
||||
} else if cObj.ifcesImpl[i].impl != ifceDef.impl() {
|
||||
panic(fmt.Sprintf("Interface '%s' is already implemented by another object", table.Name))
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
needsImplement = true
|
||||
cObj.ifces[guid] = i
|
||||
}
|
||||
|
||||
if !needsImplement {
|
||||
continue
|
||||
}
|
||||
|
||||
ifceP, ifcePSlice := allocUintptrObject(1)
|
||||
ifcePSlice[0] = vtable.ComVTable
|
||||
cObj.ifcesImpl[i] = comInterfaceDesc{ifceP, ifceDef.impl()}
|
||||
}
|
||||
|
||||
comIfcePointersL.Lock()
|
||||
for _, ifceImpl := range cObj.ifcesImpl {
|
||||
comIfcePointers[ifceImpl.ref] = cObj
|
||||
}
|
||||
comIfcePointersL.Unlock()
|
||||
|
||||
return cObj
|
||||
}
|
||||
|
||||
func newComObject[T IUnknown](comObj *comObject) *ComObject[T] {
|
||||
c := &ComObject[T]{obj: comObj}
|
||||
// Make sure to async release since release needs locks and might block the finalizer goroutine for a longer period
|
||||
runtime.SetFinalizer(c, func(obj *ComObject[T]) { obj.close(true) })
|
||||
return c
|
||||
}
|
||||
|
||||
// ComObject describes an exported go instance to be used as a ComObject which implements
|
||||
// the specified Interface.
|
||||
type ComObject[T IUnknown] struct {
|
||||
obj *comObject
|
||||
closed int32
|
||||
}
|
||||
|
||||
// Ref returns the native uintptr that points to the ComObject that is an interface pointer to T.
|
||||
// This can be used in native calls. If the object has been closed this function will panic.
|
||||
func (o *ComObject[T]) Ref() uintptr {
|
||||
if atomic.LoadInt32(&o.closed) != 0 {
|
||||
panic("ComObject has been released")
|
||||
}
|
||||
return o.obj.queryInterface(guidOf[T](), false)
|
||||
}
|
||||
|
||||
// Close releases the native com object from the go side. It will only be destroyed if the ref counter
|
||||
// reaches zero.
|
||||
// After closing `Ref()` will panic.
|
||||
func (o *ComObject[T]) Close() error {
|
||||
o.close(false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// close releases the native com object from the go side. It will only be destroyed if the ref counter
|
||||
// reaches zero.
|
||||
// After closing `Ref()` will panic.
|
||||
func (o *ComObject[T]) close(asyncRelease bool) {
|
||||
if atomic.CompareAndSwapInt32(&o.closed, 0, 1) {
|
||||
runtime.SetFinalizer(o, nil)
|
||||
if asyncRelease {
|
||||
go o.obj.release()
|
||||
} else {
|
||||
o.obj.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type comInterfaceDesc struct {
|
||||
ref uintptr // The native Com InterfacePointer
|
||||
impl any // The golang target object
|
||||
}
|
||||
|
||||
type comObject struct {
|
||||
l sync.Mutex
|
||||
|
||||
refCount int32
|
||||
ifces map[string]int // Map of ComInterfaceGUID to Interface Slots
|
||||
ifcesImpl []comInterfaceDesc // Slots with InterfaceDescriptors
|
||||
}
|
||||
|
||||
func (c *comObject) queryInterface(ifceGUID string, withAddRef bool) uintptr {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
if c.refCount <= 0 {
|
||||
panic("call on released com object")
|
||||
}
|
||||
|
||||
i, found := c.ifces[ifceGUID]
|
||||
if !found {
|
||||
return 0
|
||||
}
|
||||
|
||||
if withAddRef {
|
||||
c.refCount++
|
||||
}
|
||||
return c.ifcesImpl[i].ref
|
||||
}
|
||||
|
||||
func (c *comObject) resolve(ifceP uintptr) any {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
if c.refCount <= 0 {
|
||||
panic("call on destroyed com object")
|
||||
}
|
||||
|
||||
for _, ifce := range c.ifcesImpl {
|
||||
if ifce.ref != ifceP {
|
||||
continue
|
||||
}
|
||||
|
||||
return ifce.impl
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *comObject) addRef() int32 {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
if c.refCount <= 0 {
|
||||
panic("call on destroyed com object")
|
||||
}
|
||||
|
||||
c.refCount++
|
||||
return c.refCount
|
||||
}
|
||||
|
||||
func (c *comObject) release() int32 {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
if c.refCount <= 0 {
|
||||
panic("call on destroyed com object")
|
||||
}
|
||||
|
||||
if c.refCount--; c.refCount == 0 {
|
||||
comIfcePointersL.Lock()
|
||||
for _, ref := range c.ifcesImpl {
|
||||
delete(comIfcePointers, ref.ref)
|
||||
}
|
||||
comIfcePointersL.Unlock()
|
||||
|
||||
for _, impl := range c.ifcesImpl {
|
||||
ref := impl.ref
|
||||
if ref == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
globalFree(ref)
|
||||
}
|
||||
}
|
||||
|
||||
return c.refCount
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package combridge
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const iUnknownGUID = "{00000000-0000-0000-C000-000000000046}"
|
||||
|
||||
func init() {
|
||||
registerVTableInternal[IUnknown, IUnknown](
|
||||
iUnknownGUID,
|
||||
true,
|
||||
iUnknownQueryInterface,
|
||||
iUnknownAddRef,
|
||||
iUnknownRelease,
|
||||
)
|
||||
}
|
||||
|
||||
type IUnknown interface{}
|
||||
|
||||
func iUnknownQueryInterface(this uintptr, refiid *windows.GUID, ppvObject *uintptr) uintptr {
|
||||
if refiid == nil || ppvObject == nil {
|
||||
return uintptr(windows.E_INVALIDARG)
|
||||
}
|
||||
|
||||
comIfcePointersL.RLock()
|
||||
obj := comIfcePointers[this]
|
||||
comIfcePointersL.RUnlock()
|
||||
|
||||
ref := obj.queryInterface(refiid.String(), true)
|
||||
if ref != 0 {
|
||||
*ppvObject = ref
|
||||
return windows.NO_ERROR
|
||||
}
|
||||
|
||||
*ppvObject = 0
|
||||
return uintptr(windows.E_NOINTERFACE)
|
||||
}
|
||||
|
||||
func iUnknownAddRef(this uintptr) uintptr {
|
||||
comIfcePointersL.RLock()
|
||||
obj := comIfcePointers[this]
|
||||
comIfcePointersL.RUnlock()
|
||||
|
||||
return uintptr(obj.addRef())
|
||||
}
|
||||
|
||||
func iUnknownRelease(this uintptr) uintptr {
|
||||
comIfcePointersL.RLock()
|
||||
obj := comIfcePointers[this]
|
||||
comIfcePointersL.RUnlock()
|
||||
|
||||
return uintptr(obj.release())
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package combridge
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// IUnknownFromPointer cast a generic pointer into a IUnknownImpl pointer
|
||||
func IUnknownFromPointer(ref unsafe.Pointer) *IUnknownImpl {
|
||||
return (*IUnknownImpl)(ref)
|
||||
}
|
||||
|
||||
// IUnknownFromPointer cast native pointer into a IUnknownImpl pointer
|
||||
func IUnknownFromUintptr(ref uintptr) *IUnknownImpl {
|
||||
return IUnknownFromPointer(unsafe.Pointer(ref))
|
||||
}
|
||||
|
||||
type IUnknownVtbl struct {
|
||||
queryInterface uintptr
|
||||
addRef uintptr
|
||||
release uintptr
|
||||
}
|
||||
|
||||
func (i *IUnknownVtbl) QueryInterface(this unsafe.Pointer, refiid *windows.GUID, ppvObject **IUnknownImpl) error {
|
||||
r, _, _ := syscall.SyscallN(
|
||||
i.queryInterface,
|
||||
uintptr(this),
|
||||
uintptr(unsafe.Pointer(refiid)),
|
||||
uintptr(unsafe.Pointer(ppvObject)),
|
||||
)
|
||||
|
||||
if r != uintptr(windows.S_OK) {
|
||||
return syscall.Errno(r)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IUnknownVtbl) AddRef(this unsafe.Pointer) uint32 {
|
||||
r, _, _ := syscall.SyscallN(
|
||||
i.addRef,
|
||||
uintptr(this),
|
||||
)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func (i *IUnknownVtbl) Release(this unsafe.Pointer) uint32 {
|
||||
r, _, _ := syscall.SyscallN(
|
||||
i.release,
|
||||
uintptr(this),
|
||||
)
|
||||
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type IUnknownImpl struct {
|
||||
vtbl *IUnknownVtbl
|
||||
}
|
||||
|
||||
func (i *IUnknownImpl) QueryInterface(refiid *windows.GUID, ppvObject **IUnknownImpl) error {
|
||||
return i.vtbl.QueryInterface(unsafe.Pointer(i), refiid, ppvObject)
|
||||
}
|
||||
|
||||
func (i *IUnknownImpl) AddRef() uint32 {
|
||||
return i.vtbl.AddRef(unsafe.Pointer(i))
|
||||
}
|
||||
|
||||
func (i *IUnknownImpl) Release() uint32 {
|
||||
return i.vtbl.Release(unsafe.Pointer(i))
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package combridge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
|
||||
procGlobalFree = modkernel32.NewProc("GlobalFree")
|
||||
|
||||
uintptrSize = unsafe.Sizeof(uintptr(0))
|
||||
)
|
||||
|
||||
func allocUintptrObject(size int) (uintptr, []uintptr) {
|
||||
v := globalAlloc(uintptr(size) * uintptrSize)
|
||||
slice := unsafe.Slice((*uintptr)(unsafe.Pointer(v)), size)
|
||||
return v, slice
|
||||
}
|
||||
|
||||
func globalAlloc(dwBytes uintptr) uintptr {
|
||||
ret, _, _ := procGlobalAlloc.Call(uintptr(0), dwBytes)
|
||||
if ret == 0 {
|
||||
panic("globalAlloc failed")
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func globalFree(data uintptr) {
|
||||
ret, _, _ := procGlobalFree.Call(data)
|
||||
if ret != 0 {
|
||||
panic("globalFree failed")
|
||||
}
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package combridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
vTablesL sync.Mutex
|
||||
vTables = make(map[string]*vTable)
|
||||
)
|
||||
|
||||
// RegisterVTable registers the vtable trampoline methods for the specified ComInterface
|
||||
// TBase is the base interface of T, and must be another ComInterface which roots in IUnknown or IUnknown itself.
|
||||
// The first paramter of the fn is always the uintptr of the ComObject and the GoObject can be resolved with Resolve().
|
||||
// After having resolved the GoObject the call must be redirected to the GoObject.
|
||||
// Typically a trampoline FN looks like this.
|
||||
//
|
||||
// func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this uintptr, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
|
||||
// return combridge.Resolve[_ICoreWebView2NavigationCompletedEventHandler](this).NavigationCompleted(sender, args)
|
||||
// }
|
||||
//
|
||||
// The order of registration must be in the correct order as specified in the IDL of the interface.
|
||||
func RegisterVTable[TParent, T IUnknown](guid string, fns ...interface{}) {
|
||||
registerVTableInternal[TParent, T](guid, false, fns...)
|
||||
}
|
||||
|
||||
type vTable struct {
|
||||
Parent *vTable
|
||||
|
||||
Name string
|
||||
ComGUID string
|
||||
ComVTable uintptr
|
||||
ComProcs []uintptr
|
||||
}
|
||||
|
||||
func registerVTableInternal[TParent, T IUnknown](guid string, isInternal bool, fns ...interface{}) {
|
||||
vTablesL.Lock()
|
||||
defer vTablesL.Unlock()
|
||||
|
||||
t, tName := typeInterfaceToString[T]()
|
||||
tParent, tParentName := typeInterfaceToString[TParent]()
|
||||
if !t.Implements(tParent) {
|
||||
panic(fmt.Errorf("RegisterVTable '%s': '%s' must implement '%s'", tName, tName, tParentName))
|
||||
}
|
||||
|
||||
if !isInternal {
|
||||
if t == reflect.TypeOf((*IUnknown)(nil)).Elem() {
|
||||
panic(fmt.Errorf("RegisterVTable '%s' IUnknown can't be registered", tName))
|
||||
}
|
||||
|
||||
if t == tParent {
|
||||
panic(fmt.Errorf("RegisterVTable '%s': T and TParent can't be the same type", tName))
|
||||
}
|
||||
}
|
||||
|
||||
var parent *vTable
|
||||
var parentProcs []uintptr
|
||||
var parentProcsCount int
|
||||
if t != tParent {
|
||||
parent = vTables[tParentName]
|
||||
if parent == nil {
|
||||
panic(fmt.Errorf("RegisterVTable '%s': Parent VTable '%s' not registered", tName, tParentName))
|
||||
}
|
||||
|
||||
parentProcs = parent.ComProcs
|
||||
parentProcsCount = len(parentProcs)
|
||||
}
|
||||
|
||||
comGuid, err := windows.GUIDFromString(guid)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("RegisterVTable '%s': invalid guid: %s", tName, err))
|
||||
}
|
||||
|
||||
vTable := &vTable{
|
||||
Parent: parent,
|
||||
Name: tName,
|
||||
ComGUID: comGuid.String(),
|
||||
}
|
||||
vTable.ComVTable, vTable.ComProcs = allocUintptrObject(parentProcsCount + len(fns))
|
||||
|
||||
for i, proc := range parentProcs {
|
||||
vTable.ComProcs[i] = proc
|
||||
}
|
||||
|
||||
for i, fn := range fns {
|
||||
vTable.ComProcs[parentProcsCount+i] = windows.NewCallback(fn)
|
||||
}
|
||||
|
||||
vTables[tName] = vTable
|
||||
}
|
||||
|
||||
func typeInterfaceToString[T any]() (reflect.Type, string) {
|
||||
t := reflect.TypeOf((*T)(nil))
|
||||
if t.Kind() != reflect.Pointer {
|
||||
panic("must be a (*yourInterfaceType)(nil)")
|
||||
}
|
||||
t = t.Elem()
|
||||
return t, t.PkgPath() + "/" + t.Name()
|
||||
}
|
||||
|
||||
func typeInterfaceToStringOnly[T any]() string {
|
||||
_, nane := typeInterfaceToString[T]()
|
||||
return nane
|
||||
}
|
||||
|
||||
func guidOf[T any]() string {
|
||||
vtable := vTableOf[T]()
|
||||
if vtable == nil {
|
||||
return ""
|
||||
}
|
||||
return vtable.ComGUID
|
||||
}
|
||||
|
||||
func vTableOf[T any]() *vTable {
|
||||
name := typeInterfaceToStringOnly[T]()
|
||||
vTablesL.Lock()
|
||||
defer vTablesL.Unlock()
|
||||
|
||||
return vTables[name]
|
||||
}
|
||||
|
||||
type ifceImpl interface {
|
||||
impl() any
|
||||
ifce() (*vTable, error)
|
||||
}
|
||||
|
||||
type ifceDef[T any] struct {
|
||||
objImpl any
|
||||
}
|
||||
|
||||
func (i ifceDef[T]) impl() any {
|
||||
return i.objImpl
|
||||
}
|
||||
|
||||
func (i ifceDef[T]) ifce() (*vTable, error) {
|
||||
vtable := vTableOf[T]()
|
||||
if vtable == nil {
|
||||
return nil, fmt.Errorf("Unable to find vTable for %s", typeInterfaceToStringOnly[T]())
|
||||
}
|
||||
return vtable, nil
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type COREWEBVIEW2_COLOR struct {
|
||||
A uint8
|
||||
R uint8
|
||||
G uint8
|
||||
B uint8
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND uint32
|
||||
|
||||
const (
|
||||
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY = iota
|
||||
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW
|
||||
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS
|
||||
)
|
@ -1,12 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type COREWEBVIEW2_KEY_EVENT_KIND uint32
|
||||
|
||||
const (
|
||||
COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0
|
||||
COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = 1
|
||||
COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN = 2
|
||||
COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = 3
|
||||
)
|
@ -1,11 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type COREWEBVIEW2_MOVE_FOCUS_REASON uint32
|
||||
|
||||
const (
|
||||
COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC = 0
|
||||
COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT = 1
|
||||
COREWEBVIEW2_MOVE_FOCUS_REASON_PREVIOUS = 2
|
||||
)
|
@ -1,12 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type COREWEBVIEW2_PHYSICAL_KEY_STATUS struct {
|
||||
RepeatCount uint32
|
||||
ScanCode uint32
|
||||
IsExtendedKey bool
|
||||
IsMenuKeyDown bool
|
||||
WasKeyDown bool
|
||||
IsKeyReleased bool
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type COREWEBVIEW2_PROCESS_FAILED_KIND uint32
|
||||
|
||||
const (
|
||||
// Indicates that the browser process ended unexpectedly. The WebView
|
||||
// automatically moves to the Closed state. The app has to recreate a new
|
||||
// WebView to recover from this failure.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED = 0
|
||||
|
||||
// Indicates that the main frame's render process ended unexpectedly. A new
|
||||
// render process is created automatically and navigated to an error page.
|
||||
// You can use the `Reload` method to try to reload the page that failed.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED = 1
|
||||
|
||||
// Indicates that the main frame's render process is unresponsive.
|
||||
//
|
||||
// Note that this does not seem to work right now.
|
||||
// Does not fire for simple long running script case, the only related test
|
||||
// SitePerProcessBrowserTest::NoCommitTimeoutForInvisibleWebContents is
|
||||
// disabled.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE = 2
|
||||
|
||||
// Indicates that a frame-only render process ended unexpectedly. The process
|
||||
// exit does not affect the top-level document, only a subset of the
|
||||
// subframes within it. The content in these frames is replaced with an error
|
||||
// page in the frame.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED = 3
|
||||
|
||||
// Indicates that a utility process ended unexpectedly.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_UTILITY_PROCESS_EXITED = 4
|
||||
|
||||
// Indicates that a sandbox helper process ended unexpectedly.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_SANDBOX_HELPER_PROCESS_EXITED = 5
|
||||
|
||||
// Indicates that the GPU process ended unexpectedly.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_GPU_PROCESS_EXITED = 6
|
||||
|
||||
// Indicates that a PPAPI plugin process ended unexpectedly.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_PLUGIN_PROCESS_EXITED = 7
|
||||
|
||||
// Indicates that a PPAPI plugin broker process ended unexpectedly.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_BROKER_PROCESS_EXITED = 8
|
||||
|
||||
// Indicates that a process of unspecified kind ended unexpectedly.
|
||||
COREWEBVIEW2_PROCESS_FAILED_KIND_UNKNOWN_PROCESS_EXITED = 9
|
||||
)
|
@ -1,25 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type COREWEBVIEW2_WEB_RESOURCE_CONTEXT uint32
|
||||
|
||||
const (
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL = 0
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT = 1
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_STYLESHEET = 2
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_IMAGE = 3
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MEDIA = 4
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FONT = 5
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SCRIPT = 6
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_XML_HTTP_REQUEST = 7
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FETCH = 8
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_TEXT_TRACK = 9
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_EVENT_SOURCE = 10
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_WEBSOCKET = 11
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MANIFEST = 12
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SIGNED_EXCHANGE = 13
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_PING = 14
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_CSP_VIOLATION_REPORT = 15
|
||||
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_OTHER = 16
|
||||
)
|
@ -1,79 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2AcceleratorKeyPressedEventArgsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetKeyEventKind ComProc
|
||||
GetVirtualKey ComProc
|
||||
GetKeyEventLParam ComProc
|
||||
GetPhysicalKeyStatus ComProc
|
||||
GetHandled ComProc
|
||||
PutHandled ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2AcceleratorKeyPressedEventArgs struct {
|
||||
vtbl *_ICoreWebView2AcceleratorKeyPressedEventArgsVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEBVIEW2_KEY_EVENT_KIND, error) {
|
||||
var err error
|
||||
var keyEventKind COREWEBVIEW2_KEY_EVENT_KIND
|
||||
_, _, err = i.vtbl.GetKeyEventKind.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&keyEventKind)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return 0, err
|
||||
}
|
||||
return keyEventKind, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint, error) {
|
||||
var err error
|
||||
var virtualKey uint
|
||||
_, _, err = i.vtbl.GetVirtualKey.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&virtualKey)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return 0, err
|
||||
}
|
||||
return virtualKey, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetPhysicalKeyStatus() (COREWEBVIEW2_PHYSICAL_KEY_STATUS, error) {
|
||||
var err error
|
||||
var physicalKeyStatus COREWEBVIEW2_PHYSICAL_KEY_STATUS
|
||||
_, _, err = i.vtbl.GetPhysicalKeyStatus.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&physicalKeyStatus)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return COREWEBVIEW2_PHYSICAL_KEY_STATUS{}, err
|
||||
}
|
||||
return physicalKeyStatus, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) PutHandled(handled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutHandled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(handled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2AcceleratorKeyPressedEventHandler struct {
|
||||
vtbl *_ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl
|
||||
impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2AcceleratorKeyPressedEventHandler) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface(this *ICoreWebView2AcceleratorKeyPressedEventHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke(this *ICoreWebView2AcceleratorKeyPressedEventHandler, sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
|
||||
return this.impl.AcceleratorKeyPressed(sender, args)
|
||||
}
|
||||
|
||||
type _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr
|
||||
}
|
||||
|
||||
var _ICoreWebView2AcceleratorKeyPressedEventHandlerFn = _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2AcceleratorKeyPressedEventHandler(impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl) *ICoreWebView2AcceleratorKeyPressedEventHandler {
|
||||
return &ICoreWebView2AcceleratorKeyPressedEventHandler{
|
||||
vtbl: &_ICoreWebView2AcceleratorKeyPressedEventHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2ControllerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetIsVisible ComProc
|
||||
PutIsVisible ComProc
|
||||
GetBounds ComProc
|
||||
PutBounds ComProc
|
||||
GetZoomFactor ComProc
|
||||
PutZoomFactor ComProc
|
||||
AddZoomFactorChanged ComProc
|
||||
RemoveZoomFactorChanged ComProc
|
||||
SetBoundsAndZoomFactor ComProc
|
||||
MoveFocus ComProc
|
||||
AddMoveFocusRequested ComProc
|
||||
RemoveMoveFocusRequested ComProc
|
||||
AddGotFocus ComProc
|
||||
RemoveGotFocus ComProc
|
||||
AddLostFocus ComProc
|
||||
RemoveLostFocus ComProc
|
||||
AddAcceleratorKeyPressed ComProc
|
||||
RemoveAcceleratorKeyPressed ComProc
|
||||
GetParentWindow ComProc
|
||||
PutParentWindow ComProc
|
||||
NotifyParentWindowPositionChanged ComProc
|
||||
Close ComProc
|
||||
GetCoreWebView2 ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2Controller struct {
|
||||
vtbl *_ICoreWebView2ControllerVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) GetBounds() (*w32.Rect, error) {
|
||||
var err error
|
||||
var bounds w32.Rect
|
||||
_, _, err = i.vtbl.GetBounds.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&bounds)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return nil, err
|
||||
}
|
||||
return &bounds, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) PutBounds(bounds w32.Rect) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutBounds.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&bounds)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) MoveFocus(reason COREWEBVIEW2_MOVE_FOCUS_REASON) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.MoveFocus.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(reason),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) AddAcceleratorKeyPressed(eventHandler *ICoreWebView2AcceleratorKeyPressedEventHandler, token *_EventRegistrationToken) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.AddAcceleratorKeyPressed.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(eventHandler)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) PutIsVisible(isVisible bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsVisible.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(isVisible)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) GetICoreWebView2Controller2() *ICoreWebView2Controller2 {
|
||||
|
||||
var result *ICoreWebView2Controller2
|
||||
|
||||
iidICoreWebView2Controller2 := NewGUID("{c979903e-d4ca-4228-92eb-47ee3fa96eab}")
|
||||
i.vtbl.QueryInterface.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(iidICoreWebView2Controller2)),
|
||||
uintptr(unsafe.Pointer(&result)))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) NotifyParentWindowPositionChanged() error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.NotifyParentWindowPositionChanged.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) PutZoomFactor(zoomFactor float64) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.PutZoomFactor.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(math.Float64bits(zoomFactor)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller) GetZoomFactor() (float64, error) {
|
||||
var err error
|
||||
var zoomFactorUint64 uint64
|
||||
_, _, err = i.vtbl.GetZoomFactor.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&zoomFactorUint64)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return 0.0, err
|
||||
}
|
||||
return math.Float64frombits(zoomFactorUint64), nil
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2Controller2Vtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetIsVisible ComProc
|
||||
PutIsVisible ComProc
|
||||
GetBounds ComProc
|
||||
PutBounds ComProc
|
||||
GetZoomFactor ComProc
|
||||
PutZoomFactor ComProc
|
||||
AddZoomFactorChanged ComProc
|
||||
RemoveZoomFactorChanged ComProc
|
||||
SetBoundsAndZoomFactor ComProc
|
||||
MoveFocus ComProc
|
||||
AddMoveFocusRequested ComProc
|
||||
RemoveMoveFocusRequested ComProc
|
||||
AddGotFocus ComProc
|
||||
RemoveGotFocus ComProc
|
||||
AddLostFocus ComProc
|
||||
RemoveLostFocus ComProc
|
||||
AddAcceleratorKeyPressed ComProc
|
||||
RemoveAcceleratorKeyPressed ComProc
|
||||
GetParentWindow ComProc
|
||||
PutParentWindow ComProc
|
||||
NotifyParentWindowPositionChanged ComProc
|
||||
Close ComProc
|
||||
GetCoreWebView2 ComProc
|
||||
GetDefaultBackgroundColor ComProc
|
||||
PutDefaultBackgroundColor ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2Controller2 struct {
|
||||
vtbl *_ICoreWebView2Controller2Vtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller2) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller2) GetDefaultBackgroundColor() (*COREWEBVIEW2_COLOR, error) {
|
||||
var err error
|
||||
var backgroundColor *COREWEBVIEW2_COLOR
|
||||
_, _, err = i.vtbl.GetDefaultBackgroundColor.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&backgroundColor)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return nil, err
|
||||
}
|
||||
return backgroundColor, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Controller2) PutDefaultBackgroundColor(backgroundColor COREWEBVIEW2_COLOR) error {
|
||||
var err error
|
||||
|
||||
// Cast to a uint32 as that's what the call is expecting
|
||||
col := *(*uint32)(unsafe.Pointer(&backgroundColor))
|
||||
|
||||
_, _, err = i.vtbl.PutDefaultBackgroundColor.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(col),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type iCoreWebView2CreateCoreWebView2ControllerCompletedHandler struct {
|
||||
vtbl *_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl
|
||||
impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl
|
||||
}
|
||||
|
||||
func (i *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, errorCode uintptr, createdController *ICoreWebView2Controller) uintptr {
|
||||
return this.impl.CreateCoreWebView2ControllerCompleted(errorCode, createdController)
|
||||
}
|
||||
|
||||
type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
CreateCoreWebView2ControllerCompleted(errorCode uintptr, createdController *ICoreWebView2Controller) uintptr
|
||||
}
|
||||
|
||||
var _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn = _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler {
|
||||
return &iCoreWebView2CreateCoreWebView2ControllerCompletedHandler{
|
||||
vtbl: &_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2HttpHeadersCollectionIteratorVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetCurrentHeader ComProc
|
||||
GetHasCurrentHeader ComProc
|
||||
MoveNext ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2HttpHeadersCollectionIterator struct {
|
||||
vtbl *_ICoreWebView2HttpHeadersCollectionIteratorVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2HttpHeadersCollectionIterator) Release() error {
|
||||
return i.vtbl.CallRelease(unsafe.Pointer(i))
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2HttpHeadersCollectionIterator) HasCurrentHeader() (bool, error) {
|
||||
var hasHeader int32
|
||||
res, _, err := i.vtbl.GetHasCurrentHeader.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&hasHeader)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return false, syscall.Errno(res)
|
||||
}
|
||||
return hasHeader != 0, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2HttpHeadersCollectionIterator) GetCurrentHeader() (string, string, error) {
|
||||
// Create *uint16 to hold result
|
||||
var _name *uint16
|
||||
var _value *uint16
|
||||
res, _, err := i.vtbl.GetCurrentHeader.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&_name)),
|
||||
uintptr(unsafe.Pointer(&_value)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return "", "", err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return "", "", syscall.Errno(res)
|
||||
}
|
||||
// Get result and cleanup
|
||||
name := windows.UTF16PtrToString(_name)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(_name))
|
||||
value := windows.UTF16PtrToString(_value)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(_value))
|
||||
return name, value, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2HttpHeadersCollectionIterator) MoveNext() (bool, error) {
|
||||
var next int32
|
||||
res, _, err := i.vtbl.MoveNext.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&next)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return false, syscall.Errno(res)
|
||||
}
|
||||
return next != 0, nil
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
ERROR_ELEMENT_NOT_FOUND syscall.Errno = 0x80070490
|
||||
)
|
||||
|
||||
type _ICoreWebView2HttpRequestHeadersVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetHeader ComProc
|
||||
GetHeaders ComProc
|
||||
Contains ComProc
|
||||
SetHeader ComProc
|
||||
RemoveHeader ComProc
|
||||
GetIterator ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2HttpRequestHeaders struct {
|
||||
vtbl *_ICoreWebView2HttpRequestHeadersVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2HttpRequestHeaders) Release() error {
|
||||
return i.vtbl.CallRelease(unsafe.Pointer(i))
|
||||
}
|
||||
|
||||
// GetHeader returns the value of the specified header. If the header is not found
|
||||
// ERROR_ELEMENT_NOT_FOUND is returned as error.
|
||||
func (i *ICoreWebView2HttpRequestHeaders) GetHeader(name string) (string, error) {
|
||||
_name, err := windows.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var _value *uint16
|
||||
res, _, err := i.vtbl.GetHeader.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(_name)),
|
||||
uintptr(unsafe.Pointer(&_value)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return "", err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return "", syscall.Errno(res)
|
||||
}
|
||||
|
||||
value := windows.UTF16PtrToString(_value)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(_value))
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// SetHeader sets the specified header to the value.
|
||||
func (i *ICoreWebView2HttpRequestHeaders) SetHeader(name, value string) error {
|
||||
_name, err := windows.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_value, err := windows.UTF16PtrFromString(value)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res, _, err := i.vtbl.SetHeader.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(_name)),
|
||||
uintptr(unsafe.Pointer(_value)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return syscall.Errno(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetIterator returns an iterator over the collection of request headers. Make sure to call
|
||||
// Release on the returned Object after finished using it.
|
||||
func (i *ICoreWebView2HttpRequestHeaders) GetIterator() (*ICoreWebView2HttpHeadersCollectionIterator, error) {
|
||||
var headers *ICoreWebView2HttpHeadersCollectionIterator
|
||||
res, _, err := i.vtbl.GetIterator.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&headers)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return nil, err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return nil, syscall.Errno(res)
|
||||
}
|
||||
return headers, nil
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type _ICoreWebView2NavigationCompletedEventArgsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetIsSuccess ComProc
|
||||
GetWebErrorStatus ComProc
|
||||
GetNavigationId ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2NavigationCompletedEventArgs struct {
|
||||
vtbl *_ICoreWebView2NavigationCompletedEventArgsVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2NavigationCompletedEventArgs) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type _ICoreWebView2NavigationCompletedEventHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2NavigationCompletedEventHandler struct {
|
||||
vtbl *_ICoreWebView2NavigationCompletedEventHandlerVtbl
|
||||
impl _ICoreWebView2NavigationCompletedEventHandlerImpl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2NavigationCompletedEventHandler) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
func _ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface(this *ICoreWebView2NavigationCompletedEventHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this *ICoreWebView2NavigationCompletedEventHandler, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
|
||||
return this.impl.NavigationCompleted(sender, args)
|
||||
}
|
||||
|
||||
type _ICoreWebView2NavigationCompletedEventHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr
|
||||
}
|
||||
|
||||
var _ICoreWebView2NavigationCompletedEventHandlerFn = _ICoreWebView2NavigationCompletedEventHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2NavigationCompletedEventHandler(impl _ICoreWebView2NavigationCompletedEventHandlerImpl) *ICoreWebView2NavigationCompletedEventHandler {
|
||||
return &ICoreWebView2NavigationCompletedEventHandler{
|
||||
vtbl: &_ICoreWebView2NavigationCompletedEventHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2ProcessFailedEventArgsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetProcessFailedKind ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2ProcessFailedEventArgs struct {
|
||||
vtbl *_ICoreWebView2ProcessFailedEventArgsVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2ProcessFailedEventArgs) GetProcessFailedKind() (COREWEBVIEW2_PROCESS_FAILED_KIND, error) {
|
||||
kind := COREWEBVIEW2_PROCESS_FAILED_KIND(0xffffffff)
|
||||
hr, _, err := i.vtbl.GetProcessFailedKind.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&kind)),
|
||||
)
|
||||
|
||||
if windows.Handle(hr) != windows.S_OK {
|
||||
return 0, syscall.Errno(hr)
|
||||
}
|
||||
|
||||
if kind == 0xffffffff {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("unknown error")
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return kind, nil
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type _ICoreWebView2ProcessFailedEventHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2ProcessFailedEventHandler struct {
|
||||
vtbl *_ICoreWebView2ProcessFailedEventHandlerVtbl
|
||||
impl _ICoreWebView2ProcessFailedEventHandlerImpl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2ProcessFailedEventHandler) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
func _ICoreWebView2ProcessFailedEventHandlerIUnknownQueryInterface(this *ICoreWebView2ProcessFailedEventHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2ProcessFailedEventHandlerIUnknownAddRef(this *ICoreWebView2ProcessFailedEventHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2ProcessFailedEventHandlerIUnknownRelease(this *ICoreWebView2ProcessFailedEventHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2ProcessFailedEventHandlerInvoke(this *ICoreWebView2ProcessFailedEventHandler, sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr {
|
||||
return this.impl.ProcessFailed(sender, args)
|
||||
}
|
||||
|
||||
type _ICoreWebView2ProcessFailedEventHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
ProcessFailed(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr
|
||||
}
|
||||
|
||||
var _ICoreWebView2ProcessFailedEventHandlerFn = _ICoreWebView2ProcessFailedEventHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2ProcessFailedEventHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2ProcessFailedEventHandler(impl _ICoreWebView2ProcessFailedEventHandlerImpl) *ICoreWebView2ProcessFailedEventHandler {
|
||||
return &ICoreWebView2ProcessFailedEventHandler{
|
||||
vtbl: &_ICoreWebView2ProcessFailedEventHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
@ -1,271 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2SettingsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetIsScriptEnabled ComProc
|
||||
PutIsScriptEnabled ComProc
|
||||
GetIsWebMessageEnabled ComProc
|
||||
PutIsWebMessageEnabled ComProc
|
||||
GetAreDefaultScriptDialogsEnabled ComProc
|
||||
PutAreDefaultScriptDialogsEnabled ComProc
|
||||
GetIsStatusBarEnabled ComProc
|
||||
PutIsStatusBarEnabled ComProc
|
||||
GetAreDevToolsEnabled ComProc
|
||||
PutAreDevToolsEnabled ComProc
|
||||
GetAreDefaultContextMenusEnabled ComProc
|
||||
PutAreDefaultContextMenusEnabled ComProc
|
||||
GetAreHostObjectsAllowed ComProc
|
||||
PutAreHostObjectsAllowed ComProc
|
||||
GetIsZoomControlEnabled ComProc
|
||||
PutIsZoomControlEnabled ComProc
|
||||
GetIsBuiltInErrorPageEnabled ComProc
|
||||
PutIsBuiltInErrorPageEnabled ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2Settings struct {
|
||||
vtbl *_ICoreWebView2SettingsVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetIsScriptEnabled() (bool, error) {
|
||||
var err error
|
||||
var isScriptEnabled bool
|
||||
_, _, err = i.vtbl.GetIsScriptEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&isScriptEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return isScriptEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutIsScriptEnabled(isScriptEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsScriptEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(isScriptEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetIsWebMessageEnabled() (bool, error) {
|
||||
var err error
|
||||
var isWebMessageEnabled bool
|
||||
_, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&isWebMessageEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return isWebMessageEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(isWebMessageEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
|
||||
var err error
|
||||
var areDefaultScriptDialogsEnabled bool
|
||||
_, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return areDefaultScriptDialogsEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetIsStatusBarEnabled() (bool, error) {
|
||||
var err error
|
||||
var isStatusBarEnabled bool
|
||||
_, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&isStatusBarEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return isStatusBarEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(isStatusBarEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetAreDevToolsEnabled() (bool, error) {
|
||||
var err error
|
||||
var areDevToolsEnabled bool
|
||||
_, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&areDevToolsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return areDevToolsEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(areDevToolsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetAreDefaultContextMenusEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutAreDefaultContextMenusEnabled(enabled bool) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetAreHostObjectsAllowed() (bool, error) {
|
||||
var err error
|
||||
var allowed bool
|
||||
_, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&allowed)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return allowed, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutAreHostObjectsAllowed(allowed bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(allowed)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetIsZoomControlEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutIsZoomControlEnabled(enabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) GetIsBuiltInErrorPageEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2Settings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2WebResourceRequestVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetUri ComProc
|
||||
PutUri ComProc
|
||||
GetMethod ComProc
|
||||
PutMethod ComProc
|
||||
GetContent ComProc
|
||||
PutContent ComProc
|
||||
GetHeaders ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2WebResourceRequest struct {
|
||||
vtbl *_ICoreWebView2WebResourceRequestVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceRequest) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceRequest) GetMethod() (string, error) {
|
||||
// Create *uint16 to hold result
|
||||
var _method *uint16
|
||||
res, _, err := i.vtbl.GetMethod.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&_method)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return "", err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return "", syscall.Errno(res)
|
||||
}
|
||||
// Get result and cleanup
|
||||
uri := windows.UTF16PtrToString(_method)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(_method))
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceRequest) GetUri() (string, error) {
|
||||
var err error
|
||||
// Create *uint16 to hold result
|
||||
var _uri *uint16
|
||||
_, _, err = i.vtbl.GetUri.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&_uri)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return "", err
|
||||
} // Get result and cleanup
|
||||
uri := windows.UTF16PtrToString(_uri)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(_uri))
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
// GetContent returns the body of the request. Returns nil if there's no body. Make sure to call
|
||||
// Release on the returned IStream after finished using it.
|
||||
func (i *ICoreWebView2WebResourceRequest) GetContent() (*IStream, error) {
|
||||
var stream *IStream
|
||||
res, _, err := i.vtbl.GetContent.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&stream)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return nil, err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return nil, syscall.Errno(res)
|
||||
}
|
||||
return stream, nil
|
||||
}
|
||||
|
||||
// GetHeaders returns the mutable HTTP request headers. Make sure to call
|
||||
// Release on the returned Object after finished using it.
|
||||
func (i *ICoreWebView2WebResourceRequest) GetHeaders() (*ICoreWebView2HttpRequestHeaders, error) {
|
||||
var headers *ICoreWebView2HttpRequestHeaders
|
||||
res, _, err := i.vtbl.GetHeaders.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&headers)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return nil, err
|
||||
}
|
||||
if windows.Handle(res) != windows.S_OK {
|
||||
return nil, syscall.Errno(res)
|
||||
}
|
||||
return headers, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceRequest) Release() error {
|
||||
return i.vtbl.CallRelease(unsafe.Pointer(i))
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _ICoreWebView2WebResourceRequestedEventArgsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetRequest ComProc
|
||||
GetResponse ComProc
|
||||
PutResponse ComProc
|
||||
GetDeferral ComProc
|
||||
GetResourceContext ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2WebResourceRequestedEventArgs struct {
|
||||
vtbl *_ICoreWebView2WebResourceRequestedEventArgsVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceRequestedEventArgs) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceRequestedEventArgs) PutResponse(response *ICoreWebView2WebResourceResponse) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutResponse.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(response)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceRequestedEventArgs) GetRequest() (*ICoreWebView2WebResourceRequest, error) {
|
||||
var err error
|
||||
var request *ICoreWebView2WebResourceRequest
|
||||
_, _, err = i.vtbl.GetRequest.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&request)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return nil, err
|
||||
}
|
||||
return request, nil
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type _ICoreWebView2WebResourceRequestedEventHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type iCoreWebView2WebResourceRequestedEventHandler struct {
|
||||
vtbl *_ICoreWebView2WebResourceRequestedEventHandlerVtbl
|
||||
impl _ICoreWebView2WebResourceRequestedEventHandlerImpl
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebResourceRequestedEventHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebResourceRequestedEventHandlerInvoke(this *iCoreWebView2WebResourceRequestedEventHandler, sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
|
||||
return this.impl.WebResourceRequested(sender, args)
|
||||
}
|
||||
|
||||
type _ICoreWebView2WebResourceRequestedEventHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr
|
||||
}
|
||||
|
||||
var _ICoreWebView2WebResourceRequestedEventHandlerFn = _ICoreWebView2WebResourceRequestedEventHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2WebResourceRequestedEventHandler(impl _ICoreWebView2WebResourceRequestedEventHandlerImpl) *iCoreWebView2WebResourceRequestedEventHandler {
|
||||
return &iCoreWebView2WebResourceRequestedEventHandler{
|
||||
vtbl: &_ICoreWebView2WebResourceRequestedEventHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type _ICoreWebView2WebResourceResponseVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetContent ComProc
|
||||
PutContent ComProc
|
||||
GetHeaders ComProc
|
||||
GetStatusCode ComProc
|
||||
PutStatusCode ComProc
|
||||
GetReasonPhrase ComProc
|
||||
PutReasonPhrase ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2WebResourceResponse struct {
|
||||
vtbl *_ICoreWebView2WebResourceResponseVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceResponse) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2WebResourceResponse) Release() error {
|
||||
return i.vtbl.CallRelease(unsafe.Pointer(i))
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
type iCoreWebView2_2Vtbl struct {
|
||||
iCoreWebView2Vtbl
|
||||
AddWebResourceResponseReceived ComProc
|
||||
RemoveWebResourceResponseReceived ComProc
|
||||
NavigateWithWebResourceRequest ComProc
|
||||
AddDomContentLoaded ComProc
|
||||
RemoveDomContentLoaded ComProc
|
||||
GetCookieManager ComProc
|
||||
GetEnvironment ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2_2 struct {
|
||||
vtbl *iCoreWebView2_2Vtbl
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type iCoreWebView2_3Vtbl struct {
|
||||
iCoreWebView2_2Vtbl
|
||||
TrySuspend ComProc
|
||||
Resume ComProc
|
||||
GetIsSuspended ComProc
|
||||
SetVirtualHostNameToFolderMapping ComProc
|
||||
ClearVirtualHostNameToFolderMapping ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2_3 struct {
|
||||
vtbl *iCoreWebView2_3Vtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2_3) SetVirtualHostNameToFolderMapping(hostName, folderPath string, accessKind COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND) error {
|
||||
_hostName, err := windows.UTF16PtrFromString(hostName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_folderPath, err := windows.UTF16PtrFromString(folderPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = i.vtbl.SetVirtualHostNameToFolderMapping.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(_hostName)),
|
||||
uintptr(unsafe.Pointer(_folderPath)),
|
||||
uintptr(accessKind),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 {
|
||||
var result *ICoreWebView2_3
|
||||
|
||||
iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}")
|
||||
_, _, _ = i.vtbl.QueryInterface.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(iidICoreWebView2_3)),
|
||||
uintptr(unsafe.Pointer(&result)))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (e *Chromium) GetICoreWebView2_3() *ICoreWebView2_3 {
|
||||
return e.webview.GetICoreWebView2_3()
|
||||
}
|
@ -1,397 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// ICoreWebviewSettings is the merged settings class
|
||||
|
||||
type _ICoreWebViewSettingsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetIsScriptEnabled ComProc
|
||||
PutIsScriptEnabled ComProc
|
||||
GetIsWebMessageEnabled ComProc
|
||||
PutIsWebMessageEnabled ComProc
|
||||
GetAreDefaultScriptDialogsEnabled ComProc
|
||||
PutAreDefaultScriptDialogsEnabled ComProc
|
||||
GetIsStatusBarEnabled ComProc
|
||||
PutIsStatusBarEnabled ComProc
|
||||
GetAreDevToolsEnabled ComProc
|
||||
PutAreDevToolsEnabled ComProc
|
||||
GetAreDefaultContextMenusEnabled ComProc
|
||||
PutAreDefaultContextMenusEnabled ComProc
|
||||
GetAreHostObjectsAllowed ComProc
|
||||
PutAreHostObjectsAllowed ComProc
|
||||
GetIsZoomControlEnabled ComProc
|
||||
PutIsZoomControlEnabled ComProc
|
||||
GetIsBuiltInErrorPageEnabled ComProc
|
||||
PutIsBuiltInErrorPageEnabled ComProc
|
||||
GetUserAgent ComProc // ICoreWebView2Settings2: SDK 1.0.864.35
|
||||
PutUserAgent ComProc
|
||||
GetAreBrowserAcceleratorKeysEnabled ComProc // ICoreWebView2Settings3: SDK 1.0.864.35
|
||||
PutAreBrowserAcceleratorKeysEnabled ComProc
|
||||
GetIsPasswordAutosaveEnabled ComProc // ICoreWebView2Settings4: SDK 1.0.902.49
|
||||
PutIsPasswordAutosaveEnabled ComProc
|
||||
GetIsGeneralAutofillEnabled ComProc
|
||||
PutIsGeneralAutofillEnabled ComProc
|
||||
GetIsPinchZoomEnabled ComProc // ICoreWebView2Settings5: SDK 1.0.902.49
|
||||
PutIsPinchZoomEnabled ComProc
|
||||
GetIsSwipeNavigationEnabled ComProc // ICoreWebView2Settings6: SDK 1.0.992.28
|
||||
PutIsSwipeNavigationEnabled ComProc
|
||||
}
|
||||
|
||||
type ICoreWebViewSettings struct {
|
||||
vtbl *_ICoreWebViewSettingsVtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) AddRef() uintptr {
|
||||
return i.AddRef()
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetIsScriptEnabled() (bool, error) {
|
||||
var err error
|
||||
var isScriptEnabled bool
|
||||
_, _, err = i.vtbl.GetIsScriptEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&isScriptEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return isScriptEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutIsScriptEnabled(isScriptEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsScriptEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(isScriptEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetIsWebMessageEnabled() (bool, error) {
|
||||
var err error
|
||||
var isWebMessageEnabled bool
|
||||
_, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&isWebMessageEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return isWebMessageEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(isWebMessageEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
|
||||
var err error
|
||||
var areDefaultScriptDialogsEnabled bool
|
||||
_, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return areDefaultScriptDialogsEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetIsStatusBarEnabled() (bool, error) {
|
||||
var err error
|
||||
var isStatusBarEnabled bool
|
||||
_, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&isStatusBarEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return isStatusBarEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(isStatusBarEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetAreDevToolsEnabled() (bool, error) {
|
||||
var err error
|
||||
var areDevToolsEnabled bool
|
||||
_, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&areDevToolsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return areDevToolsEnabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(areDevToolsEnabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetAreDefaultContextMenusEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutAreDefaultContextMenusEnabled(enabled bool) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetAreHostObjectsAllowed() (bool, error) {
|
||||
var err error
|
||||
var allowed bool
|
||||
_, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&allowed)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return allowed, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutAreHostObjectsAllowed(allowed bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(allowed)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetIsZoomControlEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutIsZoomControlEnabled(enabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetIsBuiltInErrorPageEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetUserAgent() (string, error) {
|
||||
var err error
|
||||
// Create *uint16 to hold result
|
||||
var _userAgent *uint16
|
||||
_, _, err = i.vtbl.GetUserAgent.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(_userAgent)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return "", err
|
||||
} // Get result and cleanup
|
||||
userAgent := windows.UTF16PtrToString(_userAgent)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(_userAgent))
|
||||
return userAgent, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutUserAgent(userAgent string) error {
|
||||
var err error
|
||||
// Convert string 'userAgent' to *uint16
|
||||
_userAgent, err := windows.UTF16PtrFromString(userAgent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = i.vtbl.PutUserAgent.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(_userAgent)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetAreBrowserAcceleratorKeysEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetAreBrowserAcceleratorKeysEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutAreBrowserAcceleratorKeysEnabled(enabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutAreBrowserAcceleratorKeysEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetIsPinchZoomEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetIsPinchZoomEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutIsPinchZoomEnabled(enabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsPinchZoomEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) GetIsSwipeNavigationEnabled() (bool, error) {
|
||||
var err error
|
||||
var enabled bool
|
||||
_, _, err = i.vtbl.GetIsSwipeNavigationEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return false, err
|
||||
}
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebViewSettings) PutIsSwipeNavigationEnabled(enabled bool) error {
|
||||
var err error
|
||||
|
||||
_, _, err = i.vtbl.PutIsSwipeNavigationEnabled.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(boolToInt(enabled)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _IStreamVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Read ComProc
|
||||
Write ComProc
|
||||
}
|
||||
|
||||
type IStream struct {
|
||||
vtbl *_IStreamVtbl
|
||||
}
|
||||
|
||||
func (i *IStream) Release() error {
|
||||
return i.vtbl.CallRelease(unsafe.Pointer(i))
|
||||
}
|
||||
|
||||
func (i *IStream) Read(p []byte) (int, error) {
|
||||
bufLen := len(p)
|
||||
if bufLen == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var n int
|
||||
res, _, err := i.vtbl.Read.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&p[0])),
|
||||
uintptr(bufLen),
|
||||
uintptr(unsafe.Pointer(&n)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
switch windows.Handle(res) {
|
||||
case windows.S_OK:
|
||||
// The buffer has been completely filled
|
||||
return n, nil
|
||||
case windows.S_FALSE:
|
||||
// The buffer has been filled with less than len data and the stream is EOF
|
||||
return n, io.EOF
|
||||
default:
|
||||
return 0, syscall.Errno(res)
|
||||
}
|
||||
}
|
@ -1,419 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type Rect = w32.Rect
|
||||
|
||||
type Chromium struct {
|
||||
hwnd uintptr
|
||||
controller *ICoreWebView2Controller
|
||||
webview *ICoreWebView2
|
||||
inited uintptr
|
||||
envCompleted *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
|
||||
controllerCompleted *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler
|
||||
webMessageReceived *iCoreWebView2WebMessageReceivedEventHandler
|
||||
permissionRequested *iCoreWebView2PermissionRequestedEventHandler
|
||||
webResourceRequested *iCoreWebView2WebResourceRequestedEventHandler
|
||||
acceleratorKeyPressed *ICoreWebView2AcceleratorKeyPressedEventHandler
|
||||
navigationCompleted *ICoreWebView2NavigationCompletedEventHandler
|
||||
processFailed *ICoreWebView2ProcessFailedEventHandler
|
||||
|
||||
environment *ICoreWebView2Environment
|
||||
|
||||
padding Rect
|
||||
|
||||
// Settings
|
||||
Debug bool
|
||||
DataPath string
|
||||
BrowserPath string
|
||||
AdditionalBrowserArgs []string
|
||||
|
||||
// permissions
|
||||
permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState
|
||||
globalPermission *CoreWebView2PermissionState
|
||||
|
||||
// Callbacks
|
||||
MessageCallback func(string)
|
||||
WebResourceRequestedCallback func(request *ICoreWebView2WebResourceRequest, args *ICoreWebView2WebResourceRequestedEventArgs)
|
||||
NavigationCompletedCallback func(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs)
|
||||
ProcessFailedCallback func(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs)
|
||||
AcceleratorKeyCallback func(uint) bool
|
||||
}
|
||||
|
||||
func NewChromium() *Chromium {
|
||||
e := &Chromium{}
|
||||
/*
|
||||
All these handlers are passed to native code through syscalls with 'uintptr(unsafe.Pointer(handler))' and we know
|
||||
that a pointer to those will be kept in the native code. Furthermore these handlers als contain pointer to other Go
|
||||
structs like the vtable.
|
||||
This violates the unsafe.Pointer rule '(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.' because
|
||||
theres no guarantee that Go doesn't move these objects.
|
||||
AFAIK currently the Go runtime doesn't move HEAP objects, so we should be safe with these handlers. But they don't
|
||||
guarantee it, because in the future Go might use a compacting GC.
|
||||
There's a proposal to add a runtime.Pin function, to prevent moving pinned objects, which would allow to easily fix
|
||||
this issue by just pinning the handlers. The https://go-review.googlesource.com/c/go/+/367296/ should land in Go 1.19.
|
||||
*/
|
||||
e.envCompleted = newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(e)
|
||||
e.controllerCompleted = newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(e)
|
||||
e.webMessageReceived = newICoreWebView2WebMessageReceivedEventHandler(e)
|
||||
e.permissionRequested = newICoreWebView2PermissionRequestedEventHandler(e)
|
||||
e.webResourceRequested = newICoreWebView2WebResourceRequestedEventHandler(e)
|
||||
e.acceleratorKeyPressed = newICoreWebView2AcceleratorKeyPressedEventHandler(e)
|
||||
e.navigationCompleted = newICoreWebView2NavigationCompletedEventHandler(e)
|
||||
e.processFailed = newICoreWebView2ProcessFailedEventHandler(e)
|
||||
e.permissions = make(map[CoreWebView2PermissionKind]CoreWebView2PermissionState)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Chromium) Embed(hwnd uintptr) bool {
|
||||
e.hwnd = hwnd
|
||||
|
||||
dataPath := e.DataPath
|
||||
if dataPath == "" {
|
||||
currentExePath := make([]uint16, windows.MAX_PATH)
|
||||
_, err := windows.GetModuleFileName(windows.Handle(0), ¤tExePath[0], windows.MAX_PATH)
|
||||
if err != nil {
|
||||
// What to do here?
|
||||
return false
|
||||
}
|
||||
currentExeName := filepath.Base(windows.UTF16ToString(currentExePath))
|
||||
dataPath = filepath.Join(os.Getenv("AppData"), currentExeName)
|
||||
}
|
||||
|
||||
if e.BrowserPath != "" {
|
||||
if _, err := os.Stat(e.BrowserPath); errors.Is(err, os.ErrNotExist) {
|
||||
log.Printf("Browser path %s does not exist", e.BrowserPath)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
browserArgs := strings.Join(e.AdditionalBrowserArgs, " ")
|
||||
if err := createCoreWebView2EnvironmentWithOptions(e.BrowserPath, dataPath, e.envCompleted, browserArgs); err != nil {
|
||||
log.Printf("Error calling Webview2Loader: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
var msg w32.Msg
|
||||
for {
|
||||
if atomic.LoadUintptr(&e.inited) != 0 {
|
||||
break
|
||||
}
|
||||
r, _, _ := w32.User32GetMessageW.Call(
|
||||
uintptr(unsafe.Pointer(&msg)),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
w32.User32TranslateMessage.Call(uintptr(unsafe.Pointer(&msg)))
|
||||
w32.User32DispatchMessageW.Call(uintptr(unsafe.Pointer(&msg)))
|
||||
}
|
||||
e.Init("window.external={invoke:s=>window.chrome.webview.postMessage(s)}")
|
||||
return true
|
||||
}
|
||||
|
||||
func (e *Chromium) SetPadding(padding Rect) {
|
||||
if e.padding.Top == padding.Top && e.padding.Bottom == padding.Bottom &&
|
||||
e.padding.Left == padding.Left && e.padding.Right == padding.Right {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
e.padding = padding
|
||||
e.Resize()
|
||||
}
|
||||
|
||||
func (e *Chromium) Resize() {
|
||||
if e.hwnd == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var bounds w32.Rect
|
||||
w32.User32GetClientRect.Call(e.hwnd, uintptr(unsafe.Pointer(&bounds)))
|
||||
|
||||
bounds.Top += e.padding.Top
|
||||
bounds.Bottom -= e.padding.Bottom
|
||||
bounds.Left += e.padding.Left
|
||||
bounds.Right -= e.padding.Right
|
||||
|
||||
e.SetSize(bounds)
|
||||
}
|
||||
|
||||
func (e *Chromium) Navigate(url string) {
|
||||
e.webview.vtbl.Navigate.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(url))),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *Chromium) Init(script string) {
|
||||
e.webview.vtbl.AddScriptToExecuteOnDocumentCreated.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(script))),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
func (e *Chromium) Eval(script string) {
|
||||
|
||||
_script, err := windows.UTF16PtrFromString(script)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
e.webview.vtbl.ExecuteScript.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(_script)),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
func (e *Chromium) Show() error {
|
||||
return e.controller.PutIsVisible(true)
|
||||
}
|
||||
|
||||
func (e *Chromium) Hide() error {
|
||||
return e.controller.PutIsVisible(false)
|
||||
}
|
||||
|
||||
func (e *Chromium) QueryInterface(_, _ uintptr) uintptr {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) AddRef() uintptr {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (e *Chromium) Release() uintptr {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (e *Chromium) EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr {
|
||||
if int32(res) < 0 {
|
||||
log.Fatalf("Creating environment failed with %08x: %s", res, syscall.Errno(res))
|
||||
}
|
||||
env.vtbl.AddRef.Call(uintptr(unsafe.Pointer(env)))
|
||||
e.environment = env
|
||||
|
||||
env.vtbl.CreateCoreWebView2Controller.Call(
|
||||
uintptr(unsafe.Pointer(env)),
|
||||
e.hwnd,
|
||||
uintptr(unsafe.Pointer(e.controllerCompleted)),
|
||||
)
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller *ICoreWebView2Controller) uintptr {
|
||||
if int32(res) < 0 {
|
||||
log.Fatalf("Creating controller failed with %08x: %s", res, syscall.Errno(res))
|
||||
}
|
||||
controller.vtbl.AddRef.Call(uintptr(unsafe.Pointer(controller)))
|
||||
e.controller = controller
|
||||
|
||||
var token _EventRegistrationToken
|
||||
controller.vtbl.GetCoreWebView2.Call(
|
||||
uintptr(unsafe.Pointer(controller)),
|
||||
uintptr(unsafe.Pointer(&e.webview)),
|
||||
)
|
||||
e.webview.vtbl.AddRef.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
)
|
||||
e.webview.vtbl.AddWebMessageReceived.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(e.webMessageReceived)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
e.webview.vtbl.AddPermissionRequested.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(e.permissionRequested)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
e.webview.vtbl.AddWebResourceRequested.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(e.webResourceRequested)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
e.webview.vtbl.AddNavigationCompleted.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(e.navigationCompleted)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
e.webview.vtbl.AddProcessFailed.Call(
|
||||
uintptr(unsafe.Pointer(e.webview)),
|
||||
uintptr(unsafe.Pointer(e.processFailed)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
|
||||
e.controller.AddAcceleratorKeyPressed(e.acceleratorKeyPressed, &token)
|
||||
|
||||
atomic.StoreUintptr(&e.inited, 1)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
|
||||
var message *uint16
|
||||
args.vtbl.TryGetWebMessageAsString.Call(
|
||||
uintptr(unsafe.Pointer(args)),
|
||||
uintptr(unsafe.Pointer(&message)),
|
||||
)
|
||||
if e.MessageCallback != nil {
|
||||
e.MessageCallback(w32.Utf16PtrToString(message))
|
||||
}
|
||||
sender.vtbl.PostWebMessageAsString.Call(
|
||||
uintptr(unsafe.Pointer(sender)),
|
||||
uintptr(unsafe.Pointer(message)),
|
||||
)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(message))
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) SetPermission(kind CoreWebView2PermissionKind, state CoreWebView2PermissionState) {
|
||||
e.permissions[kind] = state
|
||||
}
|
||||
|
||||
func (e *Chromium) SetGlobalPermission(state CoreWebView2PermissionState) {
|
||||
e.globalPermission = &state
|
||||
}
|
||||
|
||||
func (e *Chromium) PermissionRequested(_ *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
|
||||
var kind CoreWebView2PermissionKind
|
||||
args.vtbl.GetPermissionKind.Call(
|
||||
uintptr(unsafe.Pointer(args)),
|
||||
uintptr(kind),
|
||||
)
|
||||
var result CoreWebView2PermissionState
|
||||
if e.globalPermission != nil {
|
||||
result = *e.globalPermission
|
||||
} else {
|
||||
var ok bool
|
||||
result, ok = e.permissions[kind]
|
||||
if !ok {
|
||||
result = CoreWebView2PermissionStateDefault
|
||||
}
|
||||
}
|
||||
args.vtbl.PutState.Call(
|
||||
uintptr(unsafe.Pointer(args)),
|
||||
uintptr(result),
|
||||
)
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
|
||||
req, err := args.GetRequest()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer req.Release()
|
||||
|
||||
if e.WebResourceRequestedCallback != nil {
|
||||
e.WebResourceRequestedCallback(req, args)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) AddWebResourceRequestedFilter(filter string, ctx COREWEBVIEW2_WEB_RESOURCE_CONTEXT) {
|
||||
err := e.webview.AddWebResourceRequestedFilter(filter, ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Chromium) Environment() *ICoreWebView2Environment {
|
||||
return e.environment
|
||||
}
|
||||
|
||||
// AcceleratorKeyPressed is called when an accelerator key is pressed.
|
||||
// If the AcceleratorKeyCallback method has been set, it will defer handling of the keypress
|
||||
// to the callback. That callback returns a bool indicating if the event was handled.
|
||||
func (e *Chromium) AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
|
||||
if e.AcceleratorKeyCallback == nil {
|
||||
return 0
|
||||
}
|
||||
eventKind, _ := args.GetKeyEventKind()
|
||||
if eventKind == COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN ||
|
||||
eventKind == COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN {
|
||||
virtualKey, _ := args.GetVirtualKey()
|
||||
status, _ := args.GetPhysicalKeyStatus()
|
||||
if !status.WasKeyDown {
|
||||
args.PutHandled(e.AcceleratorKeyCallback(virtualKey))
|
||||
return 0
|
||||
}
|
||||
}
|
||||
args.PutHandled(false)
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) GetSettings() (*ICoreWebViewSettings, error) {
|
||||
return e.webview.GetSettings()
|
||||
}
|
||||
|
||||
func (e *Chromium) GetController() *ICoreWebView2Controller {
|
||||
return e.controller
|
||||
}
|
||||
|
||||
func boolToInt(input bool) int {
|
||||
if input {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
|
||||
if e.NavigationCompletedCallback != nil {
|
||||
e.NavigationCompletedCallback(sender, args)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) ProcessFailed(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr {
|
||||
if e.ProcessFailedCallback != nil {
|
||||
e.ProcessFailedCallback(sender, args)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Chromium) NotifyParentWindowPositionChanged() error {
|
||||
//It looks like the wndproc function is called before the controller initialization is complete.
|
||||
//Because of this the controller is nil
|
||||
if e.controller == nil {
|
||||
return nil
|
||||
}
|
||||
return e.controller.NotifyParentWindowPositionChanged()
|
||||
}
|
||||
|
||||
func (e *Chromium) Focus() {
|
||||
err := e.controller.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Chromium) PutZoomFactor(zoomFactor float64) {
|
||||
err := e.controller.PutZoomFactor(zoomFactor)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Chromium) OpenDevToolsWindow() {
|
||||
e.webview.OpenDevToolsWindow()
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (e *Chromium) SetSize(bounds w32.Rect) {
|
||||
if e.controller == nil {
|
||||
return
|
||||
}
|
||||
|
||||
e.controller.vtbl.PutBounds.Call(
|
||||
uintptr(unsafe.Pointer(e.controller)),
|
||||
uintptr(bounds.Left),
|
||||
uintptr(bounds.Top),
|
||||
uintptr(bounds.Right),
|
||||
uintptr(bounds.Bottom),
|
||||
)
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (e *Chromium) SetSize(bounds w32.Rect) {
|
||||
if e.controller == nil {
|
||||
return
|
||||
}
|
||||
|
||||
e.controller.vtbl.PutBounds.Call(
|
||||
uintptr(unsafe.Pointer(e.controller)),
|
||||
uintptr(unsafe.Pointer(&bounds)),
|
||||
)
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
|
||||
)
|
||||
|
||||
func (e *Chromium) SetSize(bounds w32.Rect) {
|
||||
if e.controller == nil {
|
||||
return
|
||||
}
|
||||
|
||||
words := (*[2]uintptr)(unsafe.Pointer(&bounds))
|
||||
e.controller.vtbl.PutBounds.Call(
|
||||
uintptr(unsafe.Pointer(e.controller)),
|
||||
words[0],
|
||||
words[1],
|
||||
)
|
||||
}
|
@ -1,503 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.LockOSThread()
|
||||
|
||||
r, _, _ := w32.Ole32CoInitializeEx.Call(0, 2)
|
||||
if int(r) < 0 {
|
||||
log.Printf("Warning: CoInitializeEx call failed: E=%08x", r)
|
||||
}
|
||||
}
|
||||
|
||||
type _EventRegistrationToken struct {
|
||||
value int64
|
||||
}
|
||||
|
||||
type CoreWebView2PermissionKind uint32
|
||||
|
||||
const (
|
||||
CoreWebView2PermissionKindUnknownPermission CoreWebView2PermissionKind = iota
|
||||
CoreWebView2PermissionKindMicrophone
|
||||
CoreWebView2PermissionKindCamera
|
||||
CoreWebView2PermissionKindGeolocation
|
||||
CoreWebView2PermissionKindNotifications
|
||||
CoreWebView2PermissionKindOtherSensors
|
||||
CoreWebView2PermissionKindClipboardRead
|
||||
)
|
||||
|
||||
type CoreWebView2PermissionState uint32
|
||||
|
||||
const (
|
||||
CoreWebView2PermissionStateDefault CoreWebView2PermissionState = iota
|
||||
CoreWebView2PermissionStateAllow
|
||||
CoreWebView2PermissionStateDeny
|
||||
)
|
||||
|
||||
// ComProc stores a COM procedure.
|
||||
type ComProc uintptr
|
||||
|
||||
// NewComProc creates a new COM proc from a Go function.
|
||||
func NewComProc(fn interface{}) ComProc {
|
||||
return ComProc(windows.NewCallback(fn))
|
||||
}
|
||||
|
||||
// Call calls a COM procedure.
|
||||
//
|
||||
//go:uintptrescapes
|
||||
func (p ComProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
// The magic uintptrescapes comment is needed to prevent moving uintptr(unsafe.Pointer(p)) so calls to .Call() also
|
||||
// satisfy the unsafe.Pointer rule "(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall."
|
||||
// Otherwise it might be that pointers get moved, especially pointer onto the Go stack which might grow dynamically.
|
||||
// See https://pkg.go.dev/unsafe#Pointer and https://github.com/golang/go/issues/34474
|
||||
switch len(a) {
|
||||
case 0:
|
||||
return syscall.Syscall(uintptr(p), 0, 0, 0, 0)
|
||||
case 1:
|
||||
return syscall.Syscall(uintptr(p), 1, a[0], 0, 0)
|
||||
case 2:
|
||||
return syscall.Syscall(uintptr(p), 2, a[0], a[1], 0)
|
||||
case 3:
|
||||
return syscall.Syscall(uintptr(p), 3, a[0], a[1], a[2])
|
||||
case 4:
|
||||
return syscall.Syscall6(uintptr(p), 4, a[0], a[1], a[2], a[3], 0, 0)
|
||||
case 5:
|
||||
return syscall.Syscall6(uintptr(p), 5, a[0], a[1], a[2], a[3], a[4], 0)
|
||||
case 6:
|
||||
return syscall.Syscall6(uintptr(p), 6, a[0], a[1], a[2], a[3], a[4], a[5])
|
||||
case 7:
|
||||
return syscall.Syscall9(uintptr(p), 7, a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
|
||||
case 8:
|
||||
return syscall.Syscall9(uintptr(p), 8, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
|
||||
case 9:
|
||||
return syscall.Syscall9(uintptr(p), 9, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
|
||||
case 10:
|
||||
return syscall.Syscall12(uintptr(p), 10, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
|
||||
case 11:
|
||||
return syscall.Syscall12(uintptr(p), 11, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
|
||||
case 12:
|
||||
return syscall.Syscall12(uintptr(p), 12, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
|
||||
case 13:
|
||||
return syscall.Syscall15(uintptr(p), 13, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
|
||||
case 14:
|
||||
return syscall.Syscall15(uintptr(p), 14, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
|
||||
case 15:
|
||||
return syscall.Syscall15(uintptr(p), 15, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
|
||||
default:
|
||||
panic("too many arguments")
|
||||
}
|
||||
}
|
||||
|
||||
// IUnknown
|
||||
|
||||
type _IUnknownVtbl struct {
|
||||
QueryInterface ComProc
|
||||
AddRef ComProc
|
||||
Release ComProc
|
||||
}
|
||||
|
||||
func (i *_IUnknownVtbl) CallRelease(this unsafe.Pointer) error {
|
||||
_, _, err := i.Release.Call(
|
||||
uintptr(this),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type _IUnknownImpl interface {
|
||||
QueryInterface(refiid, object uintptr) uintptr
|
||||
AddRef() uintptr
|
||||
Release() uintptr
|
||||
}
|
||||
|
||||
// ICoreWebView2
|
||||
|
||||
type iCoreWebView2Vtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetSettings ComProc
|
||||
GetSource ComProc
|
||||
Navigate ComProc
|
||||
NavigateToString ComProc
|
||||
AddNavigationStarting ComProc
|
||||
RemoveNavigationStarting ComProc
|
||||
AddContentLoading ComProc
|
||||
RemoveContentLoading ComProc
|
||||
AddSourceChanged ComProc
|
||||
RemoveSourceChanged ComProc
|
||||
AddHistoryChanged ComProc
|
||||
RemoveHistoryChanged ComProc
|
||||
AddNavigationCompleted ComProc
|
||||
RemoveNavigationCompleted ComProc
|
||||
AddFrameNavigationStarting ComProc
|
||||
RemoveFrameNavigationStarting ComProc
|
||||
AddFrameNavigationCompleted ComProc
|
||||
RemoveFrameNavigationCompleted ComProc
|
||||
AddScriptDialogOpening ComProc
|
||||
RemoveScriptDialogOpening ComProc
|
||||
AddPermissionRequested ComProc
|
||||
RemovePermissionRequested ComProc
|
||||
AddProcessFailed ComProc
|
||||
RemoveProcessFailed ComProc
|
||||
AddScriptToExecuteOnDocumentCreated ComProc
|
||||
RemoveScriptToExecuteOnDocumentCreated ComProc
|
||||
ExecuteScript ComProc
|
||||
CapturePreview ComProc
|
||||
Reload ComProc
|
||||
PostWebMessageAsJSON ComProc
|
||||
PostWebMessageAsString ComProc
|
||||
AddWebMessageReceived ComProc
|
||||
RemoveWebMessageReceived ComProc
|
||||
CallDevToolsProtocolMethod ComProc
|
||||
GetBrowserProcessID ComProc
|
||||
GetCanGoBack ComProc
|
||||
GetCanGoForward ComProc
|
||||
GoBack ComProc
|
||||
GoForward ComProc
|
||||
GetDevToolsProtocolEventReceiver ComProc
|
||||
Stop ComProc
|
||||
AddNewWindowRequested ComProc
|
||||
RemoveNewWindowRequested ComProc
|
||||
AddDocumentTitleChanged ComProc
|
||||
RemoveDocumentTitleChanged ComProc
|
||||
GetDocumentTitle ComProc
|
||||
AddHostObjectToScript ComProc
|
||||
RemoveHostObjectFromScript ComProc
|
||||
OpenDevToolsWindow ComProc
|
||||
AddContainsFullScreenElementChanged ComProc
|
||||
RemoveContainsFullScreenElementChanged ComProc
|
||||
GetContainsFullScreenElement ComProc
|
||||
AddWebResourceRequested ComProc
|
||||
RemoveWebResourceRequested ComProc
|
||||
AddWebResourceRequestedFilter ComProc
|
||||
RemoveWebResourceRequestedFilter ComProc
|
||||
AddWindowCloseRequested ComProc
|
||||
RemoveWindowCloseRequested ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2 struct {
|
||||
vtbl *iCoreWebView2Vtbl
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2) GetSettings() (*ICoreWebViewSettings, error) {
|
||||
var err error
|
||||
var settings *ICoreWebViewSettings
|
||||
_, _, err = i.vtbl.GetSettings.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(&settings)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return nil, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// ICoreWebView2Environment
|
||||
|
||||
type iCoreWebView2EnvironmentVtbl struct {
|
||||
_IUnknownVtbl
|
||||
CreateCoreWebView2Controller ComProc
|
||||
CreateWebResourceResponse ComProc
|
||||
GetBrowserVersionString ComProc
|
||||
AddNewBrowserVersionAvailable ComProc
|
||||
RemoveNewBrowserVersionAvailable ComProc
|
||||
}
|
||||
|
||||
type ICoreWebView2Environment struct {
|
||||
vtbl *iCoreWebView2EnvironmentVtbl
|
||||
}
|
||||
|
||||
// CreateWebResourceResponse creates a new ICoreWebView2WebResourceResponse, it must be released after finishing using it.
|
||||
func (e *ICoreWebView2Environment) CreateWebResourceResponse(content []byte, statusCode int, reasonPhrase string, headers string) (*ICoreWebView2WebResourceResponse, error) {
|
||||
var err error
|
||||
var stream uintptr
|
||||
|
||||
if len(content) > 0 {
|
||||
// Create stream for response
|
||||
stream, err = w32.SHCreateMemStream(content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Release the IStream after we are finished, CreateWebResourceResponse Call will increase the reference
|
||||
// count on IStream and therefore it won't be freed until the reference count of the response is 0.
|
||||
defer (*IStream)(unsafe.Pointer(stream)).Release()
|
||||
}
|
||||
|
||||
// Convert string 'uri' to *uint16
|
||||
_reason, err := windows.UTF16PtrFromString(reasonPhrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Convert string 'uri' to *uint16
|
||||
_headers, err := windows.UTF16PtrFromString(headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response *ICoreWebView2WebResourceResponse
|
||||
hr, _, err := e.vtbl.CreateWebResourceResponse.Call(
|
||||
uintptr(unsafe.Pointer(e)),
|
||||
stream,
|
||||
uintptr(statusCode),
|
||||
uintptr(unsafe.Pointer(_reason)),
|
||||
uintptr(unsafe.Pointer(_headers)),
|
||||
uintptr(unsafe.Pointer(&response)),
|
||||
)
|
||||
if windows.Handle(hr) != windows.S_OK {
|
||||
return nil, syscall.Errno(hr)
|
||||
}
|
||||
|
||||
if response == nil {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("unknown error")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
|
||||
}
|
||||
|
||||
// ICoreWebView2WebMessageReceivedEventArgs
|
||||
|
||||
type iCoreWebView2WebMessageReceivedEventArgsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetSource ComProc
|
||||
GetWebMessageAsJSON ComProc
|
||||
TryGetWebMessageAsString ComProc
|
||||
}
|
||||
|
||||
type iCoreWebView2WebMessageReceivedEventArgs struct {
|
||||
vtbl *iCoreWebView2WebMessageReceivedEventArgsVtbl
|
||||
}
|
||||
|
||||
// ICoreWebView2PermissionRequestedEventArgs
|
||||
|
||||
type iCoreWebView2PermissionRequestedEventArgsVtbl struct {
|
||||
_IUnknownVtbl
|
||||
GetURI ComProc
|
||||
GetPermissionKind ComProc
|
||||
GetIsUserInitiated ComProc
|
||||
GetState ComProc
|
||||
PutState ComProc
|
||||
GetDeferral ComProc
|
||||
}
|
||||
|
||||
type iCoreWebView2PermissionRequestedEventArgs struct {
|
||||
vtbl *iCoreWebView2PermissionRequestedEventArgsVtbl
|
||||
}
|
||||
|
||||
// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
|
||||
|
||||
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr
|
||||
}
|
||||
|
||||
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler struct {
|
||||
vtbl *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl
|
||||
impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl
|
||||
}
|
||||
|
||||
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, res uintptr, env *ICoreWebView2Environment) uintptr {
|
||||
return this.impl.EnvironmentCompleted(res, env)
|
||||
}
|
||||
|
||||
var iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn = iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler {
|
||||
return &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler{
|
||||
vtbl: &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
||||
|
||||
// ICoreWebView2WebMessageReceivedEventHandler
|
||||
|
||||
type iCoreWebView2WebMessageReceivedEventHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr
|
||||
}
|
||||
|
||||
type iCoreWebView2WebMessageReceivedEventHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type iCoreWebView2WebMessageReceivedEventHandler struct {
|
||||
vtbl *iCoreWebView2WebMessageReceivedEventHandlerVtbl
|
||||
impl iCoreWebView2WebMessageReceivedEventHandlerImpl
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebMessageReceivedEventHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2WebMessageReceivedEventHandlerInvoke(this *iCoreWebView2WebMessageReceivedEventHandler, sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
|
||||
return this.impl.MessageReceived(sender, args)
|
||||
}
|
||||
|
||||
var iCoreWebView2WebMessageReceivedEventHandlerFn = iCoreWebView2WebMessageReceivedEventHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2WebMessageReceivedEventHandler(impl iCoreWebView2WebMessageReceivedEventHandlerImpl) *iCoreWebView2WebMessageReceivedEventHandler {
|
||||
return &iCoreWebView2WebMessageReceivedEventHandler{
|
||||
vtbl: &iCoreWebView2WebMessageReceivedEventHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
||||
|
||||
// ICoreWebView2PermissionRequestedEventHandler
|
||||
|
||||
type iCoreWebView2PermissionRequestedEventHandlerImpl interface {
|
||||
_IUnknownImpl
|
||||
PermissionRequested(sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr
|
||||
}
|
||||
|
||||
type iCoreWebView2PermissionRequestedEventHandlerVtbl struct {
|
||||
_IUnknownVtbl
|
||||
Invoke ComProc
|
||||
}
|
||||
|
||||
type iCoreWebView2PermissionRequestedEventHandler struct {
|
||||
vtbl *iCoreWebView2PermissionRequestedEventHandlerVtbl
|
||||
impl iCoreWebView2PermissionRequestedEventHandlerImpl
|
||||
}
|
||||
|
||||
func _ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2PermissionRequestedEventHandler, refiid, object uintptr) uintptr {
|
||||
return this.impl.QueryInterface(refiid, object)
|
||||
}
|
||||
|
||||
func _ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
|
||||
return this.impl.AddRef()
|
||||
}
|
||||
|
||||
func _ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
|
||||
return this.impl.Release()
|
||||
}
|
||||
|
||||
func _ICoreWebView2PermissionRequestedEventHandlerInvoke(this *iCoreWebView2PermissionRequestedEventHandler, sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
|
||||
return this.impl.PermissionRequested(sender, args)
|
||||
}
|
||||
|
||||
var iCoreWebView2PermissionRequestedEventHandlerFn = iCoreWebView2PermissionRequestedEventHandlerVtbl{
|
||||
_IUnknownVtbl{
|
||||
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface),
|
||||
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef),
|
||||
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease),
|
||||
},
|
||||
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerInvoke),
|
||||
}
|
||||
|
||||
func newICoreWebView2PermissionRequestedEventHandler(impl iCoreWebView2PermissionRequestedEventHandlerImpl) *iCoreWebView2PermissionRequestedEventHandler {
|
||||
return &iCoreWebView2PermissionRequestedEventHandler{
|
||||
vtbl: &iCoreWebView2PermissionRequestedEventHandlerFn,
|
||||
impl: impl,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2) AddWebResourceRequestedFilter(uri string, resourceContext COREWEBVIEW2_WEB_RESOURCE_CONTEXT) error {
|
||||
var err error
|
||||
// Convert string 'uri' to *uint16
|
||||
_uri, err := windows.UTF16PtrFromString(uri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, err = i.vtbl.AddWebResourceRequestedFilter.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(_uri)),
|
||||
uintptr(resourceContext),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (i *ICoreWebView2) AddNavigationCompleted(eventHandler *ICoreWebView2NavigationCompletedEventHandler, token *_EventRegistrationToken) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.AddNavigationCompleted.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(eventHandler)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2) AddProcessFailed(eventHandler *ICoreWebView2ProcessFailedEventHandler, token *_EventRegistrationToken) error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.AddProcessFailed.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
uintptr(unsafe.Pointer(eventHandler)),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ICoreWebView2) OpenDevToolsWindow() error {
|
||||
var err error
|
||||
_, _, err = i.vtbl.OpenDevToolsWindow.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
)
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
//go:build windows && !native_webview2loader
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
|
||||
)
|
||||
|
||||
func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
|
||||
e := &environmentCreatedHandler{environmentCompletedHandle}
|
||||
return webviewloader.CreateCoreWebView2EnvironmentWithOptions(
|
||||
e,
|
||||
webviewloader.WithBrowserExecutableFolder(browserExecutableFolder),
|
||||
webviewloader.WithUserDataFolder(userDataFolder),
|
||||
webviewloader.WithAdditionalBrowserArguments(additionalBrowserArgs),
|
||||
)
|
||||
}
|
||||
|
||||
type environmentCreatedHandler struct {
|
||||
originalHandler *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
|
||||
}
|
||||
|
||||
func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode webviewloader.HRESULT, createdEnvironment *webviewloader.ICoreWebView2Environment) webviewloader.HRESULT {
|
||||
env := (*ICoreWebView2Environment)(unsafe.Pointer(createdEnvironment))
|
||||
res := r.originalHandler.impl.EnvironmentCompleted(uintptr(errorCode), env)
|
||||
return webviewloader.HRESULT(res)
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
//go:build windows && native_webview2loader
|
||||
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
|
||||
browserPathPtr, err := windows.UTF16PtrFromString(browserExecutableFolder)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", browserExecutableFolder, err)
|
||||
}
|
||||
|
||||
userPathPtr, err := windows.UTF16PtrFromString(userDataFolder)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", userDataFolder, err)
|
||||
}
|
||||
|
||||
hr, err := webviewloader.CreateCoreWebView2EnvironmentWithOptions(
|
||||
browserPathPtr,
|
||||
userPathPtr,
|
||||
uintptr(unsafe.Pointer(environmentCompletedHandle)),
|
||||
additionalBrowserArgs,
|
||||
)
|
||||
|
||||
if hr != 0 {
|
||||
if err == nil || err == windows.ERROR_SUCCESS {
|
||||
err = syscall.Errno(hr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package edge
|
||||
|
||||
// This code has been adapted from: https://github.com/go-ole/go-ole
|
||||
|
||||
/*
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2013-2017 Yasuhiro Matsumoto, <mattn.jp@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the “Software”), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
const hextable = "0123456789ABCDEF"
|
||||
const emptyGUID = "{00000000-0000-0000-0000-000000000000}"
|
||||
|
||||
// GUID is Windows API specific GUID type.
|
||||
//
|
||||
// This exists to match Windows GUID type for direct passing for COM.
|
||||
// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.
|
||||
type GUID struct {
|
||||
Data1 uint32
|
||||
Data2 uint16
|
||||
Data3 uint16
|
||||
Data4 [8]byte
|
||||
}
|
||||
|
||||
// NewGUID converts the given string into a globally unique identifier that is
|
||||
// compliant with the Windows API.
|
||||
//
|
||||
// The supplied string may be in any of these formats:
|
||||
//
|
||||
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
|
||||
//
|
||||
// The conversion of the supplied string is not case-sensitive.
|
||||
func NewGUID(guid string) *GUID {
|
||||
d := []byte(guid)
|
||||
var d1, d2, d3, d4a, d4b []byte
|
||||
|
||||
switch len(d) {
|
||||
case 38:
|
||||
if d[0] != '{' || d[37] != '}' {
|
||||
return nil
|
||||
}
|
||||
d = d[1:37]
|
||||
fallthrough
|
||||
case 36:
|
||||
if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' {
|
||||
return nil
|
||||
}
|
||||
d1 = d[0:8]
|
||||
d2 = d[9:13]
|
||||
d3 = d[14:18]
|
||||
d4a = d[19:23]
|
||||
d4b = d[24:36]
|
||||
case 32:
|
||||
d1 = d[0:8]
|
||||
d2 = d[8:12]
|
||||
d3 = d[12:16]
|
||||
d4a = d[16:20]
|
||||
d4b = d[20:32]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
var g GUID
|
||||
var ok1, ok2, ok3, ok4 bool
|
||||
g.Data1, ok1 = decodeHexUint32(d1)
|
||||
g.Data2, ok2 = decodeHexUint16(d2)
|
||||
g.Data3, ok3 = decodeHexUint16(d3)
|
||||
g.Data4, ok4 = decodeHexByte64(d4a, d4b)
|
||||
if ok1 && ok2 && ok3 && ok4 {
|
||||
return &g
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeHexUint32(src []byte) (value uint32, ok bool) {
|
||||
var b1, b2, b3, b4 byte
|
||||
var ok1, ok2, ok3, ok4 bool
|
||||
b1, ok1 = decodeHexByte(src[0], src[1])
|
||||
b2, ok2 = decodeHexByte(src[2], src[3])
|
||||
b3, ok3 = decodeHexByte(src[4], src[5])
|
||||
b4, ok4 = decodeHexByte(src[6], src[7])
|
||||
value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4)
|
||||
ok = ok1 && ok2 && ok3 && ok4
|
||||
return
|
||||
}
|
||||
|
||||
func decodeHexUint16(src []byte) (value uint16, ok bool) {
|
||||
var b1, b2 byte
|
||||
var ok1, ok2 bool
|
||||
b1, ok1 = decodeHexByte(src[0], src[1])
|
||||
b2, ok2 = decodeHexByte(src[2], src[3])
|
||||
value = (uint16(b1) << 8) | uint16(b2)
|
||||
ok = ok1 && ok2
|
||||
return
|
||||
}
|
||||
|
||||
func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) {
|
||||
var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool
|
||||
value[0], ok1 = decodeHexByte(s1[0], s1[1])
|
||||
value[1], ok2 = decodeHexByte(s1[2], s1[3])
|
||||
value[2], ok3 = decodeHexByte(s2[0], s2[1])
|
||||
value[3], ok4 = decodeHexByte(s2[2], s2[3])
|
||||
value[4], ok5 = decodeHexByte(s2[4], s2[5])
|
||||
value[5], ok6 = decodeHexByte(s2[6], s2[7])
|
||||
value[6], ok7 = decodeHexByte(s2[8], s2[9])
|
||||
value[7], ok8 = decodeHexByte(s2[10], s2[11])
|
||||
ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8
|
||||
return
|
||||
}
|
||||
|
||||
func decodeHexByte(c1, c2 byte) (value byte, ok bool) {
|
||||
var n1, n2 byte
|
||||
var ok1, ok2 bool
|
||||
n1, ok1 = decodeHexChar(c1)
|
||||
n2, ok2 = decodeHexChar(c2)
|
||||
value = (n1 << 4) | n2
|
||||
ok = ok1 && ok2
|
||||
return
|
||||
}
|
||||
|
||||
func decodeHexChar(c byte) (byte, bool) {
|
||||
switch {
|
||||
case '0' <= c && c <= '9':
|
||||
return c - '0', true
|
||||
case 'a' <= c && c <= 'f':
|
||||
return c - 'a' + 10, true
|
||||
case 'A' <= c && c <= 'F':
|
||||
return c - 'A' + 10, true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// String converts the GUID to string form. It will adhere to this pattern:
|
||||
//
|
||||
// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
|
||||
//
|
||||
// If the GUID is nil, the string representation of an empty GUID is returned:
|
||||
//
|
||||
// {00000000-0000-0000-0000-000000000000}
|
||||
func (guid *GUID) String() string {
|
||||
if guid == nil {
|
||||
return emptyGUID
|
||||
}
|
||||
|
||||
var c [38]byte
|
||||
c[0] = '{'
|
||||
putUint32Hex(c[1:9], guid.Data1)
|
||||
c[9] = '-'
|
||||
putUint16Hex(c[10:14], guid.Data2)
|
||||
c[14] = '-'
|
||||
putUint16Hex(c[15:19], guid.Data3)
|
||||
c[19] = '-'
|
||||
putByteHex(c[20:24], guid.Data4[0:2])
|
||||
c[24] = '-'
|
||||
putByteHex(c[25:37], guid.Data4[2:8])
|
||||
c[37] = '}'
|
||||
return string(c[:])
|
||||
}
|
||||
|
||||
func putUint32Hex(b []byte, v uint32) {
|
||||
b[0] = hextable[byte(v>>24)>>4]
|
||||
b[1] = hextable[byte(v>>24)&0x0f]
|
||||
b[2] = hextable[byte(v>>16)>>4]
|
||||
b[3] = hextable[byte(v>>16)&0x0f]
|
||||
b[4] = hextable[byte(v>>8)>>4]
|
||||
b[5] = hextable[byte(v>>8)&0x0f]
|
||||
b[6] = hextable[byte(v)>>4]
|
||||
b[7] = hextable[byte(v)&0x0f]
|
||||
}
|
||||
|
||||
func putUint16Hex(b []byte, v uint16) {
|
||||
b[0] = hextable[byte(v>>8)>>4]
|
||||
b[1] = hextable[byte(v>>8)&0x0f]
|
||||
b[2] = hextable[byte(v)>>4]
|
||||
b[3] = hextable[byte(v)&0x0f]
|
||||
}
|
||||
|
||||
func putByteHex(dst, src []byte) {
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i*2] = hextable[src[i]>>4]
|
||||
dst[i*2+1] = hextable[src[i]&0x0f]
|
||||
}
|
||||
}
|
||||
|
||||
// IsEqualGUID compares two GUID.
|
||||
//
|
||||
// Not constant time comparison.
|
||||
func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool {
|
||||
return guid1.Data1 == guid2.Data1 &&
|
||||
guid1.Data2 == guid2.Data2 &&
|
||||
guid1.Data3 == guid2.Data3 &&
|
||||
guid1.Data4[0] == guid2.Data4[0] &&
|
||||
guid1.Data4[1] == guid2.Data4[1] &&
|
||||
guid1.Data4[2] == guid2.Data4[2] &&
|
||||
guid1.Data4[3] == guid2.Data4[3] &&
|
||||
guid1.Data4[4] == guid2.Data4[4] &&
|
||||
guid1.Data4[5] == guid2.Data4[5] &&
|
||||
guid1.Data4[6] == guid2.Data4[6] &&
|
||||
guid1.Data4[7] == guid2.Data4[7]
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
ISC License (ISC)
|
||||
|
||||
Copyright (c) 2020 John Chadwick
|
||||
Copyright (c) 2022 Wails Project Developers
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
@ -1,19 +0,0 @@
|
||||
# Webviewloader
|
||||
|
||||
Webviewloader is a port of [OpenWebView2Loader](https://github.com/jchv/OpenWebView2Loader) to Go.
|
||||
|
||||
It is intended to be feature-complete with the original WebView2Loader distributed with
|
||||
the WebView2 NuGet package, but some features are intentionally not implemented.
|
||||
|
||||
## Status
|
||||
|
||||
- [x] CompareBrowserVersions
|
||||
- [x] CreateCoreWebView2Environment
|
||||
- [x] CreateCoreWebView2EnvironmentWithOptions
|
||||
- [x] GetAvailableCoreWebView2BrowserVersionString
|
||||
|
||||
## Not implemented features
|
||||
|
||||
- Registry Overrides of Parameters
|
||||
- Env Variable Overrides of Parameters
|
||||
- Does not incorporate `GetCurrentPackageInfo` to search for an installed runtime
|
Binary file not shown.
@ -1,176 +0,0 @@
|
||||
//go:build windows && !native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fmt.Println("DEB | Using go webview2loader")
|
||||
preventEnvAndRegistryOverrides()
|
||||
}
|
||||
|
||||
type webView2RunTimeType int32
|
||||
|
||||
const (
|
||||
webView2RunTimeTypeInstalled webView2RunTimeType = 0x00
|
||||
webView2RunTimeTypeRedistributable webView2RunTimeType = 0x01
|
||||
)
|
||||
|
||||
// CreateCoreWebView2Environment creates an evergreen WebView2 Environment using the installed WebView2 Runtime version.
|
||||
//
|
||||
// This is equivalent to running CreateCoreWebView2EnvironmentWithOptions without any options.
|
||||
// For more information, see CreateCoreWebView2EnvironmentWithOptions.
|
||||
func CreateCoreWebView2Environment(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
|
||||
return CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler)
|
||||
}
|
||||
|
||||
// CreateCoreWebView2EnvironmentWithOptions creates an environment with a custom version of WebView2 Runtime,
|
||||
// user data folder, and with or without additional options.
|
||||
//
|
||||
// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?#createcorewebview2environmentwithoptions
|
||||
func CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, opts ...option) error {
|
||||
var params environmentOptions
|
||||
for _, opt := range opts {
|
||||
opt(¶ms)
|
||||
}
|
||||
|
||||
var err error
|
||||
var dllPath string
|
||||
var runtimeType webView2RunTimeType
|
||||
if browserExecutableFolder := params.browserExecutableFolder; browserExecutableFolder != "" {
|
||||
runtimeType = webView2RunTimeTypeRedistributable
|
||||
dllPath, err = findEmbeddedClientDll(browserExecutableFolder)
|
||||
} else {
|
||||
runtimeType = webView2RunTimeTypeInstalled
|
||||
dllPath, _, err = findInstalledClientDll(params.preferCanary)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return createWebViewEnvironmentWithClientDll(dllPath, runtimeType, params.userDataFolder,
|
||||
¶ms, environmentCompletedHandler)
|
||||
}
|
||||
|
||||
func createWebViewEnvironmentWithClientDll(lpLibFileName string, runtimeType webView2RunTimeType, userDataFolder string,
|
||||
envOptions *environmentOptions, envCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
|
||||
|
||||
if !filepath.IsAbs(lpLibFileName) {
|
||||
return fmt.Errorf("lpLibFileName must be absolute")
|
||||
}
|
||||
|
||||
dll, err := windows.LoadDLL(lpLibFileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Loading DLL failed: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
canUnloadProc, err := dll.FindProc("DllCanUnloadNow")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r1, _, _ := canUnloadProc.Call(); r1 != windows.NO_ERROR {
|
||||
return
|
||||
}
|
||||
|
||||
dll.Release()
|
||||
}()
|
||||
|
||||
createProc, err := dll.FindProc("CreateWebViewEnvironmentWithOptionsInternal")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to find CreateWebViewEnvironmentWithOptionsInternal entrypoint: %w", err)
|
||||
}
|
||||
|
||||
userDataPtr, err := windows.UTF16PtrFromString(userDataFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
envOptionsCom := combridge.New2[iCoreWebView2EnvironmentOptions, iCoreWebView2EnvironmentOptions2](
|
||||
envOptions, envOptions)
|
||||
|
||||
defer envOptionsCom.Close()
|
||||
|
||||
envCompletedHandler = &environmentCreatedHandler{envCompletedHandler}
|
||||
envCompletedCom := combridge.New[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](envCompletedHandler)
|
||||
defer envCompletedCom.Close()
|
||||
|
||||
preventEnvAndRegistryOverrides()
|
||||
|
||||
const unknown = 1
|
||||
hr, _, err := createProc.Call(
|
||||
uintptr(unknown),
|
||||
uintptr(runtimeType),
|
||||
uintptr(unsafe.Pointer(userDataPtr)),
|
||||
uintptr(envOptionsCom.Ref()),
|
||||
uintptr(envCompletedCom.Ref()))
|
||||
|
||||
if hr != 0 {
|
||||
if err == nil || err == windows.ERROR_SUCCESS {
|
||||
err = syscall.Errno(hr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type environmentCreatedHandler struct {
|
||||
originalHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
|
||||
}
|
||||
|
||||
func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT {
|
||||
// The OpenWebview2Loader has some retry logic and retries once, didn't encounter any case when this would have been
|
||||
// needed during the development: https://github.com/jchv/OpenWebView2Loader/blob/master/Source/WebView2Loader.cpp#L202
|
||||
|
||||
if createdEnvironment != nil {
|
||||
// May or may not be necessary, but the official WebView2Loader seems to do it.
|
||||
iidICoreWebView2Environment := windows.GUID{
|
||||
Data1: 0xb96d755e,
|
||||
Data2: 0x0319,
|
||||
Data3: 0x4e92,
|
||||
Data4: [8]byte{0xa2, 0x96, 0x23, 0x43, 0x6f, 0x46, 0xa1, 0xfc},
|
||||
}
|
||||
|
||||
if err := createdEnvironment.QueryInterface(&iidICoreWebView2Environment, &createdEnvironment); err != nil {
|
||||
createdEnvironment = nil
|
||||
errNo, ok := err.(syscall.Errno)
|
||||
if !ok {
|
||||
errNo = syscall.Errno(windows.E_FAIL)
|
||||
}
|
||||
errorCode = HRESULT(errNo)
|
||||
}
|
||||
}
|
||||
|
||||
r.originalHandler.EnvironmentCompleted(errorCode, createdEnvironment)
|
||||
|
||||
if createdEnvironment != nil {
|
||||
createdEnvironment.Release()
|
||||
}
|
||||
|
||||
return HRESULT(windows.S_OK)
|
||||
}
|
||||
|
||||
func preventEnvAndRegistryOverrides() {
|
||||
// Setting these env variables to empty string also prevents registry overrides because webview2
|
||||
// checks for existence and not for empty value
|
||||
os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "")
|
||||
os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "")
|
||||
os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0")
|
||||
|
||||
// The following seems not be be required because those are only used by the webview2loader which
|
||||
// in this case is implemented on our own. But nevertheless set them to empty to be consistent.
|
||||
os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", "")
|
||||
os.Setenv("WEBVIEW2_USER_DATA_FOLDER", "")
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
//go:build windows && !native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
|
||||
)
|
||||
|
||||
// HRESULT
|
||||
//
|
||||
// See https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
|
||||
type HRESULT int32
|
||||
|
||||
// ICoreWebView2Environment Represents the WebView2 Environment
|
||||
//
|
||||
// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2environment
|
||||
type ICoreWebView2Environment = combridge.IUnknownImpl
|
||||
|
||||
// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler receives the WebView2Environment created using CreateCoreWebView2Environment.
|
||||
type ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
|
||||
// EnvironmentCompleted is invoked to receive the created WebView2Environment
|
||||
//
|
||||
// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2createcorewebview2environmentcompletedhandler?#invoke
|
||||
EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT
|
||||
}
|
||||
|
||||
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
|
||||
combridge.IUnknown
|
||||
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
|
||||
}
|
||||
|
||||
func init() {
|
||||
combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](
|
||||
"{4e8a3389-c9d8-4bd2-b6b5-124fee6cc14d}",
|
||||
_iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke,
|
||||
)
|
||||
}
|
||||
|
||||
func _iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this uintptr, errorCode HRESULT, env *combridge.IUnknownImpl) uintptr {
|
||||
res := combridge.Resolve[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](this).EnvironmentCompleted(errorCode, env)
|
||||
return uintptr(res)
|
||||
}
|
@ -1,276 +0,0 @@
|
||||
//go:build windows && !native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// WithBrowserExecutableFolder to specify whether WebView2 controls use a fixed or installed version
|
||||
// of the WebView2 Runtime that exists on a user machine.
|
||||
//
|
||||
// To use a fixed version of the WebView2 Runtime,
|
||||
// pass the folder path that contains the fixed version of the WebView2 Runtime.
|
||||
// BrowserExecutableFolder supports both relative (to the application's executable) and absolute files paths.
|
||||
// To create WebView2 controls that use the installed version of the WebView2 Runtime that exists on user
|
||||
// machines, pass a empty string to WithBrowserExecutableFolder. In this scenario, the API tries to find a
|
||||
// compatible version of the WebView2 Runtime that is installed on the user machine (first at the machine level,
|
||||
// and then per user) using the selected channel preference. The path of fixed version of the WebView2 Runtime
|
||||
// should not contain \Edge\Application\. When such a path is used, the API fails with HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).
|
||||
func WithBrowserExecutableFolder(folder string) option {
|
||||
return func(wvep *environmentOptions) {
|
||||
wvep.browserExecutableFolder = folder
|
||||
}
|
||||
}
|
||||
|
||||
// WithUserDataFolder specifies to user data folder location for WebView2
|
||||
//
|
||||
// You may specify the userDataFolder to change the default user data folder location for WebView2.
|
||||
// The path is either an absolute file path or a relative file path that is interpreted as relative
|
||||
// to the compiled code for the current process.
|
||||
// Dhe default user data ({Executable File Name}.WebView2) folder is created in the same directory
|
||||
// next to the compiled code for the app. WebView2 creation fails if the compiled code is running
|
||||
// in a directory in which the process does not have permission to create a new directory.
|
||||
// The app is responsible to clean up the associated user data folder when it is done.
|
||||
func WithUserDataFolder(folder string) option {
|
||||
return func(wvep *environmentOptions) {
|
||||
wvep.userDataFolder = folder
|
||||
}
|
||||
}
|
||||
|
||||
// WithAdditionalBrowserArguments changes the behavior of the WebView.
|
||||
//
|
||||
// The arguments are passed to the
|
||||
// browser process as part of the command. For more information about
|
||||
// using command-line switches with Chromium browser processes, navigate to
|
||||
// [Run Chromium with Flags][ChromiumDevelopersHowTosRunWithFlags].
|
||||
// The value appended to a switch is appended to the browser process, for
|
||||
// example, in `--edge-webview-switches=xxx` the value is `xxx`. If you
|
||||
// specify a switch that is important to WebView functionality, it is
|
||||
// ignored, for example, `--user-data-dir`. Specific features are disabled
|
||||
// internally and blocked from being enabled. If a switch is specified
|
||||
// multiple times, only the last instance is used.
|
||||
//
|
||||
// \> [!NOTE]\n\> A merge of the different values of the same switch is not attempted,
|
||||
// except for disabled and enabled features. The features specified by
|
||||
// `--enable-features` and `--disable-features` are merged with simple
|
||||
// logic.\n\> * The features is the union of the specified features
|
||||
// and built-in features. If a feature is disabled, it is removed from the
|
||||
// enabled features list.
|
||||
//
|
||||
// If you specify command-line switches and use the
|
||||
// `additionalBrowserArguments` parameter, the `--edge-webview-switches`
|
||||
// value takes precedence and is processed last. If a switch fails to
|
||||
// parse, the switch is ignored. The default state for the operation is
|
||||
// to run the browser process with no extra flags.
|
||||
//
|
||||
// [ChromiumDevelopersHowTosRunWithFlags]: https://www.chromium.org/developers/how-tos/run-chromium-with-flags "Run Chromium with flags | The Chromium Projects"
|
||||
func WithAdditionalBrowserArguments(args string) option {
|
||||
return func(wvep *environmentOptions) {
|
||||
wvep.additionalBrowserArguments = args
|
||||
}
|
||||
}
|
||||
|
||||
// WithLanguage sets the default display language for WebView.
|
||||
//
|
||||
// It applies to browser UI such as
|
||||
// context menu and dialogs. It also applies to the `accept-languages` HTTP
|
||||
// header that WebView sends to websites. It is in the format of
|
||||
//
|
||||
// `language[-country]` where `language` is the 2-letter code from
|
||||
// [ISO 639][ISO639LanguageCodesHtml]
|
||||
// and `country` is the
|
||||
// 2-letter code from
|
||||
// [ISO 3166][ISOStandard72482Html].
|
||||
//
|
||||
// [ISO639LanguageCodesHtml]: https://www.iso.org/iso-639-language-codes.html "ISO 639 | ISO"
|
||||
// [ISOStandard72482Html]: https://www.iso.org/standard/72482.html "ISO 3166-1:2020 | ISO"
|
||||
func WithLanguage(lang string) option {
|
||||
return func(wvep *environmentOptions) {
|
||||
wvep.language = lang
|
||||
}
|
||||
}
|
||||
|
||||
// WithTargetCompatibleBrowserVersion secifies the version of the WebView2 Runtime binaries required to be
|
||||
// compatible with your app.
|
||||
//
|
||||
// This defaults to the WebView2 Runtime version
|
||||
// that corresponds with the version of the SDK the app is using. The
|
||||
// format of this value is the same as the format of the
|
||||
// `BrowserVersionString` property and other `BrowserVersion` values. Only
|
||||
// the version part of the `BrowserVersion` value is respected. The channel
|
||||
// suffix, if it exists, is ignored. The version of the WebView2 Runtime
|
||||
// binaries actually used may be different from the specified
|
||||
// `TargetCompatibleBrowserVersion`. The binaries are only guaranteed to be
|
||||
// compatible. Verify the actual version on the `BrowserVersionString`
|
||||
// property on the `ICoreWebView2Environment`.
|
||||
func WithTargetCompatibleBrowserVersion(version string) option {
|
||||
return func(wvep *environmentOptions) {
|
||||
wvep.targetCompatibleBrowserVersion = version
|
||||
}
|
||||
}
|
||||
|
||||
// WithAllowSingleSignOnUsingOSPrimaryAccount is used to enable
|
||||
// single sign on with Azure Active Directory (AAD) and personal Microsoft
|
||||
// Account (MSA) resources inside WebView. All AAD accounts, connected to
|
||||
// Windows and shared for all apps, are supported. For MSA, SSO is only enabled
|
||||
// for the account associated for Windows account login, if any.
|
||||
// Default is disabled. Universal Windows Platform apps must also declare
|
||||
// `enterpriseCloudSSO`
|
||||
// [Restricted capabilities][WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]
|
||||
// for the single sign on (SSO) to work.
|
||||
//
|
||||
// [WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]: /windows/uwp/packaging/app-capability-declarations\#restricted-capabilities "Restricted capabilities - App capability declarations | Microsoft Docs"
|
||||
func WithAllowSingleSignOnUsingOSPrimaryAccount(allow bool) option {
|
||||
return func(wvep *environmentOptions) {
|
||||
wvep.allowSingleSignOnUsingOSPrimaryAccount = allow
|
||||
}
|
||||
}
|
||||
|
||||
// WithExclusiveUserDataFolderAccess specifies that the WebView environment
|
||||
// obtains exclusive access to the user data folder.
|
||||
//
|
||||
// If the user data folder is already being used by another WebView environment with a
|
||||
// different value for `ExclusiveUserDataFolderAccess` property, the creation of a WebView2Controller
|
||||
// using the environment object will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
|
||||
// When set as TRUE, no other WebView can be created from other processes using WebView2Environment
|
||||
// objects with the same UserDataFolder. This prevents other processes from creating WebViews
|
||||
// which share the same browser process instance, since sharing is performed among
|
||||
// WebViews that have the same UserDataFolder. When another process tries to create a
|
||||
// WebView2Controller from an WebView2Environment object created with the same user data folder,
|
||||
// it will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
|
||||
func WithExclusiveUserDataFolderAccess(exclusive bool) option {
|
||||
return func(wvep *environmentOptions) {
|
||||
wvep.exclusiveUserDataFolderAccess = exclusive
|
||||
}
|
||||
}
|
||||
|
||||
type option func(*environmentOptions)
|
||||
|
||||
var _ iCoreWebView2EnvironmentOptions = &environmentOptions{}
|
||||
var _ iCoreWebView2EnvironmentOptions2 = &environmentOptions{}
|
||||
|
||||
type environmentOptions struct {
|
||||
browserExecutableFolder string
|
||||
userDataFolder string
|
||||
preferCanary bool
|
||||
|
||||
additionalBrowserArguments string
|
||||
language string
|
||||
targetCompatibleBrowserVersion string
|
||||
allowSingleSignOnUsingOSPrimaryAccount bool
|
||||
exclusiveUserDataFolderAccess bool
|
||||
}
|
||||
|
||||
func (o *environmentOptions) AdditionalBrowserArguments() string {
|
||||
return o.additionalBrowserArguments
|
||||
}
|
||||
|
||||
func (o *environmentOptions) Language() string {
|
||||
return o.language
|
||||
}
|
||||
|
||||
func (o *environmentOptions) TargetCompatibleBrowserVersion() string {
|
||||
v := o.targetCompatibleBrowserVersion
|
||||
if v == "" {
|
||||
v = kMinimumCompatibleVersion
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (o *environmentOptions) AllowSingleSignOnUsingOSPrimaryAccount() bool {
|
||||
return o.allowSingleSignOnUsingOSPrimaryAccount
|
||||
}
|
||||
|
||||
func (o *environmentOptions) ExclusiveUserDataFolderAccess() bool {
|
||||
return o.exclusiveUserDataFolderAccess
|
||||
}
|
||||
|
||||
type iCoreWebView2EnvironmentOptions interface {
|
||||
combridge.IUnknown
|
||||
|
||||
AdditionalBrowserArguments() string
|
||||
Language() string
|
||||
TargetCompatibleBrowserVersion() string
|
||||
AllowSingleSignOnUsingOSPrimaryAccount() bool
|
||||
}
|
||||
|
||||
type iCoreWebView2EnvironmentOptions2 interface {
|
||||
combridge.IUnknown
|
||||
|
||||
ExclusiveUserDataFolderAccess() bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions](
|
||||
"{2fde08a8-1e9a-4766-8c05-95a9ceb9d1c5}",
|
||||
_iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments,
|
||||
_iCoreWebView2EnvironmentOptionsNOP,
|
||||
_iCoreWebView2EnvironmentOptionsLanguage,
|
||||
_iCoreWebView2EnvironmentOptionsNOP,
|
||||
_iCoreWebView2EnvironmentTargetCompatibleBrowserVersion,
|
||||
_iCoreWebView2EnvironmentOptionsNOP,
|
||||
_iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount,
|
||||
_iCoreWebView2EnvironmentOptionsNOP,
|
||||
)
|
||||
|
||||
combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions2](
|
||||
"{ff85c98a-1ba7-4a6b-90c8-2b752c89e9e2}",
|
||||
_iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess,
|
||||
_iCoreWebView2EnvironmentOptionsNOP,
|
||||
)
|
||||
}
|
||||
func _iCoreWebView2EnvironmentOptionsNOP(this uintptr) uintptr {
|
||||
return uintptr(windows.S_FALSE)
|
||||
}
|
||||
|
||||
func _iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments(this uintptr, value **uint16) uintptr {
|
||||
v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AdditionalBrowserArguments()
|
||||
*value = stringToOleString(v)
|
||||
return uintptr(windows.S_OK)
|
||||
}
|
||||
|
||||
func _iCoreWebView2EnvironmentOptionsLanguage(this uintptr, value **uint16) uintptr {
|
||||
args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).Language()
|
||||
*value = stringToOleString(args)
|
||||
return uintptr(windows.S_OK)
|
||||
}
|
||||
|
||||
func _iCoreWebView2EnvironmentTargetCompatibleBrowserVersion(this uintptr, value **uint16) uintptr {
|
||||
args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).TargetCompatibleBrowserVersion()
|
||||
*value = stringToOleString(args)
|
||||
return uintptr(windows.S_OK)
|
||||
}
|
||||
|
||||
func _iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount(this uintptr, value *int32) uintptr {
|
||||
v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AllowSingleSignOnUsingOSPrimaryAccount()
|
||||
*value = boolToInt(v)
|
||||
return uintptr(windows.S_OK)
|
||||
}
|
||||
|
||||
func _iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess(this uintptr, value *int32) uintptr {
|
||||
v := combridge.Resolve[iCoreWebView2EnvironmentOptions2](this).ExclusiveUserDataFolderAccess()
|
||||
*value = boolToInt(v)
|
||||
return uintptr(windows.S_OK)
|
||||
}
|
||||
|
||||
func stringToOleString(v string) *uint16 {
|
||||
wstr := utf16.Encode([]rune(v + "\x00"))
|
||||
lwstr := len(wstr)
|
||||
ptr := (*uint16)(coTaskMemAlloc(2 * lwstr))
|
||||
|
||||
copy(unsafe.Slice(ptr, lwstr), wstr)
|
||||
|
||||
return ptr
|
||||
}
|
||||
|
||||
func boolToInt(v bool) int32 {
|
||||
if v {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
var (
|
||||
errNoClientDLLFound = errors.New("no webview2 found")
|
||||
)
|
||||
|
||||
func findEmbeddedBrowserVersion(filename string) (string, error) {
|
||||
block, err := getFileVersionInfo(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
info, err := verQueryValueString(block, "\\StringFileInfo\\040904B0\\ProductVersion")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func findEmbeddedClientDll(embeddedEdgeSubFolder string) (outClientPath string, err error) {
|
||||
if !filepath.IsAbs(embeddedEdgeSubFolder) {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
embeddedEdgeSubFolder = filepath.Join(filepath.Dir(exe), embeddedEdgeSubFolder)
|
||||
}
|
||||
|
||||
return findClientDllInFolder(embeddedEdgeSubFolder)
|
||||
}
|
||||
|
||||
func findClientDllInFolder(folder string) (string, error) {
|
||||
arch := ""
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
arch = "arm64"
|
||||
case "amd64":
|
||||
arch = "x64"
|
||||
case "386":
|
||||
arch = "x86"
|
||||
default:
|
||||
return "", fmt.Errorf("Unsupported architecture")
|
||||
}
|
||||
|
||||
dllPath := filepath.Join(folder, "EBWebView", arch, "EmbeddedBrowserWebView.dll")
|
||||
if _, err := os.Stat(dllPath); err != nil {
|
||||
return "", mapFindErr(err)
|
||||
}
|
||||
return dllPath, nil
|
||||
}
|
||||
|
||||
func mapFindErr(err error) error {
|
||||
if errors.Is(err, registry.ErrNotExist) {
|
||||
return errNoClientDLLFound
|
||||
}
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return errNoClientDLLFound
|
||||
}
|
||||
return err
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
//go:build windows && !native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
const (
|
||||
kNumChannels = 4
|
||||
kInstallKeyPath = "Software\\Microsoft\\EdgeUpdate\\ClientState\\"
|
||||
kMinimumCompatibleVersion = "86.0.616.0"
|
||||
)
|
||||
|
||||
var (
|
||||
kChannelName = [kNumChannels]string{
|
||||
"", "beta", "dev", "canary", // "internal"
|
||||
}
|
||||
|
||||
kChannelUuid = [kNumChannels]string{
|
||||
"{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}",
|
||||
"{2CD8A007-E189-409D-A2C8-9AF4EF3C72AA}",
|
||||
"{0D50BFEC-CD6A-4F9A-964C-C7416E3ACB10}",
|
||||
"{65C35B14-6C1D-4122-AC46-7148CC9D6497}",
|
||||
//"{BE59E8FD-089A-411B-A3B0-051D9E417818}",
|
||||
}
|
||||
|
||||
minimumCompatibleVersion, _ = parseVersion(kMinimumCompatibleVersion)
|
||||
)
|
||||
|
||||
func findInstalledClientDll(preferCanary bool) (clientPath string, version *version, err error) {
|
||||
for i := 0; i < kNumChannels; i++ {
|
||||
channel := i
|
||||
if preferCanary {
|
||||
channel = (kNumChannels - 1) - i
|
||||
}
|
||||
|
||||
key := kInstallKeyPath + kChannelUuid[channel]
|
||||
for _, checkSystem := range []bool{true, false} {
|
||||
clientPath, version, err := findInstalledClientDllForChannel(key, checkSystem)
|
||||
if err == errNoClientDLLFound {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
version.channel = kChannelName[channel]
|
||||
return clientPath, version, nil
|
||||
}
|
||||
}
|
||||
return "", nil, errNoClientDLLFound
|
||||
}
|
||||
|
||||
func findInstalledClientDllForChannel(subKey string, system bool) (clientPath string, clientVersion *version, err error) {
|
||||
key := registry.LOCAL_MACHINE
|
||||
if !system {
|
||||
key = registry.CURRENT_USER
|
||||
}
|
||||
|
||||
regKey, err := registry.OpenKey(key, subKey, registry.READ|registry.WOW64_32KEY)
|
||||
if err != nil {
|
||||
return "", nil, mapFindErr(err)
|
||||
}
|
||||
defer regKey.Close()
|
||||
|
||||
embeddedEdgeSubFolder, _, err := regKey.GetStringValue("EBWebView")
|
||||
if err != nil {
|
||||
return "", nil, mapFindErr(err)
|
||||
}
|
||||
|
||||
if embeddedEdgeSubFolder == "" {
|
||||
return "", nil, errNoClientDLLFound
|
||||
}
|
||||
|
||||
versionString := filepath.Base(embeddedEdgeSubFolder)
|
||||
version, err := parseVersion(versionString)
|
||||
if err != nil {
|
||||
return "", nil, errNoClientDLLFound
|
||||
}
|
||||
|
||||
if version.compare(minimumCompatibleVersion) < 0 {
|
||||
return "", nil, errNoClientDLLFound
|
||||
}
|
||||
|
||||
dllPath, err := findEmbeddedClientDll(embeddedEdgeSubFolder)
|
||||
if err != nil {
|
||||
return "", nil, mapFindErr(err)
|
||||
}
|
||||
|
||||
return dllPath, &version, nil
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
//go:build windows && native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/jchv/go-winloader"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func init() {
|
||||
preventEnvAndRegistryOverrides(nil, nil, "")
|
||||
}
|
||||
|
||||
var (
|
||||
memOnce sync.Once
|
||||
memModule winloader.Module
|
||||
memCreate winloader.Proc
|
||||
memCompareBrowserVersions winloader.Proc
|
||||
memGetAvailableCoreWebView2BrowserVersionString winloader.Proc
|
||||
memErr error
|
||||
)
|
||||
|
||||
const (
|
||||
// https://referencesource.microsoft.com/#system.web/Util/hresults.cs,20
|
||||
E_FILENOTFOUND = 0x80070002
|
||||
)
|
||||
|
||||
// CompareBrowserVersions will compare the 2 given versions and return:
|
||||
//
|
||||
// Less than zero: v1 < v2
|
||||
// zero: v1 == v2
|
||||
// Greater than zero: v1 > v2
|
||||
func CompareBrowserVersions(v1 string, v2 string) (int, error) {
|
||||
_v1, err := windows.UTF16PtrFromString(v1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
_v2, err := windows.UTF16PtrFromString(v2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = loadFromMemory()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var result int32
|
||||
_, _, err = memCompareBrowserVersions.Call(
|
||||
uint64(uintptr(unsafe.Pointer(_v1))),
|
||||
uint64(uintptr(unsafe.Pointer(_v2))),
|
||||
uint64(uintptr(unsafe.Pointer(&result))))
|
||||
|
||||
if err != windows.ERROR_SUCCESS {
|
||||
return 0, err
|
||||
}
|
||||
return int(result), nil
|
||||
}
|
||||
|
||||
// GetAvailableCoreWebView2BrowserVersionString returns version of the webview2 runtime.
|
||||
// If path is empty, it will try to find installed webview2 is the system.
|
||||
// If there is no version installed, a blank string is returned.
|
||||
func GetAvailableCoreWebView2BrowserVersionString(path string) (string, error) {
|
||||
if path != "" {
|
||||
// The default implementation fails if CGO and a fixed browser path is used. It's caused by the go-winloader
|
||||
// which loads the native DLL from memory.
|
||||
// Use the new GoWebView2Loader in this case, in the future we will make GoWebView2Loader
|
||||
// feature-complete and remove the use of the native DLL and go-winloader.
|
||||
version, err := goGetAvailableCoreWebView2BrowserVersionString(path)
|
||||
if errors.Is(err, errNoClientDLLFound) {
|
||||
// WebView2 is not found
|
||||
return "", nil
|
||||
} else if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
err := loadFromMemory()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var browserPath *uint16 = nil
|
||||
if path != "" {
|
||||
browserPath, err = windows.UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error calling UTF16PtrFromString for %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
preventEnvAndRegistryOverrides(browserPath, nil, "")
|
||||
var result *uint16
|
||||
res, _, err := memGetAvailableCoreWebView2BrowserVersionString.Call(
|
||||
uint64(uintptr(unsafe.Pointer(browserPath))),
|
||||
uint64(uintptr(unsafe.Pointer(&result))))
|
||||
|
||||
if res != 0 {
|
||||
if res == E_FILENOTFOUND {
|
||||
// WebView2 is not installed
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Unable to call GetAvailableCoreWebView2BrowserVersionString (%x): %w", res, err)
|
||||
}
|
||||
|
||||
version := windows.UTF16PtrToString(result)
|
||||
windows.CoTaskMemFree(unsafe.Pointer(result))
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// CreateCoreWebView2EnvironmentWithOptions tries to load WebviewLoader2 and
|
||||
// call the CreateCoreWebView2EnvironmentWithOptions routine.
|
||||
func CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentCompletedHandle uintptr, additionalBrowserArgs string) (uintptr, error) {
|
||||
err := loadFromMemory()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
preventEnvAndRegistryOverrides(browserExecutableFolder, userDataFolder, additionalBrowserArgs)
|
||||
res, _, _ := memCreate.Call(
|
||||
uint64(uintptr(unsafe.Pointer(browserExecutableFolder))),
|
||||
uint64(uintptr(unsafe.Pointer(userDataFolder))),
|
||||
0,
|
||||
uint64(environmentCompletedHandle),
|
||||
)
|
||||
return uintptr(res), nil
|
||||
}
|
||||
|
||||
func loadFromMemory() error {
|
||||
var err error
|
||||
// DLL is not available natively. Try loading embedded copy.
|
||||
memOnce.Do(func() {
|
||||
memModule, memErr = winloader.LoadFromMemory(WebView2Loader)
|
||||
if memErr != nil {
|
||||
err = fmt.Errorf("Unable to load WebView2Loader.dll from memory: %w", memErr)
|
||||
return
|
||||
}
|
||||
memCreate = memModule.Proc("CreateCoreWebView2EnvironmentWithOptions")
|
||||
memCompareBrowserVersions = memModule.Proc("CompareBrowserVersions")
|
||||
memGetAvailableCoreWebView2BrowserVersionString = memModule.Proc("GetAvailableCoreWebView2BrowserVersionString")
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func preventEnvAndRegistryOverrides(browserFolder, userDataFolder *uint16, additionalBrowserArgs string) {
|
||||
// Setting these env variables to empty string also prevents registry overrides because webview2loader
|
||||
// checks for existence and not for empty value
|
||||
os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "")
|
||||
|
||||
// Set these overrides to the values or empty to prevent registry and external env overrides
|
||||
os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", additionalBrowserArgs)
|
||||
os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0")
|
||||
os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", windows.UTF16PtrToString(browserFolder))
|
||||
os.Setenv("WEBVIEW2_USER_DATA_FOLDER", windows.UTF16PtrToString(userDataFolder))
|
||||
}
|
||||
|
||||
func goGetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
|
||||
clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return findEmbeddedBrowserVersion(clientPath)
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
//go:build windows && native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed x86/WebView2Loader.dll
|
||||
var WebView2Loader []byte
|
@ -1,8 +0,0 @@
|
||||
//go:build windows && native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed x64/WebView2Loader.dll
|
||||
var WebView2Loader []byte
|
@ -1,8 +0,0 @@
|
||||
//go:build windows && native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed arm64/WebView2Loader.dll
|
||||
var WebView2Loader []byte
|
@ -1,143 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
|
||||
procGlobalFree = modkernel32.NewProc("GlobalFree")
|
||||
|
||||
modversion = windows.NewLazySystemDLL("version.dll")
|
||||
procGetFileVersionInfoSize = modversion.NewProc("GetFileVersionInfoSizeW")
|
||||
procGetFileVersionInfo = modversion.NewProc("GetFileVersionInfoW")
|
||||
procVerQueryValue = modversion.NewProc("VerQueryValueW")
|
||||
|
||||
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
||||
procCoTaskMemAlloc = modole32.NewProc("CoTaskMemAlloc")
|
||||
)
|
||||
|
||||
func getFileVersionInfo(path string) ([]byte, error) {
|
||||
lptstrFilename, err := syscall.UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
size, _, err := procGetFileVersionInfoSize.Call(
|
||||
uintptr(unsafe.Pointer(lptstrFilename)),
|
||||
0,
|
||||
)
|
||||
|
||||
err = maskErrorSuccess(err)
|
||||
if size == 0 && err == nil {
|
||||
err = fmt.Errorf("GetFileVersionInfoSize failed")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make([]byte, size)
|
||||
ret, _, err := procGetFileVersionInfo.Call(
|
||||
uintptr(unsafe.Pointer(lptstrFilename)),
|
||||
0,
|
||||
uintptr(size),
|
||||
uintptr(unsafe.Pointer(&data[0])),
|
||||
)
|
||||
|
||||
err = maskErrorSuccess(err)
|
||||
if ret == 0 && err == nil {
|
||||
err = fmt.Errorf("GetFileVersionInfo failed")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func verQueryValueString(block []byte, subBlock string) (string, error) {
|
||||
// Allocate memory from native side to make sure the block doesn't get moved
|
||||
// because we get a pointer into that memory block from the native verQueryValue
|
||||
// call back.
|
||||
pBlock := globalAlloc(0, uint32(len(block)))
|
||||
defer globalFree(unsafe.Pointer(pBlock))
|
||||
|
||||
// Copy the memory region into native side memory
|
||||
copy(unsafe.Slice((*byte)(pBlock), len(block)), block)
|
||||
|
||||
lpSubBlock, err := syscall.UTF16PtrFromString(subBlock)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var lplpBuffer unsafe.Pointer
|
||||
var puLen uint
|
||||
ret, _, err := procVerQueryValue.Call(
|
||||
uintptr(pBlock),
|
||||
uintptr(unsafe.Pointer(lpSubBlock)),
|
||||
uintptr(unsafe.Pointer(&lplpBuffer)),
|
||||
uintptr(unsafe.Pointer(&puLen)),
|
||||
)
|
||||
|
||||
err = maskErrorSuccess(err)
|
||||
if ret == 0 && err == nil {
|
||||
err = fmt.Errorf("VerQueryValue failed")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if puLen <= 1 {
|
||||
return "", nil
|
||||
}
|
||||
puLen -= 1 // Remove Null-Terminator
|
||||
|
||||
wchar := unsafe.Slice((*uint16)(lplpBuffer), puLen)
|
||||
return string(utf16.Decode(wchar)), nil
|
||||
}
|
||||
|
||||
func globalAlloc(uFlags uint, dwBytes uint32) unsafe.Pointer {
|
||||
ret, _, _ := procGlobalAlloc.Call(
|
||||
uintptr(uFlags),
|
||||
uintptr(dwBytes))
|
||||
|
||||
if ret == 0 {
|
||||
panic("globalAlloc failed")
|
||||
}
|
||||
|
||||
return unsafe.Pointer(ret)
|
||||
}
|
||||
|
||||
func globalFree(data unsafe.Pointer) {
|
||||
ret, _, _ := procGlobalFree.Call(uintptr(data))
|
||||
if ret != 0 {
|
||||
panic("globalFree failed")
|
||||
}
|
||||
}
|
||||
|
||||
func maskErrorSuccess(err error) error {
|
||||
if err == windows.ERROR_SUCCESS {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func coTaskMemAlloc(size int) unsafe.Pointer {
|
||||
ret, _, _ := procCoTaskMemAlloc.Call(
|
||||
uintptr(size))
|
||||
|
||||
if ret == 0 {
|
||||
panic("coTaskMemAlloc failed")
|
||||
}
|
||||
return unsafe.Pointer(ret)
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
//go:build windows && !native_webview2loader
|
||||
|
||||
package webviewloader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CompareBrowserVersions will compare the 2 given versions and return:
|
||||
//
|
||||
// -1 = v1 < v2
|
||||
// 0 = v1 == v2
|
||||
// 1 = v1 > v2
|
||||
func CompareBrowserVersions(v1 string, v2 string) (int, error) {
|
||||
v, err := parseVersion(v1)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("v1 invalid: %w", err)
|
||||
}
|
||||
|
||||
w, err := parseVersion(v2)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("v2 invalid: %w", err)
|
||||
}
|
||||
|
||||
return v.compare(w), nil
|
||||
}
|
||||
|
||||
// GetAvailableCoreWebView2BrowserVersionString get the browser version info including channel name
|
||||
// if it is the WebView2 Runtime.
|
||||
// Channel names are Beta, Dev, and Canary.
|
||||
func GetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
|
||||
if browserExecutableFolder != "" {
|
||||
clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
|
||||
if errors.Is(err, errNoClientDLLFound) {
|
||||
// WebView2 is not found
|
||||
return "", nil
|
||||
} else if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return findEmbeddedBrowserVersion(clientPath)
|
||||
}
|
||||
|
||||
_, version, err := findInstalledClientDll(false)
|
||||
if errors.Is(err, errNoClientDLLFound) {
|
||||
return "", nil
|
||||
} else if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return version.String(), nil
|
||||
}
|
||||
|
||||
type version struct {
|
||||
major int
|
||||
minor int
|
||||
patch int
|
||||
build int
|
||||
|
||||
channel string
|
||||
}
|
||||
|
||||
func (v version) String() string {
|
||||
vv := fmt.Sprintf("%d.%d.%d.%d", v.major, v.minor, v.patch, v.build)
|
||||
if v.channel != "" {
|
||||
vv += " " + v.channel
|
||||
}
|
||||
|
||||
return vv
|
||||
}
|
||||
|
||||
func (v version) compare(o version) int {
|
||||
if c := compareInt(v.major, o.major); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := compareInt(v.minor, o.minor); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := compareInt(v.patch, o.patch); c != 0 {
|
||||
return c
|
||||
}
|
||||
return compareInt(v.build, o.build)
|
||||
}
|
||||
|
||||
func parseVersion(v string) (version, error) {
|
||||
var p version
|
||||
|
||||
// Split away channel information...
|
||||
if i := strings.Index(v, " "); i > 0 {
|
||||
p.channel = v[i+1:]
|
||||
v = v[:i]
|
||||
}
|
||||
|
||||
vv := strings.Split(v, ".")
|
||||
if len(vv) > 4 {
|
||||
return p, fmt.Errorf("too many version parts")
|
||||
}
|
||||
|
||||
var err error
|
||||
vv, p.major, err = parseInt(vv)
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("bad major version: %w", err)
|
||||
}
|
||||
|
||||
vv, p.minor, err = parseInt(vv)
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("bad minor version: %w", err)
|
||||
}
|
||||
|
||||
vv, p.patch, err = parseInt(vv)
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("bad patch version: %w", err)
|
||||
}
|
||||
|
||||
_, p.build, err = parseInt(vv)
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("bad build version: %w", err)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func parseInt(v []string) ([]string, int, error) {
|
||||
if len(v) == 0 {
|
||||
return nil, 0, nil
|
||||
}
|
||||
|
||||
p, err := strconv.ParseInt(v[0], 10, 32)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v[1:], int(p), nil
|
||||
}
|
||||
|
||||
func compareInt(v1, v2 int) int {
|
||||
if v1 == v2 {
|
||||
return 0
|
||||
}
|
||||
if v1 < v2 {
|
||||
return -1
|
||||
} else {
|
||||
return +1
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -3,11 +3,10 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/go-webview2/pkg/edge"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
|
||||
"github.com/wailsapp/go-webview2/webviewloader"
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
|
||||
)
|
||||
|
@ -5,7 +5,7 @@ package wv2installer
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
|
||||
"github.com/wailsapp/go-webview2/webviewloader"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
)
|
||||
|
@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Now uses new `go-webview2` module. Added by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/2687).
|
||||
- Changed styling of `doctor` command. Changed by @MarvinJWendt in [PR](https://github.com/wailsapp/wails/pull/2660)
|
||||
- Enable HiDPI option by default in windows nsis installer by @5aaee9 in [PR](https://github.com/wailsapp/wails/pull/2694)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user