diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ee48c809c8..2cadbe892b 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1295,6 +1295,9 @@ GUI_App::GUI_App() //app config initializes early becasuse it is used in instance checking in OrcaSlicer.cpp this->init_app_config(); this->init_download_path(); +#if wxUSE_WEBVIEW_EDGE + this->init_webview_runtime(); +#endif reset_to_active(); } @@ -2045,6 +2048,20 @@ void GUI_App::init_download_path() } } +#if wxUSE_WEBVIEW_EDGE +void GUI_App::init_webview_runtime() +{ + // Check WebView Runtime + if (!WebView::CheckWebViewRuntime()) { + int nRet = wxMessageBox(_L("Orca Slicer requires the Microsoft WebView2 Runtime to operate certain features.\nClick Yes to install it now."), + _L("WebView2 Runtime"), wxYES_NO); + if (nRet == wxYES) { + WebView::DownloadAndInstallWebViewRuntime(); + } + } +} +#endif + void GUI_App::init_app_config() { // Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release. diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 32572107cb..6e24605922 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -340,6 +340,9 @@ private: bool init_opengl(); void init_download_path(); +#if wxUSE_WEBVIEW_EDGE + void init_webview_runtime(); +#endif static unsigned get_colour_approx_luma(const wxColour& colour); static bool dark_mode(); const wxColour get_label_default_clr_system(); diff --git a/src/slic3r/GUI/Widgets/WebView.cpp b/src/slic3r/GUI/Widgets/WebView.cpp index 68e07e29e3..38afbfbd46 100644 --- a/src/slic3r/GUI/Widgets/WebView.cpp +++ b/src/slic3r/GUI/Widgets/WebView.cpp @@ -16,6 +16,8 @@ #ifdef __WIN32__ #include +#include +#include #elif defined __linux__ #include #define WEBKIT_API @@ -38,6 +40,61 @@ webkit_javascript_result_unref (WebKitJavascriptResult *js_result); #endif #ifdef __WIN32__ +// Run Download and Install in another thread so we don't block the UI thread +DWORD DownloadAndInstallWV2RT() { + + int returnCode = 2; // Download failed + // Use fwlink to download WebView2 Bootstrapper at runtime and invoke installation + // Broken/Invalid Https Certificate will fail to download + // Use of the download link below is governed by the below terms. You may acquire the link + // for your use at https://developer.microsoft.com/microsoft-edge/webview2/. Microsoft owns + // all legal right, title, and interest in and to the WebView2 Runtime Bootstrapper + // ("Software") and related documentation, including any intellectual property in the + // Software. You must acquire all code, including any code obtained from a Microsoft URL, + // under a separate license directly from Microsoft, including a Microsoft download site + // (e.g., https://developer.microsoft.com/microsoft-edge/webview2/). + // HRESULT hr = URLDownloadToFileW(NULL, L"https://go.microsoft.com/fwlink/p/?LinkId=2124703", + // L".\\plugin\\MicrosoftEdgeWebview2Setup.exe", 0, 0); + fs::path target_file_path = (fs::temp_directory_path() / "MicrosoftEdgeWebview2Setup.exe"); + bool downloaded = false; + Slic3r::Http::get("https://go.microsoft.com/fwlink/p/?LinkId=2124703") + .on_error([](std::string body, std::string error, unsigned http_status) { + + }) + .on_complete([&downloaded, target_file_path](std::string body, unsigned http_status) { + fs::fstream file(target_file_path, std::ios::out | std::ios::binary | std::ios::trunc); + file.write(body.c_str(), body.size()); + file.flush(); + file.close(); + + downloaded = true; + }) + .perform_sync(); + // Sleep for 1 second to wait for the buffer writen into disk + std::this_thread::sleep_for(1000ms); + if (downloaded) { + // Either Package the WebView2 Bootstrapper with your app or download it using fwlink + // Then invoke install at Runtime. + SHELLEXECUTEINFOW shExInfo = {0}; + shExInfo.cbSize = sizeof(shExInfo); + shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + shExInfo.hwnd = 0; + shExInfo.lpVerb = L"runas"; + shExInfo.lpFile = target_file_path.generic_wstring().c_str(); + shExInfo.lpParameters = L" /install"; + shExInfo.lpDirectory = 0; + shExInfo.nShow = 0; + shExInfo.hInstApp = 0; + + if (ShellExecuteExW(&shExInfo)) { + WaitForSingleObject(shExInfo.hProcess, INFINITE); + returnCode = 0; // Install successfull + } else { + returnCode = 1; // Install failed + } + } + return returnCode; +} class WebViewEdge : public wxWebViewEdge { @@ -260,7 +317,19 @@ wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url) g_webviews.push_back(webView); return webView; } +#if wxUSE_WEBVIEW_EDGE +bool WebView::CheckWebViewRuntime() +{ + wxWebViewFactoryEdge factory; + auto wxVersion = factory.GetVersionInfo(); + return wxVersion.GetMajor() != 0; +} +bool WebView::DownloadAndInstallWebViewRuntime() +{ + return DownloadAndInstallWV2RT() == 0; +} +#endif void WebView::LoadUrl(wxWebView * webView, wxString const &url) { auto url2 = url; diff --git a/src/slic3r/GUI/Widgets/WebView.hpp b/src/slic3r/GUI/Widgets/WebView.hpp index ca76fadb80..5879afffe9 100644 --- a/src/slic3r/GUI/Widgets/WebView.hpp +++ b/src/slic3r/GUI/Widgets/WebView.hpp @@ -7,7 +7,10 @@ class WebView { public: static wxWebView *CreateWebView(wxWindow *parent, wxString const &url); - +#if wxUSE_WEBVIEW_EDGE + static bool CheckWebViewRuntime(); + static bool DownloadAndInstallWebViewRuntime(); +#endif static void LoadUrl(wxWebView * webView, wxString const &url); static bool RunScript(wxWebView * webView, wxString const & msg);