-
Notifications
You must be signed in to change notification settings - Fork 965
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom WebView2Loader implementation #783
Custom WebView2Loader implementation #783
Conversation
WebView2Loader.lib is the static library. MinGW can't link that? That's a bummer. Many projects ship with dlls without a fuss, but I understand the desire to ditch them, of course. It's still possible to compile with a static lib using the windows compiler, but not for Go. It looks like supporting Go and other bindings is the main issue here, correct? They will need to depend upon a dynamic library without the option of a static one? Replacing the WebView2Loader with the opensource alternative is something I will look into a little more. I think most people will want the official one just for the sake of it's status and stability, but I could see those who are affected by the MinGW linking deficiency wanting this option to be available. |
The naming style of the lib files is a bit unusual:
Unfortunately, the static one is not usable by MinGW-w64/GCC. Static/Dynamic linking should always be an option in my opinion but users of Go and MinGW-w64 users do no thave that option. Much of the issue has to do with Go/cgo since it uses MinGW-w64/GCC and I believe it breaks the normal worklow of a Go developer if it does not by default link statically. It is not limited to Go though since C/C++ users have the option to use MinGW-w64 instead of Visual C++ unlike before. Other bindings would also be able to benefit from this. I personally build the library mainly using MinGW-w64 now in order to have a consistent workflow across platforms. Instead of fully replacing WebView2Loader with the open-source alternative I would rather reimplement only the minimum amount of features needed to ensure that we can maintain stability and good quality code. It also uses WRL which is is something we eliminated recently to be more compatible with MinGW-w64 and possibly old versions of Windows, so I do not think we should reintroduce that. For example I do not think that we need to be able to select at runtime which release channel to use of the browser engine, or to have the option to use an embedded browser or installed browser. I think that the loader could be considered as a middleman that can be eliminated without any major consequences. The only real downside I can think of is this: But what if we really need to update the loader implementation for whatever reason? In that case we need to either do a bit of reverse engineering again or rely on someone else's reimplementation e.g. OpenWebView2Loader. It is not a given that anyone will provide an open-source alternative for any future version of the loader. If it ever turns out to look that grim some time in the future then we can still fall back to the official loader. One idea is that we can at runtime check if the official loader is present and then use that instead of the reimplementation. Otherwise we just use our reimplementation. With all this said I would argue that:
The most important things here is that we need to do more to make people want to use the webview library, and not give them reasons to go somewhere else or just fork without contributing back to the project. We definitely need a good default behavior, backward-compatibility and seamless fallback. I also do not think that the loader implementation is of great importance. In any case I think that the benefits of having the option available outweights the negative sides. |
Cleans up the code and frees resources properly at runtime.
Commit 0f256cf prefers |
Regarding the embedded WebView2 header, alternatives I can imagine for that right now is to either split the Go bindings from the main Git repository (preferable in my opinion), or if possible move the WebView2 header into a Git submodule if that is something Go/cgo can work with. I am open to different ideas. |
For historical reasons, I don't think we can split the Go bindings. Do you know of a way we can do that without breaking existing dependents? |
I imagine that existing users of this repo should be locked to a specific version/commit so it would only affect new dependents or those who try to upgrade. I have not tested this but I imagine we could redirect those who continue using this repo, e.g. something like this:
I will experiment a bit with this idea. |
I have not gotten my idea above with After quite a journey with trial and error, I believe that I have figured out an acceptable way to split the Go bindings from the main repository. Since Go pins versions (Git tags or commits) of dependencies then I believe that we have the option to remove the bindings from the main repository. Google caches the Go module so that it should keep working for current dependents even if we were to delete the whole repository (not tested). They just cannot upgrade to a new version. We can also either strip down the Go module in the main repository or keep it as-is but issue a compile warning or error via cgo using
This way people should still be able to "upgrade" and get this message after doing so for as long as they are using the old Go module. MS WebView2 can be moved into a separate Git repository that we have to maintain. If we use my custom implementation of the loader then we do not need to host the lib/DLL files. All of this will be tied together using so-called vendoring. Since we specify Go 1.13 as the minimum version in our What vendoring does is copy Go packages from dependencies into a In order to get all the non-Go sources we need into the vendor directory then those files must be in a directory that has Go sources. We can add dummy Go packages in each directory that we need to have in the This way we are able to specify predictable include paths to the C/C++ compiler such as the following:
Dependents must be made aware of vendoring and run One downside with this approach is that there is no way to control which dependencies end up in the |
This PR has now been configured for vendoring. The purpose of this PR is not splitting the Go bindings so I have left that for another time. I have a complete example at the following locations:
You can try it easily like this: git clone https://github.com/SteffenL/webview-go-example
cd webview-go-example
go mod vendor
go build
# Go <1.14: go build -mod=vendor
webview-go-example.exe |
824e8b4
to
a754134
Compare
…2-loader-impl-merge-upstream
The only downside I see to this is the added complexity to the single-header application, but all of the upsides are worth it. The benefits of static-linking are obvious, and the fact that Go benefits so much from it is additionally compelling. I think getting rid of Will the versioning code in #766 conflict with the versioning code found in this PR? 2 separate discussions worth having: I support merging this. Do you have any additional thoughts @justjosias? |
…2-loader-impl-merge-upstream
@dandeto If we split the WebView2Loader reimplementation into a separate file, I wonder if we might have some issues with the header inclusion order since Since #889 introduced |
The latest work disables the built-in WebView2 loader implementation by default because The following compile-time options can be used to change how the library integrates the WebView2 loader:
I would personally like the built-in implementation to be enabled by default, with the official one taking priority. Maybe we can invert the options so that those who do not want this can explicitly disable the features rather than explicitly enable them. This is up for discussion. |
@SteffenL I agree with you - I think it's best to have the built-in implementation enabled by default so that we get all of the benefits by default. I think most users aren't going to need to use the official loader. |
All right. I think we can merge this first and then take care of the "inverted" options so that the built-in implementation is enabled by default. That will be the most beneficial approach for sure. Thank you for the review! |
We could also just keep it simple, remove the compile-time options and always compile the built-in implementation with explicit linking of the official one taking priority. Existing users will not notice any difference and there are plans to introduce error codes at some point so that a missing loader DLL does not cause silent failure. What do you think, @dandeto? |
3a4ab37
to
132a2f4
Compare
af8de6e
to
e9d9c76
Compare
The options were kept in the latest commit but defaults were changed:
|
4ea91f8
to
e656571
Compare
e656571
to
c23f394
Compare
Given that I adressed @dandeto's comment about making the built-in loader the new default (as originally intended) after the PR was approved while also leaving room to disable the options, I am going to merge this so that we can move on. Feel free to bring any new concerns to my attention so that I can address those later. |
As we do not have access to the source code of Microsoft's WebView2Loader library, it causes several annoying issues:
This PR attempts to reimplement parts of the WebView2Loader in order to eliminate the need for the binaries. We still need the header (note 2 and 3). After starting a reverse engineering effort I figured that
WebView2Loader.dll
is not actually doing a whole lot and merely provides some convenience for finding and using the client DLL of the browser (EmbeddedBrowserWebView.dll
).I found OpenWebView2Loader which I then relied on as my RE effort became more or less redundant. One can simply drop in this open-source implementation and it works just fine. We do not need the exact behavior of the official WebView2Loader which is why I did not do this.
This work is not yet complete but it is functional and I think it is a good time to begin discussions.
This branch has instructions (e.g. URLs) changed specifically for this work in order to test the work before a merge:
https://github.com/SteffenL/webview/tree/testing/custom-webview2-loader-impl
Noteworthy Changes
WebView2Loader.dll
) is present at runtime then it will be explicitly linked at runtime and used instead of our custom implementation. This also eliminates the need for an import library (*.lib
file). See note 4.Notes
go generate
before building their programs. As an experiment I wrote a tool for fetching WebView2 and setting up the Go environment. This tool can be invoked viago generate
by adding//go:generate go run github.com/webview/[...]
to the go source file. It works well but it is not a natural workflow for Go.WebView2.idl
file using the MIDL Compiler. That works fine but requires Visual Studio/C++ tools. It would be nice to be able to get WIDL (Wine Interface Definition Language (IDL) compiler) to generate a working header as it is part of MinGW-w64 but the generated code gave me compile errors.*.lib
file). Failing to do so should however produce the same result because the linker (at least in case of MSVC) sees that no exported symbols are used.To Do
CreateCoreWebView2EnvironmentWithOptions
GetAvailableCoreWebView2BrowserVersionString
Won't Do
WEBVIEW2_BROWSER_EXECUTABLE_FOLDER
.WebView2Loader.dll
exports.