|
|
|
@@ -310,114 +310,97 @@ private: |
|
|
|
|
|
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EventHandler)
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
#if JUCE_USE_WINRT_WEBVIEW
|
|
|
|
//==============================================================================
|
|
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Win32WebView)
|
|
|
|
};
|
|
|
|
|
|
|
|
extern RTL_OSVERSIONINFOW getWindowsVersionInfo();
|
|
|
|
#if JUCE_USE_WIN_WEBVIEW2
|
|
|
|
|
|
|
|
using namespace Microsoft::WRL;
|
|
|
|
|
|
|
|
using namespace ABI::Windows::Foundation;
|
|
|
|
using namespace ABI::Windows::Storage::Streams;
|
|
|
|
using namespace ABI::Windows::Web;
|
|
|
|
using namespace ABI::Windows::Web::UI;
|
|
|
|
using namespace ABI::Windows::Web::UI::Interop;
|
|
|
|
using namespace ABI::Windows::Web::Http;
|
|
|
|
using namespace ABI::Windows::Web::Http::Headers;
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class WinRTWebView : public InternalWebViewType,
|
|
|
|
public Component,
|
|
|
|
public ComponentMovementWatcher
|
|
|
|
class WebView2 : public InternalWebViewType,
|
|
|
|
public Component,
|
|
|
|
public ComponentMovementWatcher
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
WinRTWebView (WebBrowserComponent& o)
|
|
|
|
: ComponentMovementWatcher (&o),
|
|
|
|
owner (o)
|
|
|
|
WebView2 (WebBrowserComponent& o)
|
|
|
|
: ComponentMovementWatcher (&o),
|
|
|
|
owner (o)
|
|
|
|
{
|
|
|
|
if (! WinRTWrapper::getInstance()->isInitialised())
|
|
|
|
throw std::runtime_error ("Failed to initialise the WinRT wrapper");
|
|
|
|
|
|
|
|
if (! createWebViewProcess())
|
|
|
|
throw std::runtime_error ("Failed to create the WebViewControlProcess");
|
|
|
|
if (! createWebViewEnvironment())
|
|
|
|
throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");
|
|
|
|
|
|
|
|
owner.addAndMakeVisible (this);
|
|
|
|
}
|
|
|
|
|
|
|
|
~WinRTWebView() override
|
|
|
|
~WebView2() override
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
webViewControl->Stop();
|
|
|
|
|
|
|
|
removeEventHandlers();
|
|
|
|
|
|
|
|
webViewProcess->Terminate();
|
|
|
|
closeWebView();
|
|
|
|
}
|
|
|
|
|
|
|
|
void createBrowser() override
|
|
|
|
{
|
|
|
|
if (webViewControl == nullptr)
|
|
|
|
createWebViewControl();
|
|
|
|
if (webView == nullptr)
|
|
|
|
{
|
|
|
|
jassert (webViewEnvironment != nullptr);
|
|
|
|
createWebView();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasBrowserBeenCreated() override
|
|
|
|
{
|
|
|
|
return webViewControl != nullptr || isCreating;
|
|
|
|
return webView != nullptr || isCreating;
|
|
|
|
}
|
|
|
|
|
|
|
|
void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) override
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
{
|
|
|
|
if ((headers != nullptr && ! headers->isEmpty())
|
|
|
|
|| (postData != nullptr && postData->getSize() > 0))
|
|
|
|
{
|
|
|
|
auto requestMessage = createHttpRequestMessage (url, headers, postData);
|
|
|
|
webViewControl->NavigateWithHttpRequestMessage (requestMessage.get());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto uri = createURI (url);
|
|
|
|
webViewControl->Navigate (uri.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
urlRequest = { url,
|
|
|
|
headers != nullptr ? *headers : StringArray(),
|
|
|
|
postData != nullptr && postData->getSize() > 0 ? *postData : MemoryBlock() };
|
|
|
|
|
|
|
|
if (webView != nullptr)
|
|
|
|
webView->Navigate (urlRequest.url.toWideCharPointer());
|
|
|
|
}
|
|
|
|
|
|
|
|
void stop() override
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
webViewControl->Stop();
|
|
|
|
if (webView != nullptr)
|
|
|
|
webView->Stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void goBack() override
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
if (webView != nullptr)
|
|
|
|
{
|
|
|
|
boolean canGoBack = false;
|
|
|
|
webViewControl->get_CanGoBack (&canGoBack);
|
|
|
|
BOOL canGoBack = false;
|
|
|
|
webView->get_CanGoBack (&canGoBack);
|
|
|
|
|
|
|
|
if (canGoBack)
|
|
|
|
webViewControl->GoBack();
|
|
|
|
webView->GoBack();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void goForward() override
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
if (webView != nullptr)
|
|
|
|
{
|
|
|
|
boolean canGoForward = false;
|
|
|
|
webViewControl->get_CanGoForward (&canGoForward);
|
|
|
|
BOOL canGoForward = false;
|
|
|
|
webView->get_CanGoForward (&canGoForward);
|
|
|
|
|
|
|
|
if (canGoForward)
|
|
|
|
webViewControl->GoForward();
|
|
|
|
webView->GoForward();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void refresh() override
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
webViewControl->Refresh();
|
|
|
|
if (webView != nullptr)
|
|
|
|
webView->Reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
void setWebViewSize (int width, int height) override
|
|
|
|
@@ -446,117 +429,40 @@ public: |
|
|
|
|
|
|
|
private:
|
|
|
|
//==============================================================================
|
|
|
|
template<typename OperationResultType, typename ResultsType>
|
|
|
|
static HRESULT waitForCompletion (IAsyncOperation<OperationResultType>* op, ResultsType* results)
|
|
|
|
{
|
|
|
|
using OperationType = IAsyncOperation<OperationResultType>;
|
|
|
|
using DelegateType = IAsyncOperationCompletedHandler<OperationResultType>;
|
|
|
|
|
|
|
|
struct EventDelegate : public RuntimeClass<RuntimeClassFlags<RuntimeClassType::Delegate>,
|
|
|
|
DelegateType,
|
|
|
|
FtmBase>
|
|
|
|
{
|
|
|
|
EventDelegate() = default;
|
|
|
|
|
|
|
|
~EventDelegate()
|
|
|
|
{
|
|
|
|
CloseHandle (eventCompleted);
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT RuntimeClassInitialize()
|
|
|
|
{
|
|
|
|
eventCompleted = CreateEventEx (nullptr, nullptr, 0, EVENT_ALL_ACCESS);
|
|
|
|
return eventCompleted == nullptr ? HRESULT_FROM_WIN32 (GetLastError()) : S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT Invoke (OperationType*, AsyncStatus newStatus)
|
|
|
|
{
|
|
|
|
status = newStatus;
|
|
|
|
SetEvent (eventCompleted);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
AsyncStatus status = AsyncStatus::Started;
|
|
|
|
HANDLE eventCompleted = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<OperationType> operation = op;
|
|
|
|
WinRTWrapper::ComPtr<EventDelegate> eventCallback;
|
|
|
|
|
|
|
|
auto hr = MakeAndInitialize<EventDelegate> (eventCallback.resetAndGetPointerAddress());
|
|
|
|
|
|
|
|
if (SUCCEEDED (hr))
|
|
|
|
{
|
|
|
|
hr = operation->put_Completed (eventCallback.get());
|
|
|
|
|
|
|
|
if (SUCCEEDED (hr))
|
|
|
|
{
|
|
|
|
HANDLE waitForEvents[1] { eventCallback->eventCompleted };
|
|
|
|
auto handleCount = (ULONG) ARRAYSIZE (waitForEvents);
|
|
|
|
DWORD handleIndex = 0;
|
|
|
|
|
|
|
|
hr = CoWaitForMultipleHandles (COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS | COWAIT_INPUTAVAILABLE,
|
|
|
|
INFINITE, handleCount, waitForEvents, &handleIndex);
|
|
|
|
|
|
|
|
if (SUCCEEDED (hr))
|
|
|
|
{
|
|
|
|
if (eventCallback->status == AsyncStatus::Completed)
|
|
|
|
{
|
|
|
|
hr = operation->GetResults (results);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WinRTWrapper::ComPtr<IAsyncInfo> asyncInfo;
|
|
|
|
|
|
|
|
if (SUCCEEDED (operation->QueryInterface (asyncInfo.resetAndGetPointerAddress())))
|
|
|
|
asyncInfo->get_ErrorCode (&hr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
template<class ArgsType>
|
|
|
|
String getURIStringFromArgs (ArgsType& args)
|
|
|
|
template<class ArgType>
|
|
|
|
static String getUriStringFromArgs (ArgType* args)
|
|
|
|
{
|
|
|
|
WinRTWrapper::ComPtr<IUriRuntimeClass> uri;
|
|
|
|
args.get_Uri (uri.resetAndGetPointerAddress());
|
|
|
|
|
|
|
|
if (uri != nullptr)
|
|
|
|
if (args != nullptr)
|
|
|
|
{
|
|
|
|
HSTRING uriString;
|
|
|
|
uri->get_AbsoluteUri (&uriString);
|
|
|
|
LPWSTR uri;
|
|
|
|
args->get_Uri (&uri);
|
|
|
|
|
|
|
|
return WinRTWrapper::getInstance()->hStringToString (uriString);
|
|
|
|
return uri;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void addEventHandlers()
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
if (webView != nullptr)
|
|
|
|
{
|
|
|
|
webViewControl->add_NavigationStarting (Callback<ITypedEventHandler<IWebViewControl*, WebViewControlNavigationStartingEventArgs*>> (
|
|
|
|
[this] (IWebViewControl*, IWebViewControlNavigationStartingEventArgs* args)
|
|
|
|
webView->add_NavigationStarting (Callback<ICoreWebView2NavigationStartingEventHandler> (
|
|
|
|
[this] (ICoreWebView2*, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT
|
|
|
|
{
|
|
|
|
auto uriString = getURIStringFromArgs (*args);
|
|
|
|
auto uriString = getUriStringFromArgs (args);
|
|
|
|
|
|
|
|
if (uriString.isNotEmpty())
|
|
|
|
args->put_Cancel (! owner.pageAboutToLoad (uriString));
|
|
|
|
if (uriString.isNotEmpty() && ! owner.pageAboutToLoad (uriString))
|
|
|
|
args->put_Cancel (true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
).Get(), &navigationStartingToken);
|
|
|
|
}).Get(), &navigationStartingToken);
|
|
|
|
|
|
|
|
webViewControl->add_NewWindowRequested (Callback<ITypedEventHandler<IWebViewControl*, WebViewControlNewWindowRequestedEventArgs*>> (
|
|
|
|
[this] (IWebViewControl*, IWebViewControlNewWindowRequestedEventArgs* args)
|
|
|
|
webView->add_NewWindowRequested (Callback<ICoreWebView2NewWindowRequestedEventHandler> (
|
|
|
|
[this] (ICoreWebView2*, ICoreWebView2NewWindowRequestedEventArgs* args) -> HRESULT
|
|
|
|
{
|
|
|
|
auto uriString = getURIStringFromArgs (*args);
|
|
|
|
auto uriString = getUriStringFromArgs (args);
|
|
|
|
|
|
|
|
if (uriString.isNotEmpty())
|
|
|
|
{
|
|
|
|
@@ -565,237 +471,220 @@ private: |
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
).Get(), &newWindowRequestedToken);
|
|
|
|
}).Get(), &newWindowRequestedToken);
|
|
|
|
|
|
|
|
webViewControl->add_NavigationCompleted (Callback<ITypedEventHandler<IWebViewControl*, WebViewControlNavigationCompletedEventArgs*>> (
|
|
|
|
[this] (IWebViewControl*, IWebViewControlNavigationCompletedEventArgs* args)
|
|
|
|
webView->add_WindowCloseRequested (Callback<ICoreWebView2WindowCloseRequestedEventHandler> (
|
|
|
|
[this] (ICoreWebView2*, IUnknown*) -> HRESULT
|
|
|
|
{
|
|
|
|
auto uriString = getURIStringFromArgs (*args);
|
|
|
|
owner.windowCloseRequest();
|
|
|
|
return S_OK;
|
|
|
|
}).Get(), &windowCloseRequestedToken);
|
|
|
|
|
|
|
|
webView->add_NavigationCompleted (Callback<ICoreWebView2NavigationCompletedEventHandler> (
|
|
|
|
[this] (ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT
|
|
|
|
{
|
|
|
|
LPWSTR uri;
|
|
|
|
sender->get_Source (&uri);
|
|
|
|
|
|
|
|
String uriString (uri);
|
|
|
|
|
|
|
|
if (uriString.isNotEmpty())
|
|
|
|
{
|
|
|
|
boolean success;
|
|
|
|
BOOL success = false;
|
|
|
|
args->get_IsSuccess (&success);
|
|
|
|
|
|
|
|
if (success)
|
|
|
|
COREWEBVIEW2_WEB_ERROR_STATUS errorStatus;
|
|
|
|
args->get_WebErrorStatus (&errorStatus);
|
|
|
|
|
|
|
|
if (success
|
|
|
|
|| errorStatus == COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED) // this error seems to happen erroneously so ignore
|
|
|
|
{
|
|
|
|
owner.pageFinishedLoading (uriString);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WebErrorStatus status;
|
|
|
|
args->get_WebErrorStatus (&status);
|
|
|
|
auto errorString = "Error code: " + String (errorStatus);
|
|
|
|
|
|
|
|
owner.pageLoadHadNetworkError ("Error code: " + String (status));
|
|
|
|
if (owner.pageLoadHadNetworkError (errorString))
|
|
|
|
owner.goToURL ("data:text/plain;charset=UTF-8," + errorString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
).Get(), &navigationCompletedToken);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void removeEventHandlers()
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
{
|
|
|
|
if (navigationStartingToken.value != 0)
|
|
|
|
webViewControl->remove_NavigationStarting (navigationStartingToken);
|
|
|
|
}).Get(), &navigationCompletedToken);
|
|
|
|
|
|
|
|
if (newWindowRequestedToken.value != 0)
|
|
|
|
webViewControl->remove_NewWindowRequested (newWindowRequestedToken);
|
|
|
|
webView->AddWebResourceRequestedFilter (L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT);
|
|
|
|
|
|
|
|
if (navigationCompletedToken.value != 0)
|
|
|
|
webViewControl->remove_NavigationCompleted (navigationCompletedToken);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool createWebViewProcess()
|
|
|
|
{
|
|
|
|
auto webViewControlProcessFactory
|
|
|
|
= WinRTWrapper::getInstance()->getWRLFactory<IWebViewControlProcessFactory> (RuntimeClass_Windows_Web_UI_Interop_WebViewControlProcess);
|
|
|
|
webView->add_WebResourceRequested (Callback<ICoreWebView2WebResourceRequestedEventHandler> (
|
|
|
|
[this] (ICoreWebView2*, ICoreWebView2WebResourceRequestedEventArgs* args) -> HRESULT
|
|
|
|
{
|
|
|
|
if (urlRequest.url.isEmpty())
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
if (webViewControlProcessFactory == nullptr)
|
|
|
|
{
|
|
|
|
jassertfalse;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
WinRTWrapper::ComPtr<ICoreWebView2WebResourceRequest> request;
|
|
|
|
args->get_Request (request.resetAndGetPointerAddress());
|
|
|
|
|
|
|
|
auto webViewProcessOptions
|
|
|
|
= WinRTWrapper::getInstance()->activateInstance<IWebViewControlProcessOptions> (RuntimeClass_Windows_Web_UI_Interop_WebViewControlProcessOptions,
|
|
|
|
__uuidof (IWebViewControlProcessOptions));
|
|
|
|
auto uriString = getUriStringFromArgs (request.get());
|
|
|
|
|
|
|
|
webViewProcessOptions->put_PrivateNetworkClientServerCapability (WebViewControlProcessCapabilityState_Enabled);
|
|
|
|
webViewControlProcessFactory->CreateWithOptions (webViewProcessOptions.get(), webViewProcess.resetAndGetPointerAddress());
|
|
|
|
if (uriString == urlRequest.url
|
|
|
|
|| (uriString.endsWith ("/") && uriString.upToLastOccurrenceOf ("/", false, false) == urlRequest.url))
|
|
|
|
{
|
|
|
|
String method ("GET");
|
|
|
|
|
|
|
|
return webViewProcess != nullptr;
|
|
|
|
}
|
|
|
|
if (urlRequest.postData.getSize() > 0)
|
|
|
|
{
|
|
|
|
method = "POST";
|
|
|
|
|
|
|
|
void createWebViewControl()
|
|
|
|
{
|
|
|
|
if (auto* peer = getPeer())
|
|
|
|
{
|
|
|
|
ScopedValueSetter<bool> svs (isCreating, true);
|
|
|
|
WinRTWrapper::ComPtr<IStream> content (SHCreateMemStream ((BYTE*) urlRequest.postData.getData(),
|
|
|
|
(UINT) urlRequest.postData.getSize()));
|
|
|
|
request->put_Content (content.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IAsyncOperation<WebViewControl*>> createWebViewAsyncOperation;
|
|
|
|
if (! urlRequest.headers.isEmpty())
|
|
|
|
{
|
|
|
|
WinRTWrapper::ComPtr<ICoreWebView2HttpRequestHeaders> headers;
|
|
|
|
request->get_Headers (headers.resetAndGetPointerAddress());
|
|
|
|
|
|
|
|
for (auto& header : urlRequest.headers)
|
|
|
|
{
|
|
|
|
headers->SetHeader (header.upToFirstOccurrenceOf (":", false, false).trim().toWideCharPointer(),
|
|
|
|
header.fromFirstOccurrenceOf (":", false, false).trim().toWideCharPointer());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
webViewProcess->CreateWebViewControlAsync ((INT64) peer->getNativeHandle(), {},
|
|
|
|
createWebViewAsyncOperation.resetAndGetPointerAddress());
|
|
|
|
request->put_Method (method.toWideCharPointer());
|
|
|
|
|
|
|
|
waitForCompletion (createWebViewAsyncOperation.get(), webViewControl.resetAndGetPointerAddress());
|
|
|
|
urlRequest = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
addEventHandlers();
|
|
|
|
componentMovedOrResized (true, true);
|
|
|
|
return S_OK;
|
|
|
|
}).Get(), &webResourceRequestedToken);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
WinRTWrapper::ComPtr<IUriRuntimeClass> createURI (const String& url)
|
|
|
|
void removeEventHandlers()
|
|
|
|
{
|
|
|
|
auto uriRuntimeFactory
|
|
|
|
= WinRTWrapper::getInstance()->getWRLFactory <IUriRuntimeClassFactory> (RuntimeClass_Windows_Foundation_Uri);
|
|
|
|
|
|
|
|
if (uriRuntimeFactory == nullptr)
|
|
|
|
if (webView != nullptr)
|
|
|
|
{
|
|
|
|
jassertfalse;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (navigationStartingToken.value != 0)
|
|
|
|
webView->remove_NavigationStarting (navigationStartingToken);
|
|
|
|
|
|
|
|
WinRTWrapper::ScopedHString hstr (url);
|
|
|
|
WinRTWrapper::ComPtr<IUriRuntimeClass> uriRuntimeClass;
|
|
|
|
uriRuntimeFactory->CreateUri (hstr.get(), uriRuntimeClass.resetAndGetPointerAddress());
|
|
|
|
if (newWindowRequestedToken.value != 0)
|
|
|
|
webView->remove_NewWindowRequested (newWindowRequestedToken);
|
|
|
|
|
|
|
|
return uriRuntimeClass;
|
|
|
|
}
|
|
|
|
if (windowCloseRequestedToken.value != 0)
|
|
|
|
webView->remove_WindowCloseRequested (windowCloseRequestedToken);
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IHttpContent> getPOSTContent (const MemoryBlock& postData)
|
|
|
|
{
|
|
|
|
auto factory = WinRTWrapper::getInstance()->getWRLFactory<IHttpStringContentFactory> (RuntimeClass_Windows_Web_Http_HttpStringContent);
|
|
|
|
if (navigationCompletedToken.value != 0)
|
|
|
|
webView->remove_NavigationCompleted (navigationCompletedToken);
|
|
|
|
|
|
|
|
if (factory == nullptr)
|
|
|
|
{
|
|
|
|
jassertfalse;
|
|
|
|
return {};
|
|
|
|
if (webResourceRequestedToken.value != 0)
|
|
|
|
{
|
|
|
|
webView->RemoveWebResourceRequestedFilter (L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT);
|
|
|
|
webView->remove_WebResourceRequested (webResourceRequestedToken);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WinRTWrapper::ScopedHString hStr (postData.toString());
|
|
|
|
bool createWebViewEnvironment()
|
|
|
|
{
|
|
|
|
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IHttpContent> content;
|
|
|
|
factory->CreateFromString (hStr.get(), content.resetAndGetPointerAddress());
|
|
|
|
auto hr = CreateCoreWebView2EnvironmentWithOptions (nullptr, nullptr, options.Get(),
|
|
|
|
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
|
|
|
[this] (HRESULT, ICoreWebView2Environment* env) -> HRESULT
|
|
|
|
{
|
|
|
|
webViewEnvironment = env;
|
|
|
|
return S_OK;
|
|
|
|
}).Get());
|
|
|
|
|
|
|
|
return content;
|
|
|
|
return SUCCEEDED (hr);
|
|
|
|
}
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IHttpMethod> getMethod (bool isPOST)
|
|
|
|
void createWebView()
|
|
|
|
{
|
|
|
|
auto methodFactory = WinRTWrapper::getInstance()->getWRLFactory<IHttpMethodStatics> (RuntimeClass_Windows_Web_Http_HttpMethod);
|
|
|
|
isCreating = true;
|
|
|
|
|
|
|
|
if (methodFactory == nullptr)
|
|
|
|
if (auto* peer = getPeer())
|
|
|
|
{
|
|
|
|
jassertfalse;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IHttpMethod> method;
|
|
|
|
|
|
|
|
if (isPOST)
|
|
|
|
methodFactory->get_Post (method.resetAndGetPointerAddress());
|
|
|
|
else
|
|
|
|
methodFactory->get_Get (method.resetAndGetPointerAddress());
|
|
|
|
webViewEnvironment->CreateCoreWebView2Controller ((HWND) peer->getNativeHandle(),
|
|
|
|
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler> (
|
|
|
|
[this] (HRESULT, ICoreWebView2Controller* controller) -> HRESULT
|
|
|
|
{
|
|
|
|
webViewController = controller;
|
|
|
|
controller->get_CoreWebView2 (webView.resetAndGetPointerAddress());
|
|
|
|
|
|
|
|
return method;
|
|
|
|
}
|
|
|
|
isCreating = false;
|
|
|
|
|
|
|
|
void addHttpHeaders (WinRTWrapper::ComPtr<IHttpRequestMessage>& requestMessage, const StringArray& headers)
|
|
|
|
{
|
|
|
|
WinRTWrapper::ComPtr<IHttpRequestHeaderCollection> headerCollection;
|
|
|
|
requestMessage->get_Headers (headerCollection.resetAndGetPointerAddress());
|
|
|
|
addEventHandlers();
|
|
|
|
componentMovedOrResized (true, true);
|
|
|
|
|
|
|
|
for (int i = 0; i < headers.size(); ++i)
|
|
|
|
{
|
|
|
|
WinRTWrapper::ScopedHString headerName (headers[i].upToFirstOccurrenceOf (":", false, false).trim());
|
|
|
|
WinRTWrapper::ScopedHString headerValue (headers[i].fromFirstOccurrenceOf (":", false, false).trim());
|
|
|
|
if (webView != nullptr && urlRequest.url.isNotEmpty())
|
|
|
|
webView->Navigate (urlRequest.url.toWideCharPointer());
|
|
|
|
|
|
|
|
headerCollection->Append (headerName.get(), headerValue.get());
|
|
|
|
return S_OK;
|
|
|
|
}).Get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IHttpRequestMessage> createHttpRequestMessage (const String& url,
|
|
|
|
const StringArray* headers,
|
|
|
|
const MemoryBlock* postData)
|
|
|
|
void closeWebView()
|
|
|
|
{
|
|
|
|
auto requestFactory
|
|
|
|
= WinRTWrapper::getInstance()->getWRLFactory<IHttpRequestMessageFactory> (RuntimeClass_Windows_Web_Http_HttpRequestMessage);
|
|
|
|
|
|
|
|
if (requestFactory == nullptr)
|
|
|
|
{
|
|
|
|
jassertfalse;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isPOSTRequest = (postData != nullptr && postData->getSize() > 0);
|
|
|
|
auto method = getMethod (isPOSTRequest);
|
|
|
|
|
|
|
|
auto uri = createURI (url);
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IHttpRequestMessage> requestMessage;
|
|
|
|
requestFactory->Create (method.get(), uri.get(), requestMessage.resetAndGetPointerAddress());
|
|
|
|
|
|
|
|
if (isPOSTRequest)
|
|
|
|
if (webViewController.get() != nullptr)
|
|
|
|
{
|
|
|
|
auto content = getPOSTContent (*postData);
|
|
|
|
requestMessage->put_Content (content.get());
|
|
|
|
webViewController->Close();
|
|
|
|
webViewController = nullptr;
|
|
|
|
webView = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (headers != nullptr && ! headers->isEmpty())
|
|
|
|
addHttpHeaders (requestMessage, *headers);
|
|
|
|
|
|
|
|
return requestMessage;
|
|
|
|
webViewEnvironment = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void setControlBounds (Rectangle<int> newBounds) const
|
|
|
|
{
|
|
|
|
if (webViewControl != nullptr)
|
|
|
|
if (webViewController != nullptr)
|
|
|
|
{
|
|
|
|
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
|
|
|
|
if (auto* peer = owner.getTopLevelComponent()->getPeer())
|
|
|
|
newBounds = (newBounds.toDouble() * peer->getPlatformScaleFactor()).toNearestInt();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IWebViewControlSite> site;
|
|
|
|
|
|
|
|
if (SUCCEEDED (webViewControl->QueryInterface (site.resetAndGetPointerAddress())))
|
|
|
|
site->put_Bounds ({ static_cast<FLOAT> (newBounds.getX()), static_cast<FLOAT> (newBounds.getY()),
|
|
|
|
static_cast<FLOAT> (newBounds.getWidth()), static_cast<FLOAT> (newBounds.getHeight()) });
|
|
|
|
webViewController->put_Bounds({ newBounds.getX(), newBounds.getY(),
|
|
|
|
newBounds.getRight(), newBounds.getBottom() });
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void setControlVisible (bool shouldBeVisible) const
|
|
|
|
{
|
|
|
|
if (webViewControl != 0)
|
|
|
|
{
|
|
|
|
WinRTWrapper::ComPtr<IWebViewControlSite> site;
|
|
|
|
|
|
|
|
if (SUCCEEDED (webViewControl->QueryInterface (site.resetAndGetPointerAddress())))
|
|
|
|
site->put_IsVisible (shouldBeVisible);
|
|
|
|
}
|
|
|
|
if (webViewController != nullptr)
|
|
|
|
webViewController->put_IsVisible (shouldBeVisible);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
WebBrowserComponent& owner;
|
|
|
|
|
|
|
|
WinRTWrapper::ComPtr<IWebViewControlProcess> webViewProcess;
|
|
|
|
WinRTWrapper::ComPtr<IWebViewControl> webViewControl;
|
|
|
|
WinRTWrapper::ComPtr<ICoreWebView2Environment> webViewEnvironment;
|
|
|
|
WinRTWrapper::ComPtr<ICoreWebView2Controller> webViewController;
|
|
|
|
WinRTWrapper::ComPtr<ICoreWebView2> webView;
|
|
|
|
|
|
|
|
EventRegistrationToken navigationStartingToken { 0 },
|
|
|
|
newWindowRequestedToken { 0 },
|
|
|
|
windowCloseRequestedToken { 0 },
|
|
|
|
navigationCompletedToken { 0 },
|
|
|
|
webResourceRequestedToken { 0 };
|
|
|
|
|
|
|
|
EventRegistrationToken navigationStartingToken { 0 },
|
|
|
|
newWindowRequestedToken { 0 },
|
|
|
|
navigationCompletedToken { 0 };
|
|
|
|
struct URLRequest
|
|
|
|
{
|
|
|
|
String url;
|
|
|
|
StringArray headers;
|
|
|
|
MemoryBlock postData;
|
|
|
|
};
|
|
|
|
URLRequest urlRequest;
|
|
|
|
|
|
|
|
bool isCreating = false;
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebView2)
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
@@ -806,18 +695,13 @@ class WebBrowserComponent::Pimpl |
|
|
|
public:
|
|
|
|
Pimpl (WebBrowserComponent& owner)
|
|
|
|
{
|
|
|
|
#if JUCE_USE_WINRT_WEBVIEW
|
|
|
|
auto windowsVersionInfo = getWindowsVersionInfo();
|
|
|
|
|
|
|
|
if (windowsVersionInfo.dwMajorVersion >= 10 && windowsVersionInfo.dwBuildNumber >= 17763)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
internal.reset (new WinRTWebView (owner));
|
|
|
|
}
|
|
|
|
catch (std::runtime_error&) {}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if JUCE_USE_WIN_WEBVIEW2
|
|
|
|
try
|
|
|
|
{
|
|
|
|
internal.reset (new WebView2 (owner));
|
|
|
|
}
|
|
|
|
catch (std::runtime_error&) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (internal == nullptr)
|
|
|
|
internal.reset (new Win32WebView (owner));
|
|
|
|
|