|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2020 - Raw Material Software Limited
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- By using JUCE, you agree to the terms of both the JUCE 6 End-User License
- Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
-
- End User License Agreement: www.juce.com/juce-6-licence
- Privacy Policy: www.juce.com/juce-privacy-policy
-
- Or: You may also use this code under the terms of the GPL v3 (see
- www.gnu.org/licenses).
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- struct InternalWebViewType
- {
- InternalWebViewType() {}
- virtual ~InternalWebViewType() {}
-
- virtual void createBrowser() = 0;
- virtual bool hasBrowserBeenCreated() = 0;
-
- virtual void goToURL (const String&, const StringArray*, const MemoryBlock*) = 0;
-
- virtual void stop() = 0;
- virtual void goBack() = 0;
- virtual void goForward() = 0;
- virtual void refresh() = 0;
-
- virtual void focusGained() {}
- virtual void setWebViewSize (int, int) = 0;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalWebViewType)
- };
-
- #if JUCE_MINGW
- JUCE_DECLARE_UUID_GETTER (IOleClientSite, "00000118-0000-0000-c000-000000000046")
- JUCE_DECLARE_UUID_GETTER (IDispatch, "00020400-0000-0000-c000-000000000046")
-
- #ifndef WebBrowser
- class WebBrowser;
- #endif
- #endif
-
- JUCE_DECLARE_UUID_GETTER (DWebBrowserEvents2, "34A715A0-6587-11D0-924A-0020AFC7AC4D")
- JUCE_DECLARE_UUID_GETTER (IConnectionPointContainer, "B196B284-BAB4-101A-B69C-00AA00341D07")
- JUCE_DECLARE_UUID_GETTER (IWebBrowser2, "D30C1661-CDAF-11D0-8A3E-00C04FC9E26E")
- JUCE_DECLARE_UUID_GETTER (WebBrowser, "8856F961-340A-11D0-A96B-00C04FD705A2")
-
- //==============================================================================
- class Win32WebView : public InternalWebViewType,
- public ActiveXControlComponent
- {
- public:
- Win32WebView (WebBrowserComponent& owner)
- {
- owner.addAndMakeVisible (this);
- }
-
- ~Win32WebView() override
- {
- if (connectionPoint != nullptr)
- connectionPoint->Unadvise (adviseCookie);
-
- if (browser != nullptr)
- browser->Release();
- }
-
- void createBrowser() override
- {
- auto webCLSID = __uuidof (WebBrowser);
- createControl (&webCLSID);
-
- auto iidWebBrowser2 = __uuidof (IWebBrowser2);
- auto iidConnectionPointContainer = __uuidof (IConnectionPointContainer);
-
- browser = (IWebBrowser2*) queryInterface (&iidWebBrowser2);
-
- if (auto connectionPointContainer = (IConnectionPointContainer*) queryInterface (&iidConnectionPointContainer))
- {
- connectionPointContainer->FindConnectionPoint (__uuidof (DWebBrowserEvents2), &connectionPoint);
-
- if (connectionPoint != nullptr)
- {
- auto* owner = dynamic_cast<WebBrowserComponent*> (Component::getParentComponent());
- jassert (owner != nullptr);
-
- auto handler = new EventHandler (*owner);
- connectionPoint->Advise (handler, &adviseCookie);
- handler->Release();
- }
- }
- }
-
- bool hasBrowserBeenCreated() override
- {
- return browser != nullptr;
- }
-
- void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) override
- {
- if (browser != nullptr)
- {
- VARIANT headerFlags, frame, postDataVar, headersVar; // (_variant_t isn't available in all compilers)
- VariantInit (&headerFlags);
- VariantInit (&frame);
- VariantInit (&postDataVar);
- VariantInit (&headersVar);
-
- if (headers != nullptr)
- {
- V_VT (&headersVar) = VT_BSTR;
- V_BSTR (&headersVar) = SysAllocString ((const OLECHAR*) headers->joinIntoString ("\r\n").toWideCharPointer());
- }
-
- if (postData != nullptr && postData->getSize() > 0)
- {
- auto sa = SafeArrayCreateVector (VT_UI1, 0, (ULONG) postData->getSize());
-
- if (sa != nullptr)
- {
- void* data = nullptr;
- SafeArrayAccessData (sa, &data);
- jassert (data != nullptr);
-
- if (data != nullptr)
- {
- postData->copyTo (data, 0, postData->getSize());
- SafeArrayUnaccessData (sa);
-
- VARIANT postDataVar2;
- VariantInit (&postDataVar2);
- V_VT (&postDataVar2) = VT_ARRAY | VT_UI1;
- V_ARRAY (&postDataVar2) = sa;
-
- sa = nullptr;
- postDataVar = postDataVar2;
- }
- else
- {
- SafeArrayDestroy (sa);
- }
- }
- }
-
- auto urlBSTR = SysAllocString ((const OLECHAR*) url.toWideCharPointer());
- browser->Navigate (urlBSTR, &headerFlags, &frame, &postDataVar, &headersVar);
- SysFreeString (urlBSTR);
-
- VariantClear (&headerFlags);
- VariantClear (&frame);
- VariantClear (&postDataVar);
- VariantClear (&headersVar);
- }
- }
-
- void stop() override
- {
- if (browser != nullptr)
- browser->Stop();
- }
-
- void goBack() override
- {
- if (browser != nullptr)
- browser->GoBack();
- }
-
- void goForward() override
- {
- if (browser != nullptr)
- browser->GoForward();
- }
-
- void refresh() override
- {
- if (browser != nullptr)
- browser->Refresh();
- }
-
- void focusGained() override
- {
- auto iidOleObject = __uuidof (IOleObject);
- auto iidOleWindow = __uuidof (IOleWindow);
-
- if (auto oleObject = (IOleObject*) queryInterface (&iidOleObject))
- {
- if (auto oleWindow = (IOleWindow*) queryInterface (&iidOleWindow))
- {
- IOleClientSite* oleClientSite = nullptr;
-
- if (SUCCEEDED (oleObject->GetClientSite (&oleClientSite)))
- {
- HWND hwnd;
- oleWindow->GetWindow (&hwnd);
- oleObject->DoVerb (OLEIVERB_UIACTIVATE, nullptr, oleClientSite, 0, hwnd, nullptr);
- oleClientSite->Release();
- }
-
- oleWindow->Release();
- }
-
- oleObject->Release();
- }
- }
-
- using ActiveXControlComponent::focusGained;
-
- void setWebViewSize (int width, int height) override
- {
- setSize (width, height);
- }
-
- private:
- IWebBrowser2* browser = nullptr;
- IConnectionPoint* connectionPoint = nullptr;
- DWORD adviseCookie = 0;
-
- //==============================================================================
- struct EventHandler : public ComBaseClassHelper<IDispatch>,
- public ComponentMovementWatcher
- {
- EventHandler (WebBrowserComponent& w) : ComponentMovementWatcher (&w), owner (w) {}
-
- JUCE_COMRESULT GetTypeInfoCount (UINT*) override { return E_NOTIMPL; }
- JUCE_COMRESULT GetTypeInfo (UINT, LCID, ITypeInfo**) override { return E_NOTIMPL; }
- JUCE_COMRESULT GetIDsOfNames (REFIID, LPOLESTR*, UINT, LCID, DISPID*) override { return E_NOTIMPL; }
-
- JUCE_COMRESULT Invoke (DISPID dispIdMember, REFIID /*riid*/, LCID /*lcid*/, WORD /*wFlags*/, DISPPARAMS* pDispParams,
- VARIANT* /*pVarResult*/, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/) override
- {
- if (dispIdMember == DISPID_BEFORENAVIGATE2)
- {
- *pDispParams->rgvarg->pboolVal
- = owner.pageAboutToLoad (getStringFromVariant (pDispParams->rgvarg[5].pvarVal)) ? VARIANT_FALSE
- : VARIANT_TRUE;
- return S_OK;
- }
-
- if (dispIdMember == 273 /*DISPID_NEWWINDOW3*/)
- {
- owner.newWindowAttemptingToLoad (pDispParams->rgvarg[0].bstrVal);
- *pDispParams->rgvarg[3].pboolVal = VARIANT_TRUE;
- return S_OK;
- }
-
- if (dispIdMember == DISPID_DOCUMENTCOMPLETE)
- {
- owner.pageFinishedLoading (getStringFromVariant (pDispParams->rgvarg[0].pvarVal));
- return S_OK;
- }
-
- if (dispIdMember == 271 /*DISPID_NAVIGATEERROR*/)
- {
- int statusCode = pDispParams->rgvarg[1].pvarVal->intVal;
- *pDispParams->rgvarg[0].pboolVal = VARIANT_FALSE;
-
- // IWebBrowser2 also reports http status codes here, we need
- // report only network errors
- if (statusCode < 0)
- {
- LPTSTR messageBuffer = nullptr;
- auto size = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, statusCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &messageBuffer, 0, nullptr);
-
- String message (messageBuffer, size);
- LocalFree (messageBuffer);
-
- if (! owner.pageLoadHadNetworkError (message))
- *pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;
- }
-
- return S_OK;
- }
-
- if (dispIdMember == 263 /*DISPID_WINDOWCLOSING*/)
- {
- owner.windowCloseRequest();
-
- // setting this bool tells the browser to ignore the event - we'll handle it.
- if (pDispParams->cArgs > 0 && pDispParams->rgvarg[0].vt == (VT_BYREF | VT_BOOL))
- *pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;
-
- return S_OK;
- }
-
- return E_NOTIMPL;
- }
-
- void componentMovedOrResized (bool, bool) override {}
- void componentPeerChanged() override {}
- void componentVisibilityChanged() override { owner.visibilityChanged(); }
-
- private:
- WebBrowserComponent& owner;
-
- static String getStringFromVariant (VARIANT* v)
- {
- return (v->vt & VT_BYREF) != 0 ? *v->pbstrVal
- : v->bstrVal;
- }
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EventHandler)
- };
-
- //==============================================================================
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Win32WebView)
- };
-
- #if JUCE_USE_WIN_WEBVIEW2
-
- using namespace Microsoft::WRL;
-
- class WebView2 : public InternalWebViewType,
- public Component,
- public ComponentMovementWatcher
- {
- public:
- 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 (dllLocation, userDataFolder))
- throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");
-
- owner.addAndMakeVisible (this);
- }
-
- ~WebView2() override
- {
- removeEventHandlers();
- closeWebView();
-
- if (webView2LoaderHandle != nullptr)
- ::FreeLibrary (webView2LoaderHandle);
- }
-
- void createBrowser() override
- {
- if (webView == nullptr)
- {
- jassert (webViewEnvironment != nullptr);
- createWebView();
- }
- }
-
- bool hasBrowserBeenCreated() override
- {
- return webView != nullptr || isCreating;
- }
-
- void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) override
- {
- 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 (webView != nullptr)
- webView->Stop();
- }
-
- void goBack() override
- {
- if (webView != nullptr)
- {
- BOOL canGoBack = false;
- webView->get_CanGoBack (&canGoBack);
-
- if (canGoBack)
- webView->GoBack();
- }
- }
-
- void goForward() override
- {
- if (webView != nullptr)
- {
- BOOL canGoForward = false;
- webView->get_CanGoForward (&canGoForward);
-
- if (canGoForward)
- webView->GoForward();
- }
- }
-
- void refresh() override
- {
- if (webView != nullptr)
- webView->Reload();
- }
-
- void setWebViewSize (int width, int height) override
- {
- setSize (width, height);
- }
-
- void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override
- {
- if (auto* peer = owner.getTopLevelComponent()->getPeer())
- setControlBounds (peer->getAreaCoveredBy (owner));
- }
-
- void componentPeerChanged() override
- {
- componentMovedOrResized (true, true);
- }
-
- void componentVisibilityChanged() override
- {
- setControlVisible (owner.isShowing());
-
- componentPeerChanged();
- owner.visibilityChanged();
- }
-
- private:
- //==============================================================================
- template<class ArgType>
- static String getUriStringFromArgs (ArgType* args)
- {
- if (args != nullptr)
- {
- LPWSTR uri;
- args->get_Uri (&uri);
-
- return uri;
- }
-
- return {};
- }
-
- //==============================================================================
- void addEventHandlers()
- {
- if (webView != nullptr)
- {
- webView->add_NavigationStarting (Callback<ICoreWebView2NavigationStartingEventHandler> (
- [this] (ICoreWebView2*, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT
- {
- auto uriString = getUriStringFromArgs (args);
-
- if (uriString.isNotEmpty() && ! owner.pageAboutToLoad (uriString))
- args->put_Cancel (true);
-
- return S_OK;
- }).Get(), &navigationStartingToken);
-
- webView->add_NewWindowRequested (Callback<ICoreWebView2NewWindowRequestedEventHandler> (
- [this] (ICoreWebView2*, ICoreWebView2NewWindowRequestedEventArgs* args) -> HRESULT
- {
- auto uriString = getUriStringFromArgs (args);
-
- if (uriString.isNotEmpty())
- {
- owner.newWindowAttemptingToLoad (uriString);
- args->put_Handled (true);
- }
-
- return S_OK;
- }).Get(), &newWindowRequestedToken);
-
- webView->add_WindowCloseRequested (Callback<ICoreWebView2WindowCloseRequestedEventHandler> (
- [this] (ICoreWebView2*, IUnknown*) -> HRESULT
- {
- 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())
- {
- BOOL success = false;
- args->get_IsSuccess (&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
- {
- auto errorString = "Error code: " + String (errorStatus);
-
- if (owner.pageLoadHadNetworkError (errorString))
- owner.goToURL ("data:text/plain;charset=UTF-8," + errorString);
- }
- }
-
- return S_OK;
- }).Get(), &navigationCompletedToken);
-
- webView->AddWebResourceRequestedFilter (L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT);
-
- webView->add_WebResourceRequested (Callback<ICoreWebView2WebResourceRequestedEventHandler> (
- [this] (ICoreWebView2*, ICoreWebView2WebResourceRequestedEventArgs* args) -> HRESULT
- {
- if (urlRequest.url.isEmpty())
- return S_OK;
-
- WinRTWrapper::ComPtr<ICoreWebView2WebResourceRequest> request;
- args->get_Request (request.resetAndGetPointerAddress());
-
- auto uriString = getUriStringFromArgs (request.get());
-
- if (uriString == urlRequest.url
- || (uriString.endsWith ("/") && uriString.upToLastOccurrenceOf ("/", false, false) == urlRequest.url))
- {
- String method ("GET");
-
- if (urlRequest.postData.getSize() > 0)
- {
- method = "POST";
-
- WinRTWrapper::ComPtr<IStream> content (SHCreateMemStream ((BYTE*) urlRequest.postData.getData(),
- (UINT) urlRequest.postData.getSize()));
- request->put_Content (content.get());
- }
-
- 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());
- }
- }
-
- request->put_Method (method.toWideCharPointer());
-
- urlRequest = {};
- }
-
- return S_OK;
- }).Get(), &webResourceRequestedToken);
- }
- }
-
- void removeEventHandlers()
- {
- if (webView != nullptr)
- {
- if (navigationStartingToken.value != 0)
- webView->remove_NavigationStarting (navigationStartingToken);
-
- if (newWindowRequestedToken.value != 0)
- webView->remove_NewWindowRequested (newWindowRequestedToken);
-
- if (windowCloseRequestedToken.value != 0)
- webView->remove_WindowCloseRequested (windowCloseRequestedToken);
-
- if (navigationCompletedToken.value != 0)
- webView->remove_NavigationCompleted (navigationCompletedToken);
-
- if (webResourceRequestedToken.value != 0)
- {
- webView->RemoveWebResourceRequestedFilter (L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT);
- webView->remove_WebResourceRequested (webResourceRequestedToken);
- }
- }
- }
-
- 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";
-
- webView2LoaderHandle = LoadLibraryA (dllPath.toUTF8());
-
- if (webView2LoaderHandle == nullptr)
- return false;
-
- auto* createWebViewEnvironmentWithOptions = (CreateWebViewEnvironmentWithOptionsFunc) GetProcAddress (webView2LoaderHandle,
- "CreateCoreWebView2EnvironmentWithOptions");
- if (createWebViewEnvironmentWithOptions == nullptr)
- {
- // failed to load WebView2Loader.dll
- jassertfalse;
- return false;
- }
-
- auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
-
- WeakReference<WebView2> weakThis (this);
- auto hr = createWebViewEnvironmentWithOptions (nullptr,
- userDataFolder != File() ? userDataFolder.getFullPathName().toWideCharPointer() : nullptr,
- options.Get(),
- Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
- [this, weakThis] (HRESULT, ICoreWebView2Environment* env) -> HRESULT
- {
- if (weakThis != nullptr)
- webViewEnvironment = env;
-
- return S_OK;
- }).Get());
-
- return SUCCEEDED (hr);
- }
-
- void createWebView()
- {
- if (auto* peer = getPeer())
- {
- isCreating = true;
-
- WeakReference<WebView2> weakThis (this);
-
- webViewEnvironment->CreateCoreWebView2Controller ((HWND) peer->getNativeHandle(),
- Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler> (
- [this, weakThis] (HRESULT, ICoreWebView2Controller* controller) -> HRESULT
- {
- if (weakThis != nullptr)
- {
- isCreating = false;
-
- if (controller != nullptr)
- {
- webViewController = controller;
- controller->get_CoreWebView2 (webView.resetAndGetPointerAddress());
-
- addEventHandlers();
- componentMovedOrResized (true, true);
-
- if (webView != nullptr && urlRequest.url.isNotEmpty())
- webView->Navigate (urlRequest.url.toWideCharPointer());
- }
- }
-
- return S_OK;
- }).Get());
- }
- }
-
- void closeWebView()
- {
- if (webViewController.get() != nullptr)
- {
- webViewController->Close();
- webViewController = nullptr;
- webView = nullptr;
- }
-
- webViewEnvironment = nullptr;
- }
-
- //==============================================================================
- void setControlBounds (Rectangle<int> newBounds) const
- {
- if (webViewController != nullptr)
- {
- #if JUCE_WIN_PER_MONITOR_DPI_AWARE
- if (auto* peer = owner.getTopLevelComponent()->getPeer())
- newBounds = (newBounds.toDouble() * peer->getPlatformScaleFactor()).toNearestInt();
- #endif
-
- webViewController->put_Bounds({ newBounds.getX(), newBounds.getY(),
- newBounds.getRight(), newBounds.getBottom() });
- }
- }
-
- void setControlVisible (bool shouldBeVisible) const
- {
- if (webViewController != nullptr)
- webViewController->put_IsVisible (shouldBeVisible);
- }
-
- //==============================================================================
- WebBrowserComponent& owner;
-
- HMODULE webView2LoaderHandle = nullptr;
-
- WinRTWrapper::ComPtr<ICoreWebView2Environment> webViewEnvironment;
- WinRTWrapper::ComPtr<ICoreWebView2Controller> webViewController;
- WinRTWrapper::ComPtr<ICoreWebView2> webView;
-
- EventRegistrationToken navigationStartingToken { 0 },
- newWindowRequestedToken { 0 },
- windowCloseRequestedToken { 0 },
- navigationCompletedToken { 0 },
- webResourceRequestedToken { 0 };
-
- struct URLRequest
- {
- String url;
- StringArray headers;
- MemoryBlock postData;
- };
- URLRequest urlRequest;
-
- bool isCreating = false;
-
- //==============================================================================
- JUCE_DECLARE_WEAK_REFERENCEABLE (WebView2)
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebView2)
- };
-
- #endif
-
- //==============================================================================
- class WebBrowserComponent::Pimpl
- {
- public:
- Pimpl (WebBrowserComponent& owner, const File& dllLocation, const File& userDataFolder, bool useWebView2)
- {
- if (useWebView2)
- {
- #if JUCE_USE_WIN_WEBVIEW2
- try
- {
- internal.reset (new WebView2 (owner, dllLocation, userDataFolder));
- }
- catch (std::runtime_error&) {}
- #endif
- }
-
- ignoreUnused (dllLocation, userDataFolder);
-
- if (internal == nullptr)
- internal.reset (new Win32WebView (owner));
- }
-
- InternalWebViewType& getInternalWebView()
- {
- return *internal;
- }
-
- private:
- std::unique_ptr<InternalWebViewType> internal;
- };
-
- //==============================================================================
- WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
- : 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);
- }
-
- WebBrowserComponent::~WebBrowserComponent()
- {
- }
-
- //==============================================================================
- void WebBrowserComponent::goToURL (const String& url,
- const StringArray* headers,
- const MemoryBlock* postData)
- {
- lastURL = url;
-
- if (headers != nullptr)
- lastHeaders = *headers;
- else
- lastHeaders.clear();
-
- if (postData != nullptr)
- lastPostData = *postData;
- else
- lastPostData.reset();
-
- blankPageShown = false;
-
- if (! browser->getInternalWebView().hasBrowserBeenCreated())
- checkWindowAssociation();
-
- browser->getInternalWebView().goToURL (url, headers, postData);
- }
-
- void WebBrowserComponent::stop()
- {
- browser->getInternalWebView().stop();
- }
-
- void WebBrowserComponent::goBack()
- {
- lastURL.clear();
- blankPageShown = false;
-
- browser->getInternalWebView().goBack();
- }
-
- void WebBrowserComponent::goForward()
- {
- lastURL.clear();
-
- browser->getInternalWebView().goForward();
- }
-
- void WebBrowserComponent::refresh()
- {
- browser->getInternalWebView().refresh();
- }
-
- //==============================================================================
- void WebBrowserComponent::paint (Graphics& g)
- {
- if (! browser->getInternalWebView().hasBrowserBeenCreated())
- {
- g.fillAll (Colours::white);
- checkWindowAssociation();
- }
- }
-
- void WebBrowserComponent::checkWindowAssociation()
- {
- if (isShowing())
- {
- if (! browser->getInternalWebView().hasBrowserBeenCreated() && getPeer() != nullptr)
- {
- browser->getInternalWebView().createBrowser();
- reloadLastURL();
- }
- else
- {
- if (blankPageShown)
- goBack();
- }
- }
- else
- {
- if (browser != nullptr && unloadPageWhenBrowserIsHidden && ! blankPageShown)
- {
- // when the component becomes invisible, some stuff like flash
- // carries on playing audio, so we need to force it onto a blank
- // page to avoid this..
-
- blankPageShown = true;
- browser->getInternalWebView().goToURL ("about:blank", 0, 0);
- }
- }
- }
-
- void WebBrowserComponent::reloadLastURL()
- {
- if (lastURL.isNotEmpty())
- {
- goToURL (lastURL, &lastHeaders, &lastPostData);
- lastURL.clear();
- }
- }
-
- void WebBrowserComponent::parentHierarchyChanged()
- {
- checkWindowAssociation();
- }
-
- void WebBrowserComponent::resized()
- {
- browser->getInternalWebView().setWebViewSize (getWidth(), getHeight());
- }
-
- void WebBrowserComponent::visibilityChanged()
- {
- checkWindowAssociation();
- }
-
- void WebBrowserComponent::focusGained (FocusChangeType)
- {
- browser->getInternalWebView().focusGained();
- }
-
- void WebBrowserComponent::clearCookies()
- {
- HeapBlock<::INTERNET_CACHE_ENTRY_INFOA> entry;
- ::DWORD entrySize = sizeof (::INTERNET_CACHE_ENTRY_INFOA);
- ::HANDLE urlCacheHandle = ::FindFirstUrlCacheEntryA ("cookie:", entry.getData(), &entrySize);
-
- if (urlCacheHandle == nullptr && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- entry.realloc (1, entrySize);
- urlCacheHandle = ::FindFirstUrlCacheEntryA ("cookie:", entry.getData(), &entrySize);
- }
-
- if (urlCacheHandle != nullptr)
- {
- for (;;)
- {
- ::DeleteUrlCacheEntryA (entry.getData()->lpszSourceUrlName);
-
- if (::FindNextUrlCacheEntryA (urlCacheHandle, entry.getData(), &entrySize) == 0)
- {
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- entry.realloc (1, entrySize);
-
- if (::FindNextUrlCacheEntryA (urlCacheHandle, entry.getData(), &entrySize) != 0)
- continue;
- }
-
- break;
- }
- }
-
- FindCloseUrlCache (urlCacheHandle);
- }
- }
-
- } // namespace juce
|