From 045e58778ad6ec30c5ec8f565f32bda0ac759e5f Mon Sep 17 00:00:00 2001 From: "Lea\\Anthony" Date: Mon, 27 Dec 2021 18:09:41 +1100 Subject: [PATCH] Actually commit webview2runtime --- .../webview2runtime/webview2runtime.go | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 v2/internal/webview2runtime/webview2runtime.go diff --git a/v2/internal/webview2runtime/webview2runtime.go b/v2/internal/webview2runtime/webview2runtime.go new file mode 100644 index 00000000..27a17fb7 --- /dev/null +++ b/v2/internal/webview2runtime/webview2runtime.go @@ -0,0 +1,168 @@ +//go:build windows +// +build windows + +package webview2runtime + +import ( + _ "embed" + "fmt" + "io" + "net/http" + "os" + "os/exec" + "path/filepath" + "syscall" + "unsafe" +) + +//go:embed MicrosoftEdgeWebview2Setup.exe +var setupexe []byte + +// Info contains all the information about an installation of the webview2 runtime. +type Info struct { + Location string + Name string + Version string + SilentUninstall string +} + +// IsOlderThan returns true if the installed version is older than the given required version. +// Returns error if something goes wrong. +func (i *Info) IsOlderThan(requiredVersion string) (bool, error) { + var mod = syscall.NewLazyDLL("WebView2Loader.dll") + var CompareBrowserVersions = mod.NewProc("CompareBrowserVersions") + v1, err := syscall.UTF16PtrFromString(i.Version) + if err != nil { + return false, err + } + v2, err := syscall.UTF16PtrFromString(requiredVersion) + if err != nil { + return false, err + } + var result int = 9 + _, _, err = CompareBrowserVersions.Call(uintptr(unsafe.Pointer(v1)), uintptr(unsafe.Pointer(v2)), uintptr(unsafe.Pointer(&result))) + if result < -1 || result > 1 { + return false, err + } + return result == -1, nil +} + +func downloadBootstrapper() (string, error) { + bootstrapperURL := `https://go.microsoft.com/fwlink/p/?LinkId=2124703` + installer := filepath.Join(os.TempDir(), `MicrosoftEdgeWebview2Setup.exe`) + + // Download installer + out, err := os.Create(installer) + defer out.Close() + if err != nil { + return "", err + } + resp, err := http.Get(bootstrapperURL) + defer resp.Body.Close() + if err != nil { + err = out.Close() + return "", err + } + _, err = io.Copy(out, resp.Body) + if err != nil { + return "", err + } + + return installer, nil +} + +// InstallUsingEmbeddedBootstrapper will download the bootstrapper from Microsoft and run it to install +// the latest version of the runtime. +// Returns true if the installer ran successfully. +// Returns an error if something goes wrong +func InstallUsingEmbeddedBootstrapper() (bool, error) { + + installer := filepath.Join(os.TempDir(), `MicrosoftEdgeWebview2Setup.exe`) + err := os.WriteFile(installer, setupexe, 0755) + if err != nil { + return false, err + } + result, err := runInstaller(installer) + if err != nil { + return false, err + } + + return result, os.Remove(installer) + +} + +// InstallUsingBootstrapper will extract the embedded bootstrapper from Microsoft and run it to install +// the latest version of the runtime. +// Returns true if the installer ran successfully. +// Returns an error if something goes wrong +func InstallUsingBootstrapper() (bool, error) { + + installer, err := downloadBootstrapper() + if err != nil { + return false, err + } + + result, err := runInstaller(installer) + if err != nil { + return false, err + } + + return result, os.Remove(installer) + +} + +func runInstaller(installer string) (bool, error) { + err := ShellExecuteAndWait(0, "runas", installer, "", os.Getenv("TMP"), syscall.SW_NORMAL) + if err != nil { + fmt.Println(err) + return false, err + } + return true, nil +} + +// Confirm will prompt the user with a message and OK / CANCEL buttons. +// Returns true if OK is selected by the user. +// Returns an error if something went wrong. +func Confirm(caption string, title string) (bool, error) { + var flags uint = 0x00000001 // MB_OKCANCEL + result, err := MessageBox(caption, title, flags) + if err != nil { + return false, err + } + return result == 1, nil +} + +// Error will an error message to the user. +// Returns an error if something went wrong. +func Error(caption string, title string) error { + var flags uint = 0x00000010 // MB_ICONERROR + _, err := MessageBox(caption, title, flags) + return err +} + +// MessageBox prompts the user with the given caption and title. +// Flags may be provided to customise the dialog. +// Returns an error if something went wrong. +func MessageBox(caption string, title string, flags uint) (int, error) { + captionUTF16, err := syscall.UTF16PtrFromString(caption) + if err != nil { + return -1, err + } + titleUTF16, err := syscall.UTF16PtrFromString(title) + if err != nil { + return -1, err + } + ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call( + uintptr(0), + uintptr(unsafe.Pointer(captionUTF16)), + uintptr(unsafe.Pointer(titleUTF16)), + uintptr(flags)) + + return int(ret), nil +} + +// OpenInstallerDownloadWebpage will open the browser on the WebView2 download page +func OpenInstallerDownloadWebpage() error { + cmd := exec.Command("rundll32", "url.dll,FileProtocolHandler", "https://developer.microsoft.com/en-us/microsoft-edge/webview2/") + return cmd.Run() +}