Skip to content

Commit

Permalink
Feature: set browser path (#1448)
Browse files Browse the repository at this point in the history
* Added option to specify webview2 path

* Added `manual` webview strategy

* Update documentation

* Fixed build with manual tag

* Check for browser directory existence

* Added version check for manually specified webview, removed fallback for installed webview in manual strategy

* Update WebviewBrowserPath documentation

* Replaced deprecated StringToUTF16Ptr

* Return on error

* Removed manual strategy, return error in wv2installer for fixed runtime

* Removed manual strategy from CLI
  • Loading branch information
Nan0 committed Jun 24, 2022
1 parent c61ce1e commit 2065600
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 10 deletions.
3 changes: 2 additions & 1 deletion v2/internal/frontend/desktop/windows/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,9 @@ func (f *Frontend) Quit() {
func (f *Frontend) setupChromium() {
chromium := edge.NewChromium()
f.chromium = chromium
if opts := f.frontendOptions.Windows; opts != nil && opts.WebviewUserDataPath != "" {
if opts := f.frontendOptions.Windows; opts != nil {
chromium.DataPath = opts.WebviewUserDataPath
chromium.BrowserPath = opts.WebviewBrowserPath
}
chromium.MessageCallback = f.processMessage
chromium.WebResourceRequestedCallback = f.processRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package edge

import (
"errors"
"log"
"os"
"path/filepath"
Expand All @@ -30,8 +31,9 @@ type Chromium struct {
environment *ICoreWebView2Environment

// Settings
Debug bool
DataPath string
Debug bool
DataPath string
BrowserPath string

// permissions
permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState
Expand Down Expand Up @@ -84,7 +86,27 @@ func (e *Chromium) Embed(hwnd uintptr) bool {
dataPath = filepath.Join(os.Getenv("AppData"), currentExeName)
}

res, err := createCoreWebView2EnvironmentWithOptions(nil, windows.StringToUTF16Ptr(dataPath), 0, e.envCompleted)
var browserPathPtr *uint16 = nil
if e.BrowserPath != "" {
if _, err := os.Stat(e.BrowserPath); !errors.Is(err, os.ErrNotExist) {
browserPathPtr, err = windows.UTF16PtrFromString(e.BrowserPath)
if err != nil {
log.Printf("Error calling UTF16PtrFromString for %s: %v", e.BrowserPath, err)
return false
}
} else {
log.Printf("Browser path %s does not exist", e.BrowserPath)
return false
}
}

dataPathPtr, err := windows.UTF16PtrFromString(dataPath)
if err != nil {
log.Printf("Error calling UTF16PtrFromString for %s: %v", dataPath, err)
return false
}

res, err := createCoreWebView2EnvironmentWithOptions(browserPathPtr, dataPathPtr, 0, e.envCompleted)
if err != nil {
log.Printf("Error calling Webview2Loader: %v", err)
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,26 @@ func CompareBrowserVersions(v1 string, v2 string) (int, error) {
return int(result), nil
}

// GetInstalledVersion returns the installed version of the webview2 runtime.
// GetWebviewVersion 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 GetInstalledVersion() (string, error) {
func GetWebviewVersion(path string) (string, error) {
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)
}
}

var result *uint16
res, _, err := memGetAvailableCoreWebView2BrowserVersionString.Call(
uint64(uintptr(unsafe.Pointer(nil))),
uint64(uintptr(unsafe.Pointer(browserPath))),
uint64(uintptr(unsafe.Pointer(&result))))

if res != 0 {
Expand Down
3 changes: 1 addition & 2 deletions v2/internal/system/system_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ func (i *Info) discover() error {
}

func checkWebView2() *packagemanager.Dependancy {

version, _ := webviewloader.GetInstalledVersion()
version, _ := webviewloader.GetWebviewVersion("")
installed := version != ""

return &packagemanager.Dependancy{
Expand Down
15 changes: 14 additions & 1 deletion v2/internal/wv2installer/wv2installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package wv2installer

import (
"fmt"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
Expand All @@ -24,7 +25,14 @@ func Process(appoptions *options.App) (string, error) {
}

installStatus := needsInstalling
installedVersion, err := webviewloader.GetInstalledVersion()

// Override version check for manually specified webview path if present
var webviewPath = ""
if opts := appoptions.Windows; opts != nil && opts.WebviewBrowserPath != "" {
webviewPath = opts.WebviewBrowserPath
}

installedVersion, err := webviewloader.GetWebviewVersion(webviewPath)
if err != nil {
return "", err
}
Expand All @@ -42,5 +50,10 @@ func Process(appoptions *options.App) (string, error) {
}
}

// Force error strategy if webview is manually specified
if webviewPath != "" {
return installedVersion, fmt.Errorf(messages.InvalidFixedWebview2)
}

return installedVersion, doInstallationStrategy(installStatus, messages)
}
5 changes: 5 additions & 0 deletions v2/pkg/options/windows/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Messages struct {
DownloadPage string
PressOKToInstall string
ContactAdmin string
InvalidFixedWebview2 string
}

const (
Expand Down Expand Up @@ -71,6 +72,9 @@ type Options struct {
// If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code.
WebviewUserDataPath string

// Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used.
WebviewBrowserPath string

// Dark/Light or System Default Theme
Theme Theme

Expand Down Expand Up @@ -104,5 +108,6 @@ func DefaultMessages() *Messages {
DownloadPage: "This application requires the WebView2 runtime. Press OK to open the download page. Minimum version required: ",
PressOKToInstall: "Press Ok to install.",
ContactAdmin: "The WebView2 runtime is required to run this application. Please contact your system administrator.",
InvalidFixedWebview2: "The WebView2 runtime is manually specified, but It is not valid. Check minimum required version and webview2 path.",
}
}
17 changes: 17 additions & 0 deletions website/docs/guides/windows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,20 @@ up to the user.
### Error

If no suitable runtime is found, an error is given to the user and no further action taken.

## Fixed version runtime

Another way of dealing with webview2 dependency is shipping it yourself.
You can download [fixed version runtime](https://developer.microsoft.com/ru-ru/microsoft-edge/webview2/#download-section) and bundle or download it with your application.

Also, you should specify path to fixed version of webview2 runtime in the `windows.Options` structure when launching wails.

```go
wails.Run(&options.App{
Windows: &windows.Options{
WebviewBrowserPath: "",
},
})
```

Note: When `WebviewBrowserPath` is specified, `error` strategy will be forced in case of minimal required version mismatch or invalid path to a runtime.
14 changes: 14 additions & 0 deletions website/docs/reference/options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func main() {
DisableWindowIcon: false,
DisableFramelessWindowDecorations: false,
WebviewUserDataPath: "",
WebviewBrowserPath: "",
Theme: windows.SystemDefault,
CustomTheme: &windows.ThemeSettings{
DarkModeTitleBar: windows.RGB(20, 20, 20),
Expand Down Expand Up @@ -430,6 +431,19 @@ Type: string

This defines the path where the WebView2 stores the user data. If empty `%APPDATA%\[BinaryName.exe]` will be used.

### WebviewBrowserPath

Name: WebviewBrowserPath

Type: string

This defines the path to a directory with WebView2 executable files and libraries. If empty, webview2 installed in the system will be used.

Important information about distribution of fixed version runtime:
- [How to get and extract runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode)
- [Known issues for fixed version](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version)
- [The path of fixed version of the WebView2 Runtime should not contain \Edge\Application\.](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions)

### Theme

Name: Theme
Expand Down

0 comments on commit 2065600

Please sign in to comment.