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

Windows: Add WebView2Preferences struct to modify aspects of WebView2 behaviour

This commit is contained in:
ed 2021-08-19 15:47:21 +01:00
parent 315f6d8fcd
commit 4649bc1b13
6 changed files with 154 additions and 56 deletions

View file

@ -192,4 +192,11 @@
#if ! JUCE_WINDOWS #if ! JUCE_WINDOWS
juce::ScopedDPIAwarenessDisabler::ScopedDPIAwarenessDisabler() { ignoreUnused (previousContext); } juce::ScopedDPIAwarenessDisabler::ScopedDPIAwarenessDisabler() { ignoreUnused (previousContext); }
juce::ScopedDPIAwarenessDisabler::~ScopedDPIAwarenessDisabler() {} juce::ScopedDPIAwarenessDisabler::~ScopedDPIAwarenessDisabler() {}
#if JUCE_WEB_BROWSER
juce::WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl) {}
juce::WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,
const WebView2Preferences&)
: juce::WebBrowserComponent (unloadWhenHidden) {}
#endif
#endif #endif

View file

@ -141,14 +141,17 @@ public:
/** @internal */ /** @internal */
class Pimpl; class Pimpl;
private: protected:
//==============================================================================
friend class WindowsWebView2WebBrowserComponent; friend class WindowsWebView2WebBrowserComponent;
explicit WebBrowserComponent (bool unloadPageWhenBrowserIsHidden, struct ConstructWithoutPimpl
const File& dllLocation, {
const File& userDataFolder); explicit ConstructWithoutPimpl (bool unloadOnHide) : unloadWhenHidden (unloadOnHide) {}
const bool unloadWhenHidden;
};
explicit WebBrowserComponent (ConstructWithoutPimpl);
private:
//============================================================================== //==============================================================================
std::unique_ptr<Pimpl> browser; std::unique_ptr<Pimpl> browser;
bool blankPageShown = false, unloadPageWhenHidden; bool blankPageShown = false, unloadPageWhenHidden;
@ -163,6 +166,72 @@ private:
}; };
//============================================================================== //==============================================================================
/** Class used to create a set of preferences to pass to the WindowsWebView2WebBrowserComponent
wrapper constructor to modify aspects of its behaviour and settings.
You can chain together a series of calls to this class's methods to create a set of whatever
preferences you want to specify.
@tags{GUI}
*/
class JUCE_API WebView2Preferences
{
public:
//==============================================================================
/** Sets a custom location for the WebView2Loader.dll that is not a part of the
standard system DLL search paths.
*/
WebView2Preferences withDLLLocation (const File& location) const { return with (&WebView2Preferences::dllLocation, location); }
/** Sets a non-default location for storing user data for the browser instance. */
WebView2Preferences withUserDataFolder (const File& folder) const { return with (&WebView2Preferences::userDataFolder, folder); }
/** If this is set, the status bar usually displayed in the lower-left of the webview
will be disabled.
*/
WebView2Preferences withStatusBarDisabled() const { return with (&WebView2Preferences::disableStatusBar, true); }
/** If this is set, a blank page will be displayed on error instead of the default
built-in error page.
*/
WebView2Preferences withBuiltInErrorPageDisabled() const { return with (&WebView2Preferences::disableBuiltInErrorPage, true); }
/** Sets the background colour that WebView2 renders underneath all web content.
This colour must either be fully opaque or transparent. On Windows 7 this
colour must be opaque.
*/
WebView2Preferences withBackgroundColour (const Colour& colour) const
{
// the background colour must be either fully opaque or transparent!
jassert (colour.isOpaque() || colour.isTransparent());
return with (&WebView2Preferences::backgroundColour, colour);
}
//==============================================================================
File getDLLLocation() const { return dllLocation; }
File getUserDataFolder() const { return userDataFolder; }
bool getIsStatusBarDisabled() const noexcept { return disableStatusBar; }
bool getIsBuiltInErrorPageDisabled() const noexcept { return disableBuiltInErrorPage; }
Colour getBackgroundColour() const { return backgroundColour; }
private:
//==============================================================================
template <typename Member, typename Item>
WebView2Preferences with (Member&& member, Item&& item) const
{
auto options = *this;
options.*member = std::forward<Item> (item);
return options;
}
File dllLocation, userDataFolder;
bool disableStatusBar = false, disableBuiltInErrorPage = false;
Colour backgroundColour = Colours::white;
};
/** /**
If you have enabled the JUCE_USE_WIN_WEBVIEW2 flag then this wrapper will attempt to 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 use the Microsoft Edge (Chromium) WebView2 control instead of IE on Windows. It will
@ -176,34 +245,38 @@ private:
system DLL, we can't rely on it being found via the normal system DLL search paths. 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 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 installed either to a location covered by the Windows DLL system search paths or
to the folder specified in the constructor of this class. to the folder specified in the WebView2Preferences.
@tags{GUI} @tags{GUI}
*/ */
class WindowsWebView2WebBrowserComponent : public WebBrowserComponent class WindowsWebView2WebBrowserComponent : public WebBrowserComponent
{ {
public: public:
//==============================================================================
/** Creates a WebBrowserComponent that is compatible with the WebView2 control /** Creates a WebBrowserComponent that is compatible with the WebView2 control
on Windows. 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 @param unloadPageWhenBrowserIsHidden if this is true, then when the browser
component is taken offscreen, it'll clear the current page component is taken offscreen, it'll clear the current page
and replace it with a blank page - this can be handy to stop and replace it with a blank page - this can be handy to stop
the browser using resources in the background when it's not the browser using resources in the background when it's not
actually being used. actually being used.
@param dllLocation the path to WebView2Loader.dll, if this is empty then the default @param preferences a set of preferences used to control aspects of the webview's
system DLL search paths will be used behaviour.
@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 @see WebView2Preferences
executable
*/ */
WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,
const WebView2Preferences& preferences = {});
// This constructor has been deprecated. Use the new constructor that takes a
// WebView2Preferences instead.
explicit WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true, explicit WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,
const File& dllLocation = {}, const File& dllLocation = {},
const File& userDataFolder = {}) const File& userDataFolder = {})
: WebBrowserComponent (unloadPageWhenBrowserIsHidden, dllLocation, userDataFolder) : WindowsWebView2WebBrowserComponent (unloadPageWhenBrowserIsHidden,
WebView2Preferences().withDLLLocation (dllLocation)
.withUserDataFolder (userDataFolder))
{ {
} }
}; };

View file

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

View file

@ -917,13 +917,6 @@ WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)
browser->init(); browser->init();
} }
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
const File&,
const File&)
: WebBrowserComponent (unloadWhenHidden)
{
}
WebBrowserComponent::~WebBrowserComponent() WebBrowserComponent::~WebBrowserComponent()
{ {
} }

View file

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

View file

@ -342,11 +342,12 @@ class WebView2 : public InternalWebViewType,
public ComponentMovementWatcher public ComponentMovementWatcher
{ {
public: public:
WebView2 (WebBrowserComponent& o, const File& dllLocation, const File& userDataFolder) WebView2 (WebBrowserComponent& o, const WebView2Preferences& prefs)
: ComponentMovementWatcher (&o), : ComponentMovementWatcher (&o),
owner (o) owner (o),
preferences (prefs)
{ {
if (! createWebViewEnvironment (dllLocation, userDataFolder)) if (! createWebViewEnvironment())
throw std::runtime_error ("Failed to create the CoreWebView2Environemnt"); throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");
owner.addAndMakeVisible (this); owner.addAndMakeVisible (this);
@ -604,13 +605,38 @@ private:
} }
} }
bool createWebViewEnvironment (const File& dllLocation, const File& userDataFolder) void setWebViewPreferences()
{
ComSmartPtr<ICoreWebView2Controller2> controller2;
webViewController->QueryInterface (controller2.resetAndGetPointerAddress());
if (controller2 != nullptr)
{
const auto bgColour = preferences.getBackgroundColour();
controller2->put_DefaultBackgroundColor ({ (BYTE) bgColour.getAlpha(),
(BYTE) bgColour.getRed(),
(BYTE) bgColour.getGreen(),
(BYTE) bgColour.getBlue() });
}
ComSmartPtr<ICoreWebView2Settings> settings;
webView->get_Settings (settings.resetAndGetPointerAddress());
if (settings == nullptr)
{
settings->put_IsStatusBarEnabled (! preferences.getIsStatusBarDisabled());
settings->put_IsBuiltInErrorPageEnabled (! preferences.getIsBuiltInErrorPageDisabled());
}
}
bool createWebViewEnvironment()
{ {
using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR, using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,
ICoreWebView2EnvironmentOptions*, ICoreWebView2EnvironmentOptions*,
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*); ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);
auto dllPath = dllLocation.getFullPathName(); auto dllPath = preferences.getDLLLocation().getFullPathName();
if (dllPath.isEmpty()) if (dllPath.isEmpty())
dllPath = "WebView2Loader.dll"; dllPath = "WebView2Loader.dll";
@ -630,9 +656,10 @@ private:
} }
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>(); auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
const auto userDataFolder = preferences.getUserDataFolder().getFullPathName();
auto hr = createWebViewEnvironmentWithOptions (nullptr, auto hr = createWebViewEnvironmentWithOptions (nullptr,
userDataFolder != File() ? userDataFolder.getFullPathName().toWideCharPointer() : nullptr, userDataFolder.isNotEmpty() ? userDataFolder.toWideCharPointer() : nullptr,
options.Get(), options.Get(),
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>( Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Environment* env) -> HRESULT [weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Environment* env) -> HRESULT
@ -667,11 +694,15 @@ private:
weakThis->webViewController = controller; weakThis->webViewController = controller;
controller->get_CoreWebView2 (weakThis->webView.resetAndGetPointerAddress()); controller->get_CoreWebView2 (weakThis->webView.resetAndGetPointerAddress());
weakThis->addEventHandlers(); if (weakThis->webView != nullptr)
weakThis->componentMovedOrResized (true, true); {
weakThis->addEventHandlers();
weakThis->setWebViewPreferences();
weakThis->componentMovedOrResized (true, true);
if (weakThis->webView != nullptr && weakThis->urlRequest.url.isNotEmpty()) if (weakThis->urlRequest.url.isNotEmpty())
weakThis->webView->Navigate (weakThis->urlRequest.url.toWideCharPointer()); weakThis->webView->Navigate (weakThis->urlRequest.url.toWideCharPointer());
}
} }
} }
@ -715,6 +746,7 @@ private:
//============================================================================== //==============================================================================
WebBrowserComponent& owner; WebBrowserComponent& owner;
WebView2Preferences preferences;
HMODULE webView2LoaderHandle = nullptr; HMODULE webView2LoaderHandle = nullptr;
@ -734,6 +766,7 @@ private:
StringArray headers; StringArray headers;
MemoryBlock postData; MemoryBlock postData;
}; };
URLRequest urlRequest; URLRequest urlRequest;
bool isCreating = false; bool isCreating = false;
@ -749,20 +782,22 @@ private:
class WebBrowserComponent::Pimpl class WebBrowserComponent::Pimpl
{ {
public: public:
Pimpl (WebBrowserComponent& owner, const File& dllLocation, const File& userDataFolder, bool useWebView2) Pimpl (WebBrowserComponent& owner,
const WebView2Preferences& preferences,
bool useWebView2)
{ {
if (useWebView2) if (useWebView2)
{ {
#if JUCE_USE_WIN_WEBVIEW2 #if JUCE_USE_WIN_WEBVIEW2
try try
{ {
internal.reset (new WebView2 (owner, dllLocation, userDataFolder)); internal.reset (new WebView2 (owner, preferences));
} }
catch (std::runtime_error&) {} catch (const std::runtime_error&) {}
#endif #endif
} }
ignoreUnused (dllLocation, userDataFolder); ignoreUnused (preferences);
if (internal == nullptr) if (internal == nullptr)
internal.reset (new Win32WebView (owner)); internal.reset (new Win32WebView (owner));
@ -779,17 +814,14 @@ private:
//============================================================================== //==============================================================================
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden) WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
: browser (new Pimpl (*this, {}, {}, false)), : browser (new Pimpl (*this, {}, false)),
unloadPageWhenHidden (unloadWhenHidden) unloadPageWhenHidden (unloadWhenHidden)
{ {
setOpaque (true); setOpaque (true);
} }
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden, WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl args)
const File& dllLocation, : unloadPageWhenHidden (args.unloadWhenHidden)
const File& userDataFolder)
: browser (new Pimpl (*this, dllLocation, userDataFolder, true)),
unloadPageWhenHidden (unloadWhenHidden)
{ {
setOpaque (true); setOpaque (true);
} }
@ -798,6 +830,13 @@ WebBrowserComponent::~WebBrowserComponent()
{ {
} }
WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,
const WebView2Preferences& preferences)
: WebBrowserComponent (ConstructWithoutPimpl { unloadWhenHidden })
{
browser = std::make_unique<Pimpl> (*this, preferences, true);
}
//============================================================================== //==============================================================================
void WebBrowserComponent::goToURL (const String& url, void WebBrowserComponent::goToURL (const String& url,
const StringArray* headers, const StringArray* headers,