#include "WebView.hpp" #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/Utils/MacDarkMode.hpp" #include #include #include #include #include "wx/private/jsscriptwrapper.h" #ifdef __WIN32__ #include "../WebView2.h" #elif defined __linux__ #include #define WEBKIT_API struct WebKitWebView; struct WebKitJavascriptResult; extern "C" { WEBKIT_API void webkit_web_view_run_javascript (WebKitWebView *web_view, const gchar *script, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WEBKIT_API WebKitJavascriptResult * webkit_web_view_run_javascript_finish (WebKitWebView *web_view, GAsyncResult *result, GError **error); WEBKIT_API void webkit_javascript_result_unref (WebKitJavascriptResult *js_result); } #endif class FakeWebView : public wxWebView { virtual bool Create(wxWindow* parent, wxWindowID id, const wxString& url, const wxPoint& pos, const wxSize& size, long style, const wxString& name) override { return false; } virtual wxString GetCurrentTitle() const override { return wxString(); } virtual wxString GetCurrentURL() const override { return wxString(); } virtual bool IsBusy() const override { return false; } virtual bool IsEditable() const override { return false; } virtual void LoadURL(const wxString& url) override { } virtual void Print() override { } virtual void RegisterHandler(wxSharedPtr handler) override { } virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) override { } virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const override { return false; } virtual void SetEditable(bool enable = true) override { } virtual void Stop() override { } virtual bool CanGoBack() const override { return false; } virtual bool CanGoForward() const override { return false; } virtual void GoBack() override { } virtual void GoForward() override { } virtual void ClearHistory() override { } virtual void EnableHistory(bool enable = true) override { } virtual wxVector> GetBackwardHistory() override { return {}; } virtual wxVector> GetForwardHistory() override { return {}; } virtual void LoadHistoryItem(wxSharedPtr item) override { } virtual bool CanSetZoomType(wxWebViewZoomType type) const override { return false; } virtual float GetZoomFactor() const override { return 0.0f; } virtual wxWebViewZoomType GetZoomType() const override { return wxWebViewZoomType(); } virtual void SetZoomFactor(float zoom) override { } virtual void SetZoomType(wxWebViewZoomType zoomType) override { } virtual bool CanUndo() const override { return false; } virtual bool CanRedo() const override { return false; } virtual void Undo() override { } virtual void Redo() override { } virtual void* GetNativeBackend() const override { return nullptr; } virtual void DoSetPage(const wxString& html, const wxString& baseUrl) override { } }; wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url) { #if wxUSE_WEBVIEW_EDGE // Check if a fixed version of edge is present in // $executable_path/edge_fixed and use it wxFileName edgeFixedDir(wxStandardPaths::Get().GetExecutablePath()); edgeFixedDir.SetFullName(""); edgeFixedDir.AppendDir("edge_fixed"); if (edgeFixedDir.DirExists()) { wxWebViewEdge::MSWSetBrowserExecutableDir(edgeFixedDir.GetFullPath()); wxLogMessage("Using fixed edge version"); } #endif auto url2 = url; #ifdef __WIN32__ url2.Replace("\\", "/"); #endif if (!url2.empty()) { url2 = wxURI(url2).BuildURI(); } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << url2.ToUTF8(); auto webView = wxWebView::New(); if (webView) { #ifdef __WIN32__ webView->SetUserAgent(wxString::Format("BBL-Slicer/v%s", SLIC3R_VERSION)); webView->Create(parent, wxID_ANY, url2, wxDefaultPosition, wxDefaultSize); //We register the wxfs:// protocol for testing purposes webView->RegisterHandler(wxSharedPtr(new wxWebViewArchiveHandler("bbl"))); //And the memory: file system webView->RegisterHandler(wxSharedPtr(new wxWebViewFSHandler("memory"))); #else // With WKWebView handlers need to be registered before creation webView->RegisterHandler(wxSharedPtr(new wxWebViewArchiveHandler("wxfs"))); // And the memory: file system webView->RegisterHandler(wxSharedPtr(new wxWebViewFSHandler("memory"))); webView->Create(parent, wxID_ANY, url2, wxDefaultPosition, wxDefaultSize); webView->SetUserAgent(wxString::Format("BBL-Slicer/v%s", SLIC3R_VERSION)); #endif #ifndef __WIN32__ Slic3r::GUI::wxGetApp().CallAfter([webView] { #endif BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": begin to add script message handler for wx."; Slic3r::GUI::wxGetApp().set_adding_script_handler(true); if (!webView->AddScriptMessageHandler("wx")) wxLogError("Could not add script message handler"); Slic3r::GUI::wxGetApp().set_adding_script_handler(false); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": finished add script message handler for wx."; #ifndef __WIN32__ }); #endif webView->EnableContextMenu(false); } else { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": failed. Use fake web view."; webView = new FakeWebView; } return webView; } void WebView::LoadUrl(wxWebView * webView, wxString const &url) { auto url2 = url; #ifdef __WIN32__ url2.Replace("\\", "/"); #endif if (!url2.empty()) { url2 = wxURI(url2).BuildURI(); } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << url2.ToUTF8(); webView->LoadURL(url2); } bool WebView::RunScript(wxWebView *webView, wxString const &javascript) { if (Slic3r::GUI::wxGetApp().get_mode() == Slic3r::comDevelop) wxLogMessage("Running JavaScript:\n%s\n", javascript); try { #ifdef __WIN32__ ICoreWebView2 * webView2 = (ICoreWebView2 *) webView->GetNativeBackend(); if (webView2 == nullptr) return false; int count = 0; wxJSScriptWrapper wrapJS(javascript, &count); return webView2->ExecuteScript(wrapJS.GetWrappedCode(), NULL) == 0; #elif defined __WXMAC__ WKWebView * wkWebView = (WKWebView *) webView->GetNativeBackend(); int count = 0; wxJSScriptWrapper wrapJS(javascript, &count); Slic3r::GUI::WKWebView_evaluateJavaScript(wkWebView, wrapJS.GetWrappedCode(), nullptr); return true; #else WebKitWebView *wkWebView = (WebKitWebView *) webView->GetNativeBackend(); webkit_web_view_run_javascript( wkWebView, javascript.utf8_str(), NULL, [](GObject *wkWebView, GAsyncResult *res, void *) { GError * error = NULL; auto result = webkit_web_view_run_javascript_finish((WebKitWebView*)wkWebView, res, &error); if (!result) g_error_free (error); else webkit_javascript_result_unref (result); }, NULL); return true; #endif } catch (std::exception &e) { return false; } }