mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-12 10:21:17 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b9b05ed85 |
@@ -25,8 +25,9 @@ DockPanel::DockPanel(wxWindow* parent,
|
|||||||
const std::string& html,
|
const std::string& html,
|
||||||
MessageHandler on_message,
|
MessageHandler on_message,
|
||||||
CloseHandler on_close,
|
CloseHandler on_close,
|
||||||
CloseHandler on_destroyed)
|
CloseHandler on_destroyed,
|
||||||
: WebPanel(parent, web_hosting::orca_bridge_script())
|
const wxString& profile)
|
||||||
|
: WebPanel(parent, web_hosting::orca_bridge_script(), profile)
|
||||||
, m_html(html)
|
, m_html(html)
|
||||||
, m_on_message(std::move(on_message))
|
, m_on_message(std::move(on_message))
|
||||||
, m_on_close(std::move(on_close))
|
, m_on_close(std::move(on_close))
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
class wxWindow;
|
class wxWindow;
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
@@ -27,7 +29,8 @@ public:
|
|||||||
const std::string& html,
|
const std::string& html,
|
||||||
MessageHandler on_message,
|
MessageHandler on_message,
|
||||||
CloseHandler on_close,
|
CloseHandler on_close,
|
||||||
CloseHandler on_destroyed);
|
CloseHandler on_destroyed,
|
||||||
|
const wxString& profile = wxEmptyString);
|
||||||
~DockPanel() override;
|
~DockPanel() override;
|
||||||
|
|
||||||
// Main thread only.
|
// Main thread only.
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ WebDialog::WebDialog(wxWindow* parent,
|
|||||||
SubmitHandler on_submit,
|
SubmitHandler on_submit,
|
||||||
CloseHandler on_close,
|
CloseHandler on_close,
|
||||||
CloseHandler on_destroyed,
|
CloseHandler on_destroyed,
|
||||||
long wx_style)
|
long wx_style,
|
||||||
|
const wxString& profile)
|
||||||
: WebViewHostDialog(parent, wxID_ANY, title, wxDefaultPosition, size, wx_style)
|
: WebViewHostDialog(parent, wxID_ANY, title, wxDefaultPosition, size, wx_style)
|
||||||
, m_html(html)
|
, m_html(html)
|
||||||
, m_on_message(std::move(on_message))
|
, m_on_message(std::move(on_message))
|
||||||
@@ -37,7 +38,7 @@ WebDialog::WebDialog(wxWindow* parent,
|
|||||||
{
|
{
|
||||||
// A tiny bundled bootstrap page brings the webview up; the real plugin HTML
|
// A tiny bundled bootstrap page brings the webview up; the real plugin HTML
|
||||||
// is swapped in via SetPage once the bootstrap finishes loading.
|
// is swapped in via SetPage once the bootstrap finishes loading.
|
||||||
create_webview(web_hosting::BOOTSTRAP_PAGE, title, size, wxSize(320, 240));
|
create_webview(web_hosting::BOOTSTRAP_PAGE, title, size, wxSize(320, 240), profile);
|
||||||
|
|
||||||
// Paint the window/webview in the themed background so there is no white
|
// Paint the window/webview in the themed background so there is no white
|
||||||
// flash before the (transparent) bootstrap page and plugin HTML render.
|
// flash before the (transparent) bootstrap page and plugin HTML render.
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ public:
|
|||||||
SubmitHandler on_submit,
|
SubmitHandler on_submit,
|
||||||
CloseHandler on_close,
|
CloseHandler on_close,
|
||||||
CloseHandler on_destroyed,
|
CloseHandler on_destroyed,
|
||||||
long wx_style = wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER);
|
long wx_style = wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER,
|
||||||
|
const wxString& profile = wxEmptyString);
|
||||||
~WebDialog() override;
|
~WebDialog() override;
|
||||||
|
|
||||||
static void post_message(WebDialog* dialog, const nlohmann::json& data);
|
static void post_message(WebDialog* dialog, const nlohmann::json& data);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
WebPanel::WebPanel(wxWindow* parent, const char* bridge_script)
|
WebPanel::WebPanel(wxWindow* parent, const char* bridge_script, const wxString& profile)
|
||||||
: wxPanel(parent, wxID_ANY)
|
: wxPanel(parent, wxID_ANY)
|
||||||
{
|
{
|
||||||
SetBackgroundColour(wxGetApp().get_window_default_clr());
|
SetBackgroundColour(wxGetApp().get_window_default_clr());
|
||||||
@@ -25,7 +25,7 @@ WebPanel::WebPanel(wxWindow* parent, const char* bridge_script)
|
|||||||
SetSizer(sizer);
|
SetSizer(sizer);
|
||||||
|
|
||||||
// Never null: WebView::CreateWebView substitutes a placeholder view when no backend is available.
|
// Never null: WebView::CreateWebView substitutes a placeholder view when no backend is available.
|
||||||
m_browser = WebView::CreateWebView(this, web_hosting::bootstrap_url());
|
m_browser = WebView::CreateWebView(this, web_hosting::bootstrap_url(), profile);
|
||||||
m_browser->SetBackgroundColour(GetBackgroundColour());
|
m_browser->SetBackgroundColour(GetBackgroundColour());
|
||||||
m_browser->AddUserScript(wxString::FromUTF8(WebViewHostDialog::theme_user_script()));
|
m_browser->AddUserScript(wxString::FromUTF8(WebViewHostDialog::theme_user_script()));
|
||||||
m_browser->AddUserScript(wxString::FromUTF8(WebViewHostDialog::element_defaults_user_script()));
|
m_browser->AddUserScript(wxString::FromUTF8(WebViewHostDialog::element_defaults_user_script()));
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Slic3r { namespace GUI {
|
|||||||
class WebPanel : public wxPanel
|
class WebPanel : public wxPanel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WebPanel(wxWindow* parent, const char* bridge_script);
|
WebPanel(wxWindow* parent, const char* bridge_script, const wxString& profile = wxEmptyString);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxWebView* browser() const { return m_browser; }
|
wxWebView* browser() const { return m_browser; }
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/Utils/MacDarkMode.hpp"
|
#include "slic3r/Utils/MacDarkMode.hpp"
|
||||||
|
|
||||||
|
#include <libslic3r/Utils.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
@@ -72,6 +74,26 @@ webkit_javascript_result_unref (WebKitJavascriptResult *js_result);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Private storage root for an isolated (plugin) profile. Plugin pages must not reach the shared
|
||||||
|
// default store's cookies/session (e.g. the OrcaCloud login), so each profile gets its own dir.
|
||||||
|
// macOS isolates with an in-memory store instead (see CreateWebView), so this is unused there.
|
||||||
|
#if !defined(__WXOSX__)
|
||||||
|
static wxString isolated_profile_path(const wxString& profile)
|
||||||
|
{
|
||||||
|
wxString safe;
|
||||||
|
safe.reserve(profile.size());
|
||||||
|
for (wxString::const_iterator it = profile.begin(); it != profile.end(); ++it) {
|
||||||
|
const wxChar c = *it;
|
||||||
|
const bool keep = (c >= wxT('a') && c <= wxT('z')) || (c >= wxT('A') && c <= wxT('Z')) ||
|
||||||
|
(c >= wxT('0') && c <= wxT('9')) || c == wxT('.') || c == wxT('-') || c == wxT('_');
|
||||||
|
safe += keep ? c : wxT('_');
|
||||||
|
}
|
||||||
|
if (safe.empty())
|
||||||
|
safe = wxT("default");
|
||||||
|
return wxString::FromUTF8((boost::filesystem::path(Slic3r::data_dir()) / "web_profiles" / safe.ToStdString()).string());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
// Run Download and Install in another thread so we don't block the UI thread
|
// Run Download and Install in another thread so we don't block the UI thread
|
||||||
DWORD DownloadAndInstallWV2RT() {
|
DWORD DownloadAndInstallWV2RT() {
|
||||||
@@ -135,6 +157,9 @@ DWORD DownloadAndInstallWV2RT() {
|
|||||||
class WebViewEdge : public wxWebViewEdge
|
class WebViewEdge : public wxWebViewEdge
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
WebViewEdge() = default;
|
||||||
|
explicit WebViewEdge(const wxWebViewConfiguration& config) : wxWebViewEdge(config) {}
|
||||||
|
|
||||||
bool SetUserAgent(const wxString &userAgent) override
|
bool SetUserAgent(const wxString &userAgent) override
|
||||||
{
|
{
|
||||||
bool dark = userAgent.Contains("dark");
|
bool dark = userAgent.Contains("dark");
|
||||||
@@ -213,6 +238,11 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit WebViewWebKit(const wxWebViewConfiguration& config)
|
||||||
|
: wxWebViewWebKit(config)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~WebViewWebKit() override
|
~WebViewWebKit() override
|
||||||
{
|
{
|
||||||
RemoveScriptMessageHandler("wx");
|
RemoveScriptMessageHandler("wx");
|
||||||
@@ -284,7 +314,7 @@ static WebViewRef *webview_ref(wxWebView *webView)
|
|||||||
return webView ? static_cast<WebViewRef *>(webView->GetRefData()) : nullptr;
|
return webView ? static_cast<WebViewRef *>(webView->GetRefData()) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url)
|
wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url, wxString const & profile)
|
||||||
{
|
{
|
||||||
#if wxUSE_WEBVIEW_EDGE
|
#if wxUSE_WEBVIEW_EDGE
|
||||||
// Check if a fixed version of edge is present in
|
// Check if a fixed version of edge is present in
|
||||||
@@ -304,12 +334,36 @@ wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url)
|
|||||||
if (!url2.empty()) { url2 = wxURI(url2).BuildURI(); }
|
if (!url2.empty()) { url2 = wxURI(url2).BuildURI(); }
|
||||||
BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << ": " << url2.ToUTF8();
|
BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << ": " << url2.ToUTF8();
|
||||||
|
|
||||||
|
const bool isolated = !profile.IsEmpty();
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
wxWebView* webView = new WebViewEdge;
|
wxWebView* webView = nullptr;
|
||||||
|
if (isolated) {
|
||||||
|
wxWebViewConfiguration config = wxWebView::NewConfiguration(wxWebViewBackendEdge);
|
||||||
|
config.SetDataPath(isolated_profile_path(profile));
|
||||||
|
webView = new WebViewEdge(config);
|
||||||
|
} else {
|
||||||
|
webView = new WebViewEdge;
|
||||||
|
}
|
||||||
#elif defined(__WXOSX__)
|
#elif defined(__WXOSX__)
|
||||||
wxWebView* webView = new WebViewWebKit;
|
wxWebView* webView = nullptr;
|
||||||
|
if (isolated) {
|
||||||
|
// wx has no SetDataPath on macOS; give the view its own in-memory store instead.
|
||||||
|
wxWebViewConfiguration config = wxWebView::NewConfiguration(wxWebViewBackendWebKit);
|
||||||
|
Slic3r::GUI::WKWebViewConfiguration_setNonPersistentDataStore(config.GetNativeConfiguration());
|
||||||
|
webView = new WebViewWebKit(config);
|
||||||
|
} else {
|
||||||
|
webView = new WebViewWebKit;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
auto webView = wxWebView::New();
|
wxWebView* webView = nullptr;
|
||||||
|
if (isolated) {
|
||||||
|
wxWebViewConfiguration config = wxWebView::NewConfiguration(wxWebViewBackendWebKit);
|
||||||
|
config.SetDataPath(isolated_profile_path(profile));
|
||||||
|
webView = wxWebView::New(config);
|
||||||
|
} else {
|
||||||
|
webView = wxWebView::New();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (webView) {
|
if (webView) {
|
||||||
webView->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
webView->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ wxDECLARE_EVENT(EVT_WEBVIEW_RECREATED, wxCommandEvent);
|
|||||||
class WebView
|
class WebView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static wxWebView *CreateWebView(wxWindow *parent, wxString const &url);
|
// `profile` empty -> the shared default backend store used by all trusted UI.
|
||||||
|
// `profile` non-empty -> a private store keyed by `profile`, so this view shares no
|
||||||
|
// cookies/storage/session with the shared store or any other profile. Used for
|
||||||
|
// plugin-supplied (untrusted) content.
|
||||||
|
static wxWebView *CreateWebView(wxWindow *parent, wxString const &url, wxString const &profile = wxEmptyString);
|
||||||
#if wxUSE_WEBVIEW_EDGE
|
#if wxUSE_WEBVIEW_EDGE
|
||||||
static bool CheckWebViewRuntime();
|
static bool CheckWebViewRuntime();
|
||||||
static bool DownloadAndInstallWebViewRuntime();
|
static bool DownloadAndInstallWebViewRuntime();
|
||||||
|
|||||||
@@ -172,7 +172,8 @@ WebViewHostDialog::WebViewHostDialog(wxWindow* parent,
|
|||||||
bool WebViewHostDialog::create_webview(const std::string& resource_path,
|
bool WebViewHostDialog::create_webview(const std::string& resource_path,
|
||||||
const wxString& title,
|
const wxString& title,
|
||||||
const wxSize& dialog_size,
|
const wxSize& dialog_size,
|
||||||
const wxSize& min_size)
|
const wxSize& min_size,
|
||||||
|
const wxString& profile)
|
||||||
{
|
{
|
||||||
SetTitle(title);
|
SetTitle(title);
|
||||||
SetMinSize(FromDIP(min_size));
|
SetMinSize(FromDIP(min_size));
|
||||||
@@ -181,7 +182,7 @@ bool WebViewHostDialog::create_webview(const std::string& resource_path,
|
|||||||
wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
// Created empty and loaded below, after the user scripts are added, so the first load already has them.
|
// Created empty and loaded below, after the user scripts are added, so the first load already has them.
|
||||||
m_browser = WebView::CreateWebView(this, wxEmptyString);
|
m_browser = WebView::CreateWebView(this, wxEmptyString, profile);
|
||||||
if (m_browser == nullptr) {
|
if (m_browser == nullptr) {
|
||||||
wxLogError("Could not init m_browser");
|
wxLogError("Could not init m_browser");
|
||||||
delete topsizer;
|
delete topsizer;
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ public:
|
|||||||
bool create_webview(const std::string& resource_path,
|
bool create_webview(const std::string& resource_path,
|
||||||
const wxString& title,
|
const wxString& title,
|
||||||
const wxSize& dialog_size = wxSize(820, 660),
|
const wxSize& dialog_size = wxSize(820, 660),
|
||||||
const wxSize& min_size = wxSize(640, 640));
|
const wxSize& min_size = wxSize(640, 640),
|
||||||
|
const wxString& profile = wxEmptyString);
|
||||||
|
|
||||||
void load_url(const wxString& url);
|
void load_url(const wxString& url);
|
||||||
bool run_script(const wxString& script);
|
bool run_script(const wxString& script);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ extern double mac_max_scaling_factor();
|
|||||||
extern void set_miniaturizable(void * window);
|
extern void set_miniaturizable(void * window);
|
||||||
void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &));
|
void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &));
|
||||||
void WKWebView_setTransparentBackground(void * web);
|
void WKWebView_setTransparentBackground(void * web);
|
||||||
|
void WKWebViewConfiguration_setNonPersistentDataStore(void * configuration);
|
||||||
void WKWebView_force_display(void * web);
|
void WKWebView_force_display(void * web);
|
||||||
void set_tag_when_enter_full_screen(bool isfullscreen);
|
void set_tag_when_enter_full_screen(bool isfullscreen);
|
||||||
void set_title_colour_after_set_title(void * window);
|
void set_title_colour_after_set_title(void * window);
|
||||||
|
|||||||
@@ -102,6 +102,15 @@ void WKWebView_setTransparentBackground(void * web)
|
|||||||
[webView registerForDraggedTypes: @[NSFilenamesPboardType]];
|
[webView registerForDraggedTypes: @[NSFilenamesPboardType]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Give a WKWebViewConfiguration its own in-memory website data store, so the view's cookies and
|
||||||
|
// storage neither come from nor leak into the shared default store. Used to isolate plugin web views.
|
||||||
|
void WKWebViewConfiguration_setNonPersistentDataStore(void * configuration)
|
||||||
|
{
|
||||||
|
WKWebViewConfiguration * config = (WKWebViewConfiguration*)configuration;
|
||||||
|
if (config)
|
||||||
|
config.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
|
||||||
|
}
|
||||||
|
|
||||||
// Force a WKWebView to re-lay-out and repaint. Needed for chrome-less popups: the window is
|
// Force a WKWebView to re-lay-out and repaint. Needed for chrome-less popups: the window is
|
||||||
// transparent, so a WKWebView whose layer has no pending frame leaves the whole window invisible
|
// transparent, so a WKWebView whose layer has no pending frame leaves the whole window invisible
|
||||||
// until the user generates input (scroll/arrow). setNeedsDisplay alone does not always reach the
|
// until the user generates input (scroll/arrow). setNeedsDisplay alone does not always reach the
|
||||||
|
|||||||
@@ -390,7 +390,8 @@ py::object ui_create_window(const std::string& html, const std::string& title, i
|
|||||||
|
|
||||||
auto* dlg = new GUI::WebDialog(ui_parent(), wxString::FromUTF8(title), html,
|
auto* dlg = new GUI::WebDialog(ui_parent(), wxString::FromUTF8(title), html,
|
||||||
wxSize(w, h), std::move(msg_adapter), std::move(submit_adapter),
|
wxSize(w, h), std::move(msg_adapter), std::move(submit_adapter),
|
||||||
std::move(on_close), std::move(on_destroyed), PLUGIN_WX_STYLE);
|
std::move(on_close), std::move(on_destroyed), PLUGIN_WX_STYLE,
|
||||||
|
wxString::FromUTF8(plugin_key));
|
||||||
UiRegistry::instance().bind(new_id, dlg, plugin_key);
|
UiRegistry::instance().bind(new_id, dlg, plugin_key);
|
||||||
if (modal) {
|
if (modal) {
|
||||||
dlg->ShowModal();
|
dlg->ShowModal();
|
||||||
@@ -487,7 +488,7 @@ py::object ui_create_dock_panel(const std::string& html, const std::string& titl
|
|||||||
|
|
||||||
auto on_destroyed = [new_id]() { UiRegistry::instance().remove(new_id); };
|
auto on_destroyed = [new_id]() { UiRegistry::instance().remove(new_id); };
|
||||||
auto* panel = new GUI::DockPanel(plater, html, std::move(msg_adapter), make_close_adapter(close_holder),
|
auto* panel = new GUI::DockPanel(plater, html, std::move(msg_adapter), make_close_adapter(close_holder),
|
||||||
std::move(on_destroyed));
|
std::move(on_destroyed), wxString::FromUTF8(plugin_key));
|
||||||
UiRegistry::instance().bind(new_id, panel, plugin_key);
|
UiRegistry::instance().bind(new_id, panel, plugin_key);
|
||||||
plater->add_dock_pane(panel, GUI::plugin_pane_name(plugin_key, title), wxString::FromUTF8(title), dock,
|
plater->add_dock_pane(panel, GUI::plugin_pane_name(plugin_key, title), wxString::FromUTF8(title), dock,
|
||||||
wxSize(w, h), [panel]() { panel->fire_close(); });
|
wxSize(w, h), [panel]() { panel->fire_close(); });
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ constexpr char PLUGIN_PAGE_BRIDGE_JS[] = R"JS(
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
PluginPage::PluginPage(wxWindow* parent, std::shared_ptr<PagesPluginCapability> capability)
|
PluginPage::PluginPage(wxWindow* parent, std::shared_ptr<PagesPluginCapability> capability)
|
||||||
: GUI::WebPanel(parent, PLUGIN_PAGE_BRIDGE_JS)
|
: GUI::WebPanel(parent, PLUGIN_PAGE_BRIDGE_JS,
|
||||||
|
wxString::FromUTF8(capability ? capability->identity().plugin_key : std::string()))
|
||||||
, m_cap(std::move(capability))
|
, m_cap(std::move(capability))
|
||||||
, m_lifetime(std::make_shared<std::atomic<PluginPage*>>(this))
|
, m_lifetime(std::make_shared<std::atomic<PluginPage*>>(this))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user