From 2bde97fb1170452279a875994c371fcf702ac940 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 19 Aug 2024 16:08:27 +0200 Subject: [PATCH] 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