diff --git a/include/wx/webview_chromium.h b/include/wx/webview_chromium.h index dc20c894f2..7ff2fa9774 100644 --- a/include/wx/webview_chromium.h +++ b/include/wx/webview_chromium.h @@ -26,7 +26,7 @@ struct ImplData; class WXDLLIMPEXP_WEBVIEW_CHROMIUM wxWebViewChromium : public wxWebView { public: - wxWebViewChromium() {} + wxWebViewChromium() { Init(); } wxWebViewChromium(wxWindow* parent, wxWindowID id, @@ -36,6 +36,8 @@ public: long style = 0, const wxString& name = wxWebViewNameStr) { + Init(); + Create(parent, id, url, pos, size, style, name); } @@ -68,6 +70,7 @@ public: virtual void EnableHistory(bool enable = true) override; virtual void Stop() override; virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) override; + virtual bool SetProxy(const wxString& proxy) override; virtual wxString GetPageSource() const override; virtual wxString GetPageText() const override; @@ -130,6 +133,9 @@ protected: virtual void DoSetPage(const wxString& html, const wxString& baseUrl) override; private: + // Common part of all ctors. + void Init(); + // Actually create the browser: this can only be done once the window is // created in wxGTK. bool DoCreateBrowser(const wxString& url); diff --git a/interface/wx/webview.h b/interface/wx/webview.h index 44f84e9f5d..7bbda33d1b 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -1237,8 +1237,17 @@ public: The @a proxy string must be a valid proxy specification, e.g. @c http://my.local.proxy.corp:8080 - @note Currently this function is only implemented in WebKit2 and Edge - backends and must be called before Create() for the latter one. + Currently this function is only implemented in WebKit2, Edge and + Chromium backends and only WebKit2 backend allows to set the proxy + after creating the webview, so it is recommended to call it before + Create(): + @code + auto webview = wxWebView::New(); + if ( !webview->SetProxy("http://127.0.0.1:8080") ) { + wxLogWarning("Setting proxy failed!"); + } + webview->Create(parent, wxID_ANY); + @endcode @return @true if proxy was set successfully or @false if it failed, e.g. because this is not supported by the currently used backend. diff --git a/src/common/webview_chromium.cpp b/src/common/webview_chromium.cpp index 7e766f4636..7fccdefe57 100644 --- a/src/common/webview_chromium.cpp +++ b/src/common/webview_chromium.cpp @@ -43,6 +43,7 @@ wxGCC_WARNING_SUPPRESS(unused-parameter) #include "include/cef_app.h" #include "include/cef_browser.h" #include "include/cef_client.h" +#include "include/cef_request_context_handler.h" #include "include/cef_scheme.h" #include "include/cef_string_visitor.h" #include "include/cef_version.h" @@ -88,6 +89,10 @@ struct ImplData wxString m_initialURL; #endif // __WXGTK__ + // We also remember the proxy passed to wxWebView::SetProxy() as we can + // only set it when creating the browser currently. + wxString m_proxy; + // These flags are used when destroying wxWebViewChromium, see its dtor. bool m_calledDoClose = false; bool m_calledOnBeforeClose = false; @@ -370,6 +375,11 @@ private: using namespace wxCEF; +void wxWebViewChromium::Init() +{ + m_implData = new ImplData{}; +} + bool wxWebViewChromium::Create(wxWindow* parent, wxWindowID id, const wxString& url, @@ -398,8 +408,6 @@ bool wxWebViewChromium::Create(wxWindow* parent, MSWDisableComposited(); #endif // __WXMSW__ - m_implData = new ImplData{}; - m_clientHandler = new ClientHandler{*this}; m_clientHandler->AddRef(); @@ -482,13 +490,48 @@ bool wxWebViewChromium::DoCreateBrowser(const wxString& url) const wxSize sz = GetClientSize(); info.SetAsChild(handle, {0, 0, sz.x, sz.y}); + // Create a request context (which will possibly remain empty) to allow + // setting the proxy if it was specified. + CefRefPtr reqContext; + + const auto& proxy = m_implData->m_proxy; + if ( !proxy.empty() ) + { + CefRequestContextSettings reqSettings; + reqContext = CefRequestContext::CreateContext(reqSettings, nullptr); + + // The structure of "proxy" dictionary seems to be documented at + // + // https://developer.chrome.com/docs/extensions/reference/proxy/ + // + // but it looks like we can also use a much simpler dictionary instead + // of defining "ProxyRules" sub-dictionary as documented there, so just + // do this instead. + auto proxyDict = CefDictionaryValue::Create(); + auto proxyVal = CefValue::Create(); + + if ( !proxyDict->SetString("mode", "fixed_servers") || + !proxyDict->SetString("server", proxy.ToStdWstring()) || + !proxyVal->SetDictionary(proxyDict) ) + { + // This is really not supposed to happen. + wxFAIL_MSG("constructing proxy value failed?"); + } + + CefString error; + if ( !reqContext->SetPreference("proxy", proxyVal, error) ) + { + wxLogError(_("Failed to set proxy \"%s\": %s"), proxy, error.ToWString()); + } + } + if ( !CefBrowserHost::CreateBrowser( info, CefRefPtr{m_clientHandler}, url.ToStdString(), browsersettings, nullptr, // No extra info - nullptr // Use global request context + reqContext ) ) { wxLogTrace(TRACE_CEF, "CefBrowserHost::CreateBrowser() failed"); @@ -809,6 +852,15 @@ void wxWebViewChromium::Reload(wxWebViewReloadFlags flags) } } +bool wxWebViewChromium::SetProxy(const wxString& proxy) +{ + wxCHECK_MSG( !m_clientHandler, false, "should be called before Create()" ); + + m_implData->m_proxy = proxy; + + return true; +} + wxString wxWebViewChromium::GetPageSource() const { return m_pageSource;