From ce44b8638fd867d81816cb7100cede73ec00c96a Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 8 Aug 2024 15:21:54 +0200 Subject: [PATCH 01/14] Open external browser for login --- src/slic3r/GUI/Plater.cpp | 13 +++++++++++-- src/slic3r/GUI/UserAccountCommunication.cpp | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9c70d60074..5c029495a4 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -876,12 +876,20 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) }); this->q->Bind(EVT_OPEN_PRUSAAUTH, [this](OpenPrusaAuthEvent& evt) { BOOST_LOG_TRIVIAL(info) << "open login browser: " << evt.data; + /* std::string dialog_msg; LoginWebViewDialog dialog(this->q, dialog_msg, evt.data); if (dialog.ShowModal() != wxID_OK) { return; } user_account->on_login_code_recieved(dialog_msg); + */ + DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); + #ifdef __linux__ + if (DownloaderUtils::Worker::perform_registration_linux) + DesktopIntegrationDialog::perform_downloader_desktop_integration(); + #endif // __linux__ + wxGetApp().open_login_browser_with_dialog(evt.data); }); this->q->Bind(EVT_UA_LOGGEDOUT, [this](UserAccountSuccessEvent& evt) { @@ -895,9 +903,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) sidebar->update_printer_presets_combobox(); wxGetApp().update_wizard_login_page(); this->show_action_buttons(this->ready_to_slice); - - LogoutWebViewDialog dlg(this->q); + // Needed only when using internal web browser to login (which is case of config wizard) + LogoutWebViewDialog dlg(this->q); dlg.ShowModal(); + // }); this->q->Bind(EVT_UA_ID_USER_SUCCESS, [this](UserAccountSuccessEvent& evt) { diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 0a7f261755..9f7b356f7f 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -334,7 +334,7 @@ wxString UserAccountCommunication::get_login_redirect_url() { BOOST_LOG_TRIVIAL(info) << "code verifier: " << m_code_verifier; BOOST_LOG_TRIVIAL(info) << "code challenge: " << code_challenge; - wxString url = GUI::format_wxstr(L"%1%/o/authorize/?embed=1&client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); + wxString url = GUI::format_wxstr(L"%1%/o/authorize/?client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%&choose_account=1", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); return url; } From 47d793ffb3e73debf600e937e97cab78efe6928f Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 13 Aug 2024 19:13:49 +0200 Subject: [PATCH 02/14] Open login in browser only for external services --- src/slic3r/GUI/Plater.cpp | 13 ++++++++++--- src/slic3r/GUI/UserAccount.hpp | 2 +- src/slic3r/GUI/UserAccountCommunication.cpp | 13 ++++++++----- src/slic3r/GUI/UserAccountCommunication.hpp | 2 +- src/slic3r/GUI/UserAccountSession.hpp | 2 +- src/slic3r/GUI/WebViewDialog.cpp | 10 +++++----- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5c029495a4..4b9428fe7b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -875,11 +875,18 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) user_account->on_login_code_recieved(evt.data); }); this->q->Bind(EVT_OPEN_PRUSAAUTH, [this](OpenPrusaAuthEvent& evt) { - BOOST_LOG_TRIVIAL(info) << "open login browser: " << evt.data; - /* + BOOST_LOG_TRIVIAL(info) << "open login browser: " << evt.data.first; std::string dialog_msg; - LoginWebViewDialog dialog(this->q, dialog_msg, evt.data); + LoginWebViewDialog dialog(this->q, dialog_msg, evt.data.first); if (dialog.ShowModal() != wxID_OK) { + if(!dialog_msg.empty()) { + DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); +#ifdef __linux__ + if (DownloaderUtils::Worker::perform_registration_linux) + DesktopIntegrationDialog::perform_downloader_desktop_integration(); +#endif // __linux__ + wxGetApp().open_login_browser_with_dialog(evt.data.second); + } return; } user_account->on_login_code_recieved(dialog_msg); diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index e38efdd02c..387605302d 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -38,7 +38,7 @@ public: bool is_logged(); void do_login(); void do_logout(); - wxString get_login_redirect_url() { return m_communication->get_login_redirect_url(); } + wxString get_login_redirect_url() { return m_communication->get_login_redirect_url(true); } void set_remember_session(bool remember); void toggle_remember_session(); diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 9f7b356f7f..8da213dc65 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -321,7 +321,7 @@ void UserAccountCommunication::on_uuid_map_success() } } -wxString UserAccountCommunication::get_login_redirect_url() { +wxString UserAccountCommunication::get_login_redirect_url(bool internal) { auto& sc = Utils::ServiceConfig::instance(); const std::string AUTH_HOST = sc.account_url(); const std::string CLIENT_ID = client_id(); @@ -334,14 +334,17 @@ wxString UserAccountCommunication::get_login_redirect_url() { BOOST_LOG_TRIVIAL(info) << "code verifier: " << m_code_verifier; BOOST_LOG_TRIVIAL(info) << "code challenge: " << code_challenge; - wxString url = GUI::format_wxstr(L"%1%/o/authorize/?client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%&choose_account=1", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); - + wxString url = GUI::format_wxstr(L"%1%/o/authorize/?embed=1&client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); + if (!internal) { + url += L"&choose_account=1"; + } return url; } void UserAccountCommunication::login_redirect() { - wxString url = get_login_redirect_url(); - wxQueueEvent(m_evt_handler,new OpenPrusaAuthEvent(GUI::EVT_OPEN_PRUSAAUTH, std::move(url))); + wxString url1 = get_login_redirect_url(true); + wxString url2 = get_login_redirect_url(false); + wxQueueEvent(m_evt_handler,new OpenPrusaAuthEvent(GUI::EVT_OPEN_PRUSAAUTH, {std::move(url1), std::move(url2)})); } bool UserAccountCommunication::is_logged() diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index 623cbf7e6d..336fbf944f 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -42,7 +42,7 @@ public: void do_login(); void do_logout(); void do_clear(); - wxString get_login_redirect_url(); + wxString get_login_redirect_url(bool internal); // Trigger function starts various remote operations void enqueue_connect_status_action(); void enqueue_connect_printer_models_action(); diff --git a/src/slic3r/GUI/UserAccountSession.hpp b/src/slic3r/GUI/UserAccountSession.hpp index 1733ec728f..d540319ab3 100644 --- a/src/slic3r/GUI/UserAccountSession.hpp +++ b/src/slic3r/GUI/UserAccountSession.hpp @@ -14,7 +14,7 @@ namespace Slic3r { namespace GUI { -using OpenPrusaAuthEvent = Event; +using OpenPrusaAuthEvent = Event>; using UserAccountSuccessEvent = Event; using UserAccountFailEvent = Event; using UserAccountTimeEvent = Event; diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 9d5ec17a1f..f03c8dd979 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1370,22 +1370,22 @@ void PrinterPickWebViewDialog::on_dpi_changed(const wxRect &suggested_rect) } LoginWebViewDialog::LoginWebViewDialog(wxWindow *parent, std::string &ret_val, const wxString& url) - : WebViewDialog(parent - , url - , _L("Log in dialog"), - wxSize(50 * wxGetApp().em_unit(), 80 * wxGetApp().em_unit()) - , {}) + : WebViewDialog(parent, url, _L("Log in dialog"), wxSize(50 * wxGetApp().em_unit(), 80 * wxGetApp().em_unit()), {}) , m_ret_val(ret_val) { Centre(); } void LoginWebViewDialog::on_navigation_request(wxWebViewEvent &evt) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " " << evt.GetURL(); wxString url = evt.GetURL(); if (url.starts_with(L"prusaslicer")) { evt.Veto(); m_ret_val = into_u8(url); EndModal(wxID_OK); + } else if (!url.starts_with(L"https://account.prusa3d.com")) { + m_ret_val = GUI::into_u8(url); + EndModal(wxID_EXECUTE); } } void LoginWebViewDialog::on_dpi_changed(const wxRect &suggested_rect) From c93631a504340d05ee9ad6d2da4d312e180215e6 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 14 Aug 2024 09:37:46 +0200 Subject: [PATCH 03/14] followup --- src/slic3r/GUI/Plater.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4b9428fe7b..a061d95e3a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -885,18 +885,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) if (DownloaderUtils::Worker::perform_registration_linux) DesktopIntegrationDialog::perform_downloader_desktop_integration(); #endif // __linux__ - wxGetApp().open_login_browser_with_dialog(evt.data.second); + wxGetApp().open_login_browser_with_dialog(/*dialog_msg*/evt.data.second); } - return; + } else { + user_account->on_login_code_recieved(dialog_msg); } - user_account->on_login_code_recieved(dialog_msg); - */ - DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); - #ifdef __linux__ - if (DownloaderUtils::Worker::perform_registration_linux) - DesktopIntegrationDialog::perform_downloader_desktop_integration(); - #endif // __linux__ - wxGetApp().open_login_browser_with_dialog(evt.data); }); this->q->Bind(EVT_UA_LOGGEDOUT, [this](UserAccountSuccessEvent& evt) { From e6313aa5e06e8f8534edc4dd1f4ec4ee13f75488 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 14 Aug 2024 16:00:55 +0200 Subject: [PATCH 04/14] CLI option for single instance only with prusaslicer:// url --- src/libslic3r/PrintConfig.cpp | 4 ++++ src/slic3r/GUI/InstanceCheck.cpp | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index fbe9fbaa51..9a0bd956e6 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -5664,6 +5664,10 @@ CLIMiscConfigDef::CLIMiscConfigDef() "or an existing PrusaSlicer window is activated. " "Overrides the \"single_instance\" configuration value from application preferences."); + def = this->add("single_instance_on_url", coBool); + def->label = L("Single instance mode for prusaslicer url"); + def->tooltip = L("Works as single_instance but only if prusaslicer url is present."); + def = this->add("datadir", coString); def->label = L("Data directory"); def->tooltip = L("Load and store settings at the given directory. This is useful for maintaining different profiles or including configurations from a network storage."); diff --git a/src/slic3r/GUI/InstanceCheck.cpp b/src/slic3r/GUI/InstanceCheck.cpp index ce96c1c42f..882e2e3259 100644 --- a/src/slic3r/GUI/InstanceCheck.cpp +++ b/src/slic3r/GUI/InstanceCheck.cpp @@ -69,18 +69,29 @@ namespace instance_check_internal //if (argc < 2) // return ret; std::vector arguments { argv[0] }; + bool send_if_url = false; + bool has_url = false; for (int i = 1; i < argc; ++i) { const std::string token = argv[i]; + if (token.find("prusaslicer://") == 0) { + BOOST_LOG_TRIVIAL(info) << "url found: " << token; + has_url = true; + } // Processing of boolean command line arguments shall match DynamicConfig::read_cli(). if (token == "--single-instance") ret.should_send = true; else if (token == "--no-single-instance") ret.should_send = false; + else if (token == "--single-instance-on-url") + send_if_url = true; else arguments.emplace_back(token); } + if (send_if_url && has_url) { + ret.should_send = true; + } ret.cl_string = escape_strings_cstyle(arguments); - BOOST_LOG_TRIVIAL(debug) << "single instance: " << + BOOST_LOG_TRIVIAL(info) << "single instance: " << (ret.should_send.has_value() ? (*ret.should_send ? "true" : "false") : "undefined") << ". other params: " << ret.cl_string; return ret; From 07320325e11811918aac360388e907c12a6712fa Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 16 Aug 2024 11:15:49 +0200 Subject: [PATCH 05/14] Remove old url protocol desktop files before opening browser for login --- src/slic3r/GUI/DesktopIntegrationDialog.cpp | 55 +++++++++++++++++++-- src/slic3r/GUI/DesktopIntegrationDialog.hpp | 1 + src/slic3r/GUI/Plater.cpp | 6 ++- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp index d8f3dc025b..639d167229 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp @@ -139,20 +139,35 @@ bool contains_path_dir(const std::string& p, const std::string& dir_name) if (p.empty() || dir_name.empty()) return false; boost::filesystem::path path(p + (p[p.size()-1] == '/' ? "" : "/") + dir_name); - if (boost::filesystem::exists(path) && boost::filesystem::is_directory(path)) { + boost::system::error_code ec; + if (boost::filesystem::exists(path, ec) && !ec) { //BOOST_LOG_TRIVIAL(debug) << path.string() << " " << std::oct << boost::filesystem::status(path).permissions(); - return true; //boost::filesystem::status(path).permissions() & boost::filesystem::owner_write; + return boost::filesystem::is_directory(path); //boost::filesystem::status(path).permissions() & boost::filesystem::owner_write; } else BOOST_LOG_TRIVIAL(debug) << path.string() << " doesnt exists"; return false; } + +boost::filesystem::path get_existing_dir(const std::string& sub, const std::string& dir_name) +{ + assert(!p.empty() && !dir_name.empty()); + boost::filesystem::path path = boost::filesystem::path(sub) / dir_name; + boost::system::error_code ec; + if (!boost::filesystem::exists(path, ec) || ec) { + return boost::filesystem::path(); + } + if (!boost::filesystem::is_directory(path, ec) || ec) { + return boost::filesystem::path(); + } + return path; +} // Creates directory in path if not exists yet void create_dir(const boost::filesystem::path& path) { - if (boost::filesystem::exists(path)) + boost::system::error_code ec; + if (boost::filesystem::exists(path, ec) && !ec) return; BOOST_LOG_TRIVIAL(debug)<< "creating " << path.string(); - boost::system::error_code ec; boost::filesystem::create_directory(path, ec); if (ec) BOOST_LOG_TRIVIAL(error)<< "create directory failed: " << ec.message(); @@ -627,6 +642,38 @@ void DesktopIntegrationDialog::undo_downloader_registration() } // There is no need to undo xdg-mime default command. It is done automatically when desktop file is deleted. } +void DesktopIntegrationDialog::undo_downloader_registration_rigid() +{ + // Try ro find any PrusaSlicerURLProtocol.desktop files including alpha and beta and get rid of them + + // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. + // If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used. + // $XDG_DATA_DIRS defines the preference-ordered set of base directories to search for data files in addition to the $XDG_DATA_HOME base directory. + // The directories in $XDG_DATA_DIRS should be seperated with a colon ':'. + // If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used. + std::vectortarget_candidates; + target_candidates.emplace_back(GUI::into_u8(wxFileName::GetHomeDir()) + "/.local/share"); + resolve_path_from_var("XDG_DATA_HOME", target_candidates); + resolve_path_from_var("XDG_DATA_DIRS", target_candidates); + for (const std::string cand : target_candidates) { + boost::filesystem::path apps_path = get_existing_dir(cand, "applications"); + if (apps_path.empty()) { + continue; + } + for (const std::string& suffix : {"" , "-beta", "-alpha"}) { + boost::filesystem::path file_path = apps_path / GUI::format("PrusaSlicerURLProtocol%1%.desktop", suffix); + boost::system::error_code ec; + if (!boost::filesystem::exists(file_path, ec) || ec) { + continue; + } + if (!boost::filesystem::remove(file_path, ec) || ec) { + BOOST_LOG_TRIVIAL(error) << "Failed to remove file " << file_path << " ec: " << ec.message(); + continue; + } + BOOST_LOG_TRIVIAL(info) << "Desktop File removed: " << file_path; + } + } +} DesktopIntegrationDialog::DesktopIntegrationDialog(wxWindow *parent) : wxDialog(parent, wxID_ANY, _(L("Desktop Integration")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.hpp b/src/slic3r/GUI/DesktopIntegrationDialog.hpp index 4c2263d0fd..c26ad6b8d4 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.hpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.hpp @@ -39,6 +39,7 @@ public: static void perform_downloader_desktop_integration(); static void undo_downloader_registration(); + static void undo_downloader_registration_rigid(); private: }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a061d95e3a..b7f51b5fb1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -881,9 +881,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) if (dialog.ShowModal() != wxID_OK) { if(!dialog_msg.empty()) { DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); -#ifdef __linux__ +#if defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION) if (DownloaderUtils::Worker::perform_registration_linux) DesktopIntegrationDialog::perform_downloader_desktop_integration(); +#elif defined(__linux__) && ! defined(SLIC3R_DESKTOP_INTEGRATION) + // ! defined(SLIC3R_DESKTOP_INTEGRATION) means the desktop integration was done elswhere f.e. by flatpack + // Remove all desktop files registering prusaslicer:// url done by previous versions. + DesktopIntegrationDialog::undo_downloader_registration_rigid(); #endif // __linux__ wxGetApp().open_login_browser_with_dialog(/*dialog_msg*/evt.data.second); } From 23cc50c9f5aab71e66a4d6cbf313c6243f51119b Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 16 Aug 2024 12:06:01 +0200 Subject: [PATCH 06/14] fix of opening external browser --- src/slic3r/GUI/WebViewDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index f03c8dd979..39dd83775c 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1383,7 +1383,7 @@ void LoginWebViewDialog::on_navigation_request(wxWebViewEvent &evt) evt.Veto(); m_ret_val = into_u8(url); EndModal(wxID_OK); - } else if (!url.starts_with(L"https://account.prusa3d.com")) { + } else if (!url.starts_with(L"https://account.prusa3d.com") && url.starts_with(L"http")) { m_ret_val = GUI::into_u8(url); EndModal(wxID_EXECUTE); } From 3e6b4ba443499cd8324d311d80d79fdfb7886986 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 16 Aug 2024 14:02:11 +0200 Subject: [PATCH 07/14] Fix of login in internal browser --- src/slic3r/GUI/UserAccount.hpp | 2 +- src/slic3r/GUI/UserAccountCommunication.cpp | 10 ++++------ src/slic3r/GUI/UserAccountCommunication.hpp | 3 ++- src/slic3r/GUI/WebViewDialog.cpp | 12 ++++++++---- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 387605302d..e38efdd02c 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -38,7 +38,7 @@ public: bool is_logged(); void do_login(); void do_logout(); - wxString get_login_redirect_url() { return m_communication->get_login_redirect_url(true); } + wxString get_login_redirect_url() { return m_communication->get_login_redirect_url(); } void set_remember_session(bool remember); void toggle_remember_session(); diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 8da213dc65..9420d3c2fe 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -321,7 +321,8 @@ void UserAccountCommunication::on_uuid_map_success() } } -wxString UserAccountCommunication::get_login_redirect_url(bool internal) { +// Generates and stores Code Verifier - second call deletes previous one. +wxString UserAccountCommunication::get_login_redirect_url() { auto& sc = Utils::ServiceConfig::instance(); const std::string AUTH_HOST = sc.account_url(); const std::string CLIENT_ID = client_id(); @@ -335,15 +336,12 @@ wxString UserAccountCommunication::get_login_redirect_url(bool internal) { BOOST_LOG_TRIVIAL(info) << "code challenge: " << code_challenge; wxString url = GUI::format_wxstr(L"%1%/o/authorize/?embed=1&client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); - if (!internal) { - url += L"&choose_account=1"; - } return url; } void UserAccountCommunication::login_redirect() { - wxString url1 = get_login_redirect_url(true); - wxString url2 = get_login_redirect_url(false); + wxString url1 = get_login_redirect_url(); + wxString url2 = url1 + L"&choose_account=1"; wxQueueEvent(m_evt_handler,new OpenPrusaAuthEvent(GUI::EVT_OPEN_PRUSAAUTH, {std::move(url1), std::move(url2)})); } diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index 336fbf944f..fdf749e56b 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -42,7 +42,8 @@ public: void do_login(); void do_logout(); void do_clear(); - wxString get_login_redirect_url(bool internal); + // Generates and stores Code Verifier - second call deletes previous one. + wxString get_login_redirect_url(); // Trigger function starts various remote operations void enqueue_connect_status_action(); void enqueue_connect_printer_models_action(); diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 39dd83775c..448a646762 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -8,6 +8,7 @@ #include "slic3r/GUI/format.hpp" #include "slic3r/GUI/WebView.hpp" #include "slic3r/GUI/WebViewPlatformUtils.hpp" +#include "slic3r/Utils/ServiceConfig.hpp" #include "slic3r/GUI/MsgDialog.hpp" #include "slic3r/GUI/Field.hpp" @@ -1377,15 +1378,18 @@ LoginWebViewDialog::LoginWebViewDialog(wxWindow *parent, std::string &ret_val, c } void LoginWebViewDialog::on_navigation_request(wxWebViewEvent &evt) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " " << evt.GetURL(); wxString url = evt.GetURL(); if (url.starts_with(L"prusaslicer")) { evt.Veto(); m_ret_val = into_u8(url); EndModal(wxID_OK); - } else if (!url.starts_with(L"https://account.prusa3d.com") && url.starts_with(L"http")) { - m_ret_val = GUI::into_u8(url); - EndModal(wxID_EXECUTE); + } else if (url.starts_with(L"http")) { + auto& sc = Utils::ServiceConfig::instance(); + if (!url.starts_with(GUI::from_u8(sc.account_url()))) { + m_ret_val = GUI::into_u8(url); + EndModal(wxID_EXECUTE); + } + } } void LoginWebViewDialog::on_dpi_changed(const wxRect &suggested_rect) From a41ee17a68e9df0c5f65df7986c0264a10250b42 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 16 Aug 2024 14:40:34 +0200 Subject: [PATCH 08/14] Undo desktop registration before registering new one --- src/slic3r/GUI/Plater.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b7f51b5fb1..fa0108e8ec 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -881,13 +881,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) if (dialog.ShowModal() != wxID_OK) { if(!dialog_msg.empty()) { DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); -#if defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION) +#if defined(__linux__) + // Remove all desktop files registering prusaslicer:// url done by previous versions. + DesktopIntegrationDialog::undo_downloader_registration_rigid(); +#if defined(SLIC3R_DESKTOP_INTEGRATION) if (DownloaderUtils::Worker::perform_registration_linux) DesktopIntegrationDialog::perform_downloader_desktop_integration(); -#elif defined(__linux__) && ! defined(SLIC3R_DESKTOP_INTEGRATION) - // ! defined(SLIC3R_DESKTOP_INTEGRATION) means the desktop integration was done elswhere f.e. by flatpack - // Remove all desktop files registering prusaslicer:// url done by previous versions. - DesktopIntegrationDialog::undo_downloader_registration_rigid(); +#endif // SLIC3R_DESKTOP_INTEGRATION #endif // __linux__ wxGetApp().open_login_browser_with_dialog(/*dialog_msg*/evt.data.second); } From ab358cb4c4e4674e765069e7df5f84dc360d6b0e Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 16 Aug 2024 14:42:53 +0200 Subject: [PATCH 09/14] User underscore instead of minus --- src/slic3r/GUI/DesktopIntegrationDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp index 639d167229..2ca450bf9c 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp @@ -529,12 +529,12 @@ void DesktopIntegrationDialog::perform_downloader_desktop_integration() std::string version(SLIC3R_VERSION); if (version.find("alpha") != std::string::npos) { - version_suffix = "-alpha"; + version_suffix = "_alpha"; name_suffix = " - alpha"; } else if (version.find("beta") != std::string::npos) { - version_suffix = "-beta"; + version_suffix = "_beta"; name_suffix = " - beta"; } @@ -660,7 +660,7 @@ void DesktopIntegrationDialog::undo_downloader_registration_rigid() if (apps_path.empty()) { continue; } - for (const std::string& suffix : {"" , "-beta", "-alpha"}) { + for (const std::string& suffix : {"" , "-beta", "-alpha" , "_beta", "_alpha"}) { boost::filesystem::path file_path = apps_path / GUI::format("PrusaSlicerURLProtocol%1%.desktop", suffix); boost::system::error_code ec; if (!boost::filesystem::exists(file_path, ec) || ec) { From 2bde97fb1170452279a875994c371fcf702ac940 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 19 Aug 2024 16:08:27 +0200 Subject: [PATCH 10/14] Keep login dialog opened while opening 3rd vendor in external browser. --- src/slic3r/GUI/ConfigWizardWebViewPage.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 44 ++++++++++++++------- src/slic3r/GUI/UserAccount.hpp | 3 +- src/slic3r/GUI/UserAccountCommunication.cpp | 21 +++++++++- src/slic3r/GUI/UserAccountCommunication.hpp | 4 +- src/slic3r/GUI/WebViewDialog.cpp | 13 +++--- src/slic3r/GUI/WebViewDialog.hpp | 8 +++- 7 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizardWebViewPage.cpp b/src/slic3r/GUI/ConfigWizardWebViewPage.cpp index 87e7f6ccbe..e5e1db837a 100644 --- a/src/slic3r/GUI/ConfigWizardWebViewPage.cpp +++ b/src/slic3r/GUI/ConfigWizardWebViewPage.cpp @@ -23,7 +23,7 @@ ConfigWizardWebViewPage::ConfigWizardWebViewPage(ConfigWizard *parent) // Create the webview m_browser_sizer = new wxBoxSizer(wxHORIZONTAL); - m_browser = WebView::CreateWebView(this, p_user_account->get_login_redirect_url(), {}); + m_browser = WebView::CreateWebView(this, p_user_account->generate_login_redirect_url(), {}); if (!m_browser) { // TRN Config wizard page with a log in page. wxStaticText* fail_text = new wxStaticText(this, wxID_ANY, _L("Failed to load a web browser. Logging in is not possible in the moment.")); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fa0108e8ec..f59d51bd22 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -272,6 +272,9 @@ struct Plater::priv std::unique_ptr notification_manager; std::unique_ptr user_account; std::unique_ptr preset_archive_database; + // Login dialog needs to be kept somewhere. + // It is created inside evt Bind. But it might be closed from another event. + LoginWebViewDialog* login_dialog { nullptr }; ProjectDirtyStateManager dirty_state; @@ -875,26 +878,31 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) user_account->on_login_code_recieved(evt.data); }); this->q->Bind(EVT_OPEN_PRUSAAUTH, [this](OpenPrusaAuthEvent& evt) { + if (login_dialog != nullptr) { + this->q->RemoveChild(login_dialog); + login_dialog->Destroy(); + login_dialog = nullptr; + } BOOST_LOG_TRIVIAL(info) << "open login browser: " << evt.data.first; std::string dialog_msg; - LoginWebViewDialog dialog(this->q, dialog_msg, evt.data.first); - if (dialog.ShowModal() != wxID_OK) { - if(!dialog_msg.empty()) { - DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); -#if defined(__linux__) - // Remove all desktop files registering prusaslicer:// url done by previous versions. - DesktopIntegrationDialog::undo_downloader_registration_rigid(); -#if defined(SLIC3R_DESKTOP_INTEGRATION) - if (DownloaderUtils::Worker::perform_registration_linux) - DesktopIntegrationDialog::perform_downloader_desktop_integration(); -#endif // SLIC3R_DESKTOP_INTEGRATION -#endif // __linux__ - wxGetApp().open_login_browser_with_dialog(/*dialog_msg*/evt.data.second); - } - } else { + login_dialog = new LoginWebViewDialog(this->q, dialog_msg, evt.data.first, this->q); + if (login_dialog->ShowModal() == wxID_OK) { user_account->on_login_code_recieved(dialog_msg); } }); + this->q->Bind(EVT_OPEN_EXTERNAL_LOGIN, [this](wxCommandEvent& evt) { + DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); +#if defined(__linux__) + // Remove all desktop files registering prusaslicer:// url done by previous versions. + DesktopIntegrationDialog::undo_downloader_registration_rigid(); +#if defined(SLIC3R_DESKTOP_INTEGRATION) + if (DownloaderUtils::Worker::perform_registration_linux) + DesktopIntegrationDialog::perform_downloader_desktop_integration(); +#endif // SLIC3R_DESKTOP_INTEGRATION +#endif // __linux__ + wxString url = user_account->get_login_redirect_url()+ L"&choose_account=1"; + wxGetApp().open_login_browser_with_dialog(into_u8(url)); + }); this->q->Bind(EVT_UA_LOGGEDOUT, [this](UserAccountSuccessEvent& evt) { user_account->clear(); @@ -914,6 +922,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) }); this->q->Bind(EVT_UA_ID_USER_SUCCESS, [this](UserAccountSuccessEvent& evt) { + if (login_dialog != nullptr) { + this->q->RemoveChild(login_dialog); + login_dialog->Destroy(); + login_dialog = nullptr; + } + // There are multiple handlers and we want to notify all evt.Skip(); std::string who = user_account->get_username(); diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index e38efdd02c..b65b3684e0 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -38,8 +38,9 @@ public: bool is_logged(); void do_login(); void do_logout(); + wxString generate_login_redirect_url() { return m_communication->generate_login_redirect_url(); } wxString get_login_redirect_url() { return m_communication->get_login_redirect_url(); } - + void set_remember_session(bool remember); void toggle_remember_session(); bool get_remember_session(); diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 9420d3c2fe..9dc553cce7 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -322,7 +322,8 @@ void UserAccountCommunication::on_uuid_map_success() } // Generates and stores Code Verifier - second call deletes previous one. -wxString UserAccountCommunication::get_login_redirect_url() { +wxString UserAccountCommunication::generate_login_redirect_url() +{ auto& sc = Utils::ServiceConfig::instance(); const std::string AUTH_HOST = sc.account_url(); const std::string CLIENT_ID = client_id(); @@ -338,9 +339,25 @@ wxString UserAccountCommunication::get_login_redirect_url() { wxString url = GUI::format_wxstr(L"%1%/o/authorize/?embed=1&client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); return url; } +wxString UserAccountCommunication::get_login_redirect_url() const +{ + auto& sc = Utils::ServiceConfig::instance(); + const std::string AUTH_HOST = sc.account_url(); + const std::string CLIENT_ID = client_id(); + const std::string REDIRECT_URI = "prusaslicer://login"; + CodeChalengeGenerator ccg; + std::string code_challenge = ccg.generate_chalenge(m_code_verifier); + wxString language = GUI::wxGetApp().current_language_code(); + language = language.SubString(0, 1); + BOOST_LOG_TRIVIAL(info) << "code verifier: " << m_code_verifier; + BOOST_LOG_TRIVIAL(info) << "code challenge: " << code_challenge; + + wxString url = GUI::format_wxstr(L"%1%/o/authorize/?embed=1&client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); + return url; +} void UserAccountCommunication::login_redirect() { - wxString url1 = get_login_redirect_url(); + wxString url1 = generate_login_redirect_url(); wxString url2 = url1 + L"&choose_account=1"; wxQueueEvent(m_evt_handler,new OpenPrusaAuthEvent(GUI::EVT_OPEN_PRUSAAUTH, {std::move(url1), std::move(url2)})); } diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index fdf749e56b..95fc99fabc 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -43,7 +43,9 @@ public: void do_logout(); void do_clear(); // Generates and stores Code Verifier - second call deletes previous one. - wxString get_login_redirect_url(); + wxString generate_login_redirect_url(); + // Only recreates the url with already existing url (if generate was not called before - url will be faulty) + wxString get_login_redirect_url() const; // Trigger function starts various remote operations void enqueue_connect_status_action(); void enqueue_connect_printer_models_action(); diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 448a646762..7e9e8e9600 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -27,6 +27,7 @@ // to set authorization cookie for all WebKit requests to Connect #define AUTH_VIA_FETCH_OVERRIDE 0 +wxDEFINE_EVENT(EVT_OPEN_EXTERNAL_LOGIN, wxCommandEvent); namespace pt = boost::property_tree; @@ -1370,9 +1371,10 @@ void PrinterPickWebViewDialog::on_dpi_changed(const wxRect &suggested_rect) Refresh(); } -LoginWebViewDialog::LoginWebViewDialog(wxWindow *parent, std::string &ret_val, const wxString& url) +LoginWebViewDialog::LoginWebViewDialog(wxWindow *parent, std::string &ret_val, const wxString& url, wxEvtHandler* evt_handler) : WebViewDialog(parent, url, _L("Log in dialog"), wxSize(50 * wxGetApp().em_unit(), 80 * wxGetApp().em_unit()), {}) , m_ret_val(ret_val) + , p_evt_handler(evt_handler) { Centre(); } @@ -1385,11 +1387,12 @@ void LoginWebViewDialog::on_navigation_request(wxWebViewEvent &evt) EndModal(wxID_OK); } else if (url.starts_with(L"http")) { auto& sc = Utils::ServiceConfig::instance(); - if (!url.starts_with(GUI::from_u8(sc.account_url()))) { - m_ret_val = GUI::into_u8(url); - EndModal(wxID_EXECUTE); + if (!m_evt_sent && !url.starts_with(GUI::from_u8(sc.account_url()))) { + wxCommandEvent* evt = new wxCommandEvent(EVT_OPEN_EXTERNAL_LOGIN); + evt->SetString(url); + p_evt_handler->QueueEvent(evt); + m_evt_sent = true; } - } } void LoginWebViewDialog::on_dpi_changed(const wxRect &suggested_rect) diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index cc9a76e6f5..92619b0a50 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -17,6 +17,8 @@ class wxWebView; class wxWebViewEvent; +wxDECLARE_EVENT(EVT_OPEN_EXTERNAL_LOGIN, wxCommandEvent); + namespace Slic3r { namespace GUI { @@ -276,12 +278,14 @@ public: class LoginWebViewDialog : public WebViewDialog { public: - LoginWebViewDialog(wxWindow *parent, std::string &ret_val, const wxString& url); + LoginWebViewDialog(wxWindow *parent, std::string &ret_val, const wxString& url, wxEvtHandler* evt_handler); void on_navigation_request(wxWebViewEvent &evt) override; void on_dpi_changed(const wxRect &suggested_rect) override; private: - std::string &m_ret_val; + std::string& m_ret_val; + wxEvtHandler* p_evt_handler; + bool m_evt_sent{ false }; }; class LogoutWebViewDialog : public WebViewDialog From 17300d75490507353f578bc8a2277cb04fa65a76 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 19 Aug 2024 16:42:29 +0200 Subject: [PATCH 11/14] Fix of closing login dialog --- src/slic3r/GUI/Plater.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f59d51bd22..36160150cd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -878,17 +878,17 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) user_account->on_login_code_recieved(evt.data); }); this->q->Bind(EVT_OPEN_PRUSAAUTH, [this](OpenPrusaAuthEvent& evt) { - if (login_dialog != nullptr) { - this->q->RemoveChild(login_dialog); - login_dialog->Destroy(); - login_dialog = nullptr; - } BOOST_LOG_TRIVIAL(info) << "open login browser: " << evt.data.first; std::string dialog_msg; login_dialog = new LoginWebViewDialog(this->q, dialog_msg, evt.data.first, this->q); if (login_dialog->ShowModal() == wxID_OK) { user_account->on_login_code_recieved(dialog_msg); } + if (login_dialog != nullptr) { + this->q->RemoveChild(login_dialog); + login_dialog->Destroy(); + login_dialog = nullptr; + } }); this->q->Bind(EVT_OPEN_EXTERNAL_LOGIN, [this](wxCommandEvent& evt) { DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); @@ -923,11 +923,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_UA_ID_USER_SUCCESS, [this](UserAccountSuccessEvent& evt) { if (login_dialog != nullptr) { - this->q->RemoveChild(login_dialog); - login_dialog->Destroy(); - login_dialog = nullptr; + login_dialog->EndModal(wxID_CANCEL); } - // There are multiple handlers and we want to notify all evt.Skip(); std::string who = user_account->get_username(); From 02ddb361084ec83b658f26873d4f8bc52213fc66 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 21 Aug 2024 13:40:43 +0200 Subject: [PATCH 12/14] Login url with service. Changed code for registering custom url to not check downloader dest.. --- src/slic3r/GUI/ConfigWizard.cpp | 10 +++++++--- src/slic3r/GUI/ConfigWizard.hpp | 3 ++- src/slic3r/GUI/GUI_App.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 12 ++++++++++-- src/slic3r/GUI/UserAccount.hpp | 2 +- src/slic3r/GUI/UserAccountCommunication.cpp | 10 +++++----- src/slic3r/GUI/UserAccountCommunication.hpp | 2 +- 7 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 59ea6386aa..c3151657d8 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1718,7 +1718,7 @@ bool PageDownloader::on_finish_downloader() const bool DownloaderUtils::Worker::perform_registration_linux = false; #endif // __linux__ -bool DownloaderUtils::Worker::perform_register(const std::string& path) +bool DownloaderUtils::Worker::perform_download_register(const std::string& path) { boost::filesystem::path aux_dest (path); boost::system::error_code ec; @@ -1734,6 +1734,10 @@ bool DownloaderUtils::Worker::perform_register(const std::string& path) } BOOST_LOG_TRIVIAL(info) << "Downloader registration: Directory for downloads: " << chosen_dest.string(); wxGetApp().app_config->set("url_downloader_dest", chosen_dest.string()); + perform_url_register(); +} +bool DownloaderUtils::Worker::perform_url_register() +{ #ifdef _WIN32 // Registry key creation for "prusaslicer://" URL @@ -1793,12 +1797,12 @@ bool DownloaderUtils::Worker::on_finish() { BOOST_LOG_TRIVIAL(debug) << "PageDownloader::on_finish_downloader ac_value " << ac_value << " downloader_checked " << downloader_checked; if (ac_value && downloader_checked) { // already registered but we need to do it again - if (!perform_register(GUI::into_u8(path_name()))) + if (!perform_download_register(GUI::into_u8(path_name()))) return false; app_config->set("downloader_url_registered", "1"); } else if (!ac_value && downloader_checked) { // register - if (!perform_register(GUI::into_u8(path_name()))) + if (!perform_download_register(GUI::into_u8(path_name()))) return false; app_config->set("downloader_url_registered", "1"); } else if (ac_value && !downloader_checked) { diff --git a/src/slic3r/GUI/ConfigWizard.hpp b/src/slic3r/GUI/ConfigWizard.hpp index ba39d531ac..cc9d36d806 100644 --- a/src/slic3r/GUI/ConfigWizard.hpp +++ b/src/slic3r/GUI/ConfigWizard.hpp @@ -52,7 +52,8 @@ namespace DownloaderUtils { void set_path_name(const std::string& name); bool on_finish(); - static bool perform_register(const std::string& path); + static bool perform_download_register(const std::string& path); + static bool perform_url_register(); #ifdef __linux__ static bool perform_registration_linux; #endif // __linux__ diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1ef8b24ffc..905478207e 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3337,7 +3337,7 @@ void GUI_App::show_downloader_registration_dialog() , true, wxYES_NO); if (msg.ShowModal() == wxID_YES) { auto downloader_worker = new DownloaderUtils::Worker(nullptr); - downloader_worker->perform_register(app_config->get("url_downloader_dest")); + downloader_worker->perform_download_register(app_config->get("url_downloader_dest")); #if defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION) if (DownloaderUtils::Worker::perform_registration_linux) DesktopIntegrationDialog::perform_downloader_desktop_integration(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 36160150cd..4eeece1932 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -891,7 +891,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) } }); this->q->Bind(EVT_OPEN_EXTERNAL_LOGIN, [this](wxCommandEvent& evt) { - DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); + DownloaderUtils::Worker::perform_url_register(); #if defined(__linux__) // Remove all desktop files registering prusaslicer:// url done by previous versions. DesktopIntegrationDialog::undo_downloader_registration_rigid(); @@ -900,7 +900,15 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) DesktopIntegrationDialog::perform_downloader_desktop_integration(); #endif // SLIC3R_DESKTOP_INTEGRATION #endif // __linux__ - wxString url = user_account->get_login_redirect_url()+ L"&choose_account=1"; + std::string service; + if (evt.GetString().Find("accounts.google.com") != wxString::npos) { + service = "google"; + } else if (evt.GetString().Find("appleid.apple.com") != wxString::npos) { + service = "apple"; + } else if (evt.GetString().Find("facebook.com") != wxString::npos) { + service = "facebook"; + } + wxString url = user_account->get_login_redirect_url(service); wxGetApp().open_login_browser_with_dialog(into_u8(url)); }); diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index b65b3684e0..22787f9d7c 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -39,7 +39,7 @@ public: void do_login(); void do_logout(); wxString generate_login_redirect_url() { return m_communication->generate_login_redirect_url(); } - wxString get_login_redirect_url() { return m_communication->get_login_redirect_url(); } + wxString get_login_redirect_url(const std::string& service = std::string()) { return m_communication->get_login_redirect_url(service); } void set_remember_session(bool remember); void toggle_remember_session(); diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 9dc553cce7..27a8dd2957 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -322,7 +322,7 @@ void UserAccountCommunication::on_uuid_map_success() } // Generates and stores Code Verifier - second call deletes previous one. -wxString UserAccountCommunication::generate_login_redirect_url() +wxString UserAccountCommunication::generate_login_redirect_url() { auto& sc = Utils::ServiceConfig::instance(); const std::string AUTH_HOST = sc.account_url(); @@ -339,7 +339,7 @@ wxString UserAccountCommunication::generate_login_redirect_url() wxString url = GUI::format_wxstr(L"%1%/o/authorize/?embed=1&client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); return url; } -wxString UserAccountCommunication::get_login_redirect_url() const +wxString UserAccountCommunication::get_login_redirect_url(const std::string& service/* = std::string()*/) const { auto& sc = Utils::ServiceConfig::instance(); const std::string AUTH_HOST = sc.account_url(); @@ -349,10 +349,10 @@ wxString UserAccountCommunication::get_login_redirect_url() const std::string code_challenge = ccg.generate_chalenge(m_code_verifier); wxString language = GUI::wxGetApp().current_language_code(); language = language.SubString(0, 1); - BOOST_LOG_TRIVIAL(info) << "code verifier: " << m_code_verifier; - BOOST_LOG_TRIVIAL(info) << "code challenge: " << code_challenge; - wxString url = GUI::format_wxstr(L"%1%/o/authorize/?embed=1&client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&language=%5%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI, language); + std::string params = GUI::format("embed=1&client_id=%1%&response_type=code&code_challenge=%2%&code_challenge_method=S256&scope=basic_info&redirect_uri=%3%&language=%4%", CLIENT_ID, code_challenge, REDIRECT_URI, language); + params = Http::url_encode(params); + wxString url = GUI::format_wxstr(L"%1%/login/%2%?next=/o/authorize/?%3%", AUTH_HOST, service, params); return url; } void UserAccountCommunication::login_redirect() diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index 95fc99fabc..f4ec0dbf99 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -45,7 +45,7 @@ public: // Generates and stores Code Verifier - second call deletes previous one. wxString generate_login_redirect_url(); // Only recreates the url with already existing url (if generate was not called before - url will be faulty) - wxString get_login_redirect_url() const; + wxString get_login_redirect_url(const std::string& service = std::string()) const; // Trigger function starts various remote operations void enqueue_connect_status_action(); void enqueue_connect_printer_models_action(); From fa94b9fb5422ea1f0eac76b5990b8d0a0c4a6139 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 26 Aug 2024 14:03:32 +0200 Subject: [PATCH 13/14] Fix of return value --- src/slic3r/GUI/ConfigWizard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index c3151657d8..7dec1da12a 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1734,7 +1734,7 @@ bool DownloaderUtils::Worker::perform_download_register(const std::string& path) } BOOST_LOG_TRIVIAL(info) << "Downloader registration: Directory for downloads: " << chosen_dest.string(); wxGetApp().app_config->set("url_downloader_dest", chosen_dest.string()); - perform_url_register(); + return perform_url_register(); } bool DownloaderUtils::Worker::perform_url_register() { From 5871ad2e51e032a20931165c85400d4a8fdfd1b2 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 27 Aug 2024 17:23:48 +0200 Subject: [PATCH 14/14] Open external browser in config wizard. --- src/slic3r/GUI/ConfigWizardWebViewPage.cpp | 16 ++++++++++++++-- src/slic3r/GUI/ConfigWizardWebViewPage.hpp | 6 +++++- src/slic3r/GUI/Plater.cpp | 13 +++++++++---- src/slic3r/GUI/WebViewDialog.cpp | 5 ++++- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizardWebViewPage.cpp b/src/slic3r/GUI/ConfigWizardWebViewPage.cpp index e5e1db837a..0023707813 100644 --- a/src/slic3r/GUI/ConfigWizardWebViewPage.cpp +++ b/src/slic3r/GUI/ConfigWizardWebViewPage.cpp @@ -6,9 +6,11 @@ #include "Plater.hpp" #include "slic3r/GUI/I18N.hpp" #include "format.hpp" - +#include "Event.hpp" #include +wxDEFINE_EVENT(EVT_OPEN_EXTERNAL_LOGIN_WIZARD, wxCommandEvent); + namespace Slic3r { namespace GUI { wxDEFINE_EVENT(EVT_LOGIN_VIA_WIZARD, Event); @@ -124,7 +126,17 @@ void ConfigWizardWebViewPage::on_navigation_request(wxWebViewEvent &evt) evt.Veto(); m_vetoed = true; wxPostEvent(wxGetApp().plater(), Event(EVT_LOGIN_VIA_WIZARD, into_u8(url))); + } else if (url.Find("accounts.google.com") != wxString::npos + || url.Find("appleid.apple.com") != wxString::npos + || url.Find("facebook.com") != wxString::npos) + { + auto& sc = Utils::ServiceConfig::instance(); + if (!m_evt_sent && !url.starts_with(GUI::from_u8(sc.account_url()))) { + wxCommandEvent evt(EVT_OPEN_EXTERNAL_LOGIN_WIZARD); + evt.SetString(url); + wxPostEvent(wxGetApp().plater(), evt); + m_evt_sent = true; + } } } - }} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/ConfigWizardWebViewPage.hpp b/src/slic3r/GUI/ConfigWizardWebViewPage.hpp index 8ad6638063..2a873de805 100644 --- a/src/slic3r/GUI/ConfigWizardWebViewPage.hpp +++ b/src/slic3r/GUI/ConfigWizardWebViewPage.hpp @@ -2,15 +2,18 @@ #define slic3r_ConfigWizardWebViewPage_hpp_ #include "ConfigWizard_private.hpp" -#include "Event.hpp" +#include class wxWebView; class wxWebViewEvent; +wxDECLARE_EVENT(EVT_OPEN_EXTERNAL_LOGIN_WIZARD, wxCommandEvent); + namespace Slic3r { namespace GUI { wxDECLARE_EVENT(EVT_LOGIN_VIA_WIZARD, Event); + /* struct ConfigWizardPage: wxPanel { @@ -61,6 +64,7 @@ private: wxStaticText *m_text{nullptr}; bool m_load_error_page{false}; bool m_vetoed{false}; + bool m_evt_sent{false}; }; }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4eeece1932..3ac107988e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -126,6 +126,7 @@ #include "UserAccountUtils.hpp" #include "DesktopIntegrationDialog.hpp" #include "WebViewDialog.hpp" +#include "ConfigWizardWebViewPage.hpp" #include "PresetArchiveDatabase.hpp" #ifdef __APPLE__ @@ -890,8 +891,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) login_dialog = nullptr; } }); - this->q->Bind(EVT_OPEN_EXTERNAL_LOGIN, [this](wxCommandEvent& evt) { - DownloaderUtils::Worker::perform_url_register(); + + auto open_external_login = [this](wxCommandEvent& evt){ + DownloaderUtils::Worker::perform_url_register(); #if defined(__linux__) // Remove all desktop files registering prusaslicer:// url done by previous versions. DesktopIntegrationDialog::undo_downloader_registration_rigid(); @@ -909,8 +911,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) service = "facebook"; } wxString url = user_account->get_login_redirect_url(service); - wxGetApp().open_login_browser_with_dialog(into_u8(url)); - }); + wxGetApp().open_login_browser_with_dialog(into_u8(url), nullptr, false); + }; + + this->q->Bind(EVT_OPEN_EXTERNAL_LOGIN_WIZARD, open_external_login); + this->q->Bind(EVT_OPEN_EXTERNAL_LOGIN, open_external_login); this->q->Bind(EVT_UA_LOGGEDOUT, [this](UserAccountSuccessEvent& evt) { user_account->clear(); diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 7e9e8e9600..eac2873152 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1385,7 +1385,10 @@ void LoginWebViewDialog::on_navigation_request(wxWebViewEvent &evt) evt.Veto(); m_ret_val = into_u8(url); EndModal(wxID_OK); - } else if (url.starts_with(L"http")) { + } else if (url.Find("accounts.google.com") != wxString::npos + || url.Find("appleid.apple.com") != wxString::npos + || url.Find("facebook.com") != wxString::npos) + { auto& sc = Utils::ServiceConfig::instance(); if (!m_evt_sent && !url.starts_with(GUI::from_u8(sc.account_url()))) { wxCommandEvent* evt = new wxCommandEvent(EVT_OPEN_EXTERNAL_LOGIN);