1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Windows: Added WindowsWebView2WebBrowserComponent wrapper to add support for custom WebView2Loader.dll location and user data folder for WebView2

This commit is contained in:
ed 2020-06-16 18:31:23 +01:00
parent f5cb3f4ae1
commit 1f63357263
6 changed files with 139 additions and 23 deletions

View file

@ -59,15 +59,15 @@
/** Config: JUCE_USE_WIN_WEBVIEW2
Enables the use of the Microsoft Edge (Chromium) WebView2 browser on Windows,
currently in developer preview. This requires Microsoft Edge (minimum version
82.0.488.0) to be installed on the user's machine at runtime.
currently in developer preview.
If using the Projucer, the Microsoft.Web.WebView2 package will be added to the
project solution if this flag is enabled. If you are building using CMake you
will need to manually add the package via the Visual Studio package manager.
If the required components are not available at runtime it will fall back to the
IE-based Win32 web view.
In addition to enabling this macro, you will need to use the
WindowsWebView2WebBrowserComponent wrapper - see the documentation of that
class for more details.
*/
#ifndef JUCE_USE_WIN_WEBVIEW2
#define JUCE_USE_WIN_WEBVIEW2 0

View file

@ -26,10 +26,12 @@ namespace juce
A component that displays an embedded web browser.
The browser itself will be platform-dependent. On Mac and iOS it will be
WebKit, on Android it will be Chrome, and on Linux it will be WebKit. On
Windows, if the JUCE_USE_WIN_WEBVIEW2 flag is enabled, it will either be
Microsoft Edge (Chromium) or IE depending on availability of the Edge
runtime.
WebKit, on Android it will be Chrome, and on Linux it will be WebKit.
On Windows it will be IE, but if JUCE_USE_WIN_WEBVIEW2 is enabled then using
the WindowsWebView2WebBrowserComponent wrapper instead of this class directly
will attempt to use the Microsoft Edge (Chromium) WebView2. See the documentation
of that class for more information about its requirements.
@tags{GUI}
*/
@ -133,6 +135,13 @@ public:
class Pimpl;
private:
//==============================================================================
friend class WindowsWebView2WebBrowserComponent;
explicit WebBrowserComponent (bool unloadPageWhenBrowserIsHidden,
const File& dllLocation,
const File& userDataFolder);
//==============================================================================
std::unique_ptr<Pimpl> browser;
bool blankPageShown = false, unloadPageWhenBrowserIsHidden;
@ -146,6 +155,50 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebBrowserComponent)
};
//==============================================================================
/**
If you have enabled the JUCE_USE_WIN_WEBVIEW2 flag then this wrapper will attempt to
use the Microsoft Edge (Chromium) WebView2 control instead of IE on Windows. It will
behave the same as WebBrowserComponent on all other platforms and will fall back to
IE on Windows if the WebView2 requirements are not met.
This requires Microsoft Edge (minimum version 82.0.488.0) to be installed at runtime.
Currently this also requires that WebView2Loader.dll, which can be found in the
Microsoft.Web.WebView package, is installed at runtime. As this is not a standard
system DLL, we can't rely on it being found via the normal system DLL search paths.
Therefore in order to use WebView2 you need to ensure that WebView2Loader.dll is
installed either to a location covered by the Windows DLL system search paths or
to the folder specified in the constructor of this class.
*/
class WindowsWebView2WebBrowserComponent : public WebBrowserComponent
{
public:
/** Creates a WebBrowserComponent that is compatible with the WebView2 control
on Windows.
This allows you to specify a custom location for the WebView2Loader.dll as
well as a non-default location for storing user data for the browser instance.
@param unloadPageWhenBrowserIsHidden if this is true, then when the browser
component is taken offscreen, it'll clear the current page
and replace it with a blank page - this can be handy to stop
the browser using resources in the background when it's not
actually being used.
@param dllLocation the path to WebView2Loader.dll, if this is empty then the default
system DLL search paths will be used
@param userDataFolder a directory in which the WebView2 user data will be stored, if
this is empty then a directory will be created next to the
executable
*/
explicit WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,
const File& dllLocation = {},
const File& userDataFolder = {})
: WebBrowserComponent (unloadPageWhenBrowserIsHidden, dllLocation, userDataFolder)
{
}
};
#endif
} // namespace juce

View file

@ -585,6 +585,13 @@ WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)
addAndMakeVisible (browser.get());
}
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
const File&,
const File&)
: WebBrowserComponent (unloadWhenHidden)
{
}
WebBrowserComponent::~WebBrowserComponent()
{
}

View file

@ -898,9 +898,9 @@ private:
};
//==============================================================================
WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_)
WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)
: browser (new Pimpl (*this)),
unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_)
unloadPageWhenBrowserIsHidden (unloadWhenHidden)
{
ignoreUnused (blankPageShown);
ignoreUnused (unloadPageWhenBrowserIsHidden);
@ -910,6 +910,13 @@ WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidd
browser->init();
}
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
const File&,
const File&)
: WebBrowserComponent (unloadWhenHidden)
{
}
WebBrowserComponent::~WebBrowserComponent()
{
}

View file

@ -543,6 +543,13 @@ WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
addAndMakeVisible (browser.get());
}
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
const File&,
const File&)
: WebBrowserComponent (unloadWhenHidden)
{
}
WebBrowserComponent::~WebBrowserComponent()
{
}

View file

@ -324,14 +324,14 @@ class WebView2 : public InternalWebViewType,
public ComponentMovementWatcher
{
public:
WebView2 (WebBrowserComponent& o)
WebView2 (WebBrowserComponent& o, const File& dllLocation, const File& userDataFolder)
: ComponentMovementWatcher (&o),
owner (o)
{
if (! WinRTWrapper::getInstance()->isInitialised())
throw std::runtime_error ("Failed to initialise the WinRT wrapper");
if (! createWebViewEnvironment())
if (! createWebViewEnvironment (dllLocation, userDataFolder))
throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");
owner.addAndMakeVisible (this);
@ -586,11 +586,32 @@ private:
}
}
bool createWebViewEnvironment()
bool createWebViewEnvironment (const File& dllLocation, const File& userDataFolder)
{
using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,
ICoreWebView2EnvironmentOptions*,
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);
auto dllPath = dllLocation.getFullPathName();
if (dllPath.isEmpty())
dllPath = "WebView2Loader.dll";
auto loaderModule = LoadLibraryA (dllPath.toUTF8());
auto* createWebViewEnvironmentWithOptions = (CreateWebViewEnvironmentWithOptionsFunc) GetProcAddress (loaderModule,
"CreateCoreWebView2EnvironmentWithOptions");
if (createWebViewEnvironmentWithOptions == nullptr)
{
// failed to load WebView2Loader.dll
jassertfalse;
return false;
}
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
auto hr = CreateCoreWebView2EnvironmentWithOptions (nullptr, nullptr, options.Get(),
auto hr = createWebViewEnvironmentWithOptions (nullptr,
userDataFolder != File() ? userDataFolder.getFullPathName().toWideCharPointer() : nullptr,
options.Get(),
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[this] (HRESULT, ICoreWebView2Environment* env) -> HRESULT
{
@ -611,8 +632,15 @@ private:
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler> (
[this] (HRESULT, ICoreWebView2Controller* controller) -> HRESULT
{
webViewController = controller;
controller->get_CoreWebView2 (webView.resetAndGetPointerAddress());
if (controller != nullptr)
{
webViewController = controller;
controller->get_CoreWebView2(webView.resetAndGetPointerAddress());
}
else
{
jassertfalse;
}
isCreating = false;
@ -693,15 +721,20 @@ private:
class WebBrowserComponent::Pimpl
{
public:
Pimpl (WebBrowserComponent& owner)
Pimpl (WebBrowserComponent& owner, const File& dllLocation, const File& userDataFolder, bool useWebView2)
{
#if JUCE_USE_WIN_WEBVIEW2
try
if (useWebView2)
{
internal.reset (new WebView2 (owner));
#if JUCE_USE_WIN_WEBVIEW2
try
{
internal.reset (new WebView2 (owner, dllLocation, userDataFolder));
}
catch (std::runtime_error&) {}
#endif
}
catch (std::runtime_error&) {}
#endif
ignoreUnused (dllLocation, userDataFolder);
if (internal == nullptr)
internal.reset (new Win32WebView (owner));
@ -718,7 +751,16 @@ private:
//==============================================================================
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
: browser (new Pimpl (*this)),
: browser (new Pimpl (*this, {}, {}, false)),
unloadPageWhenBrowserIsHidden (unloadWhenHidden)
{
setOpaque (true);
}
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
const File& dllLocation,
const File& userDataFolder)
: browser (new Pimpl (*this, dllLocation, userDataFolder, true)),
unloadPageWhenBrowserIsHidden (unloadWhenHidden)
{
setOpaque (true);