diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 27a8dd2957..78227501aa 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -512,6 +512,14 @@ void UserAccountCommunication::on_activate_window(bool active) std::lock_guard lck(m_thread_stop_mutex); m_window_is_active = active; } + auto now = std::time(nullptr); + BOOST_LOG_TRIVIAL(info) << "UserAccountCommunication activate: active " << active; + if (active && m_next_token_refresh_at - now < 60) { + BOOST_LOG_TRIVIAL(info) << "Enqueue access token refresh on activation"; + enqueue_refresh(); + m_token_timer->Stop(); + } + } void UserAccountCommunication::wakeup_session_thread() @@ -527,12 +535,16 @@ void UserAccountCommunication::set_refresh_time(int seconds) { assert(m_token_timer); m_token_timer->Stop(); - int miliseconds = std::max(seconds * 1000 - 66666, 60000); - m_token_timer->StartOnce(miliseconds); + const auto prior_expiration_secs = 5 * 60; + int milliseconds = std::max((seconds - prior_expiration_secs) * 1000, 60000); + m_next_token_refresh_at = std::time(nullptr) + milliseconds / 1000; + m_token_timer->StartOnce(milliseconds); } + void UserAccountCommunication::on_token_timer(wxTimerEvent& evt) { + BOOST_LOG_TRIVIAL(info) << "UserAccountCommunication: Token refresh timer fired"; enqueue_refresh(); } void UserAccountCommunication::on_polling_timer(wxTimerEvent& evt) diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index f4ec0dbf99..48d9a62e39 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace Slic3r { namespace GUI { @@ -97,6 +97,7 @@ private: wxTimer* m_token_timer; wxEvtHandler* m_timer_evt_handler; + std::time_t m_next_token_refresh_at; void wakeup_session_thread(); void init_session_thread(); diff --git a/src/slic3r/GUI/UserAccountSession.cpp b/src/slic3r/GUI/UserAccountSession.cpp index db81c2984e..860e90cc5d 100644 --- a/src/slic3r/GUI/UserAccountSession.cpp +++ b/src/slic3r/GUI/UserAccountSession.cpp @@ -123,6 +123,7 @@ void UserAccountSession::init_with_code(const std::string& code, const std::stri void UserAccountSession::token_success_callback(const std::string& body) { + BOOST_LOG_TRIVIAL(debug) << "Access token refreshed"; // Data we need std::string access_token, refresh_token, shared_session_key; int expires_in = 300; @@ -176,6 +177,7 @@ void UserAccountSession::token_success_callback(const std::string& body) void UserAccountSession::code_exchange_fail_callback(const std::string& body) { + BOOST_LOG_TRIVIAL(debug) << "Access token refresh failed, body: " << body; clear(); cancel_queue(); // Unlike refresh_fail_callback, no event was triggered so far, do it. (USER_ACCOUNT_ACTION_CODE_FOR_TOKEN does not send events) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index eac2873152..0411a06b84 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -636,6 +636,30 @@ wxString ConnectWebViewPanel::get_login_script(bool refresh) window.__access_token_version = 0; )", #else +// R"( +// console.log('Preparing login'); +// function errorHandler(err) { +// const msg = { +// action: 'ERROR', +// error: JSON.stringify(err), +// critical: false +// }; +// console.error('Login error occurred', msg); +// window._prusaSlicer.postMessage(msg); +// }; +// window.fetch('/slicer/login', {method: 'POST', headers: {Authorization: 'Bearer %s'}}) +// .then(function (resp) { +// console.log('Login resp', resp); +// resp.text() +// .then(function (json) { console.log('Login resp body', json); return json; }) +// .then(function (body) { +// if (resp.status >= 400) errorHandler({status: resp.status, body}); +// }); +// }) +// .catch(function (err){ +// errorHandler({message: err.message, stack: err.stack}); +// }); +// )", R"( console.log('Preparing login'); function errorHandler(err) { @@ -647,18 +671,46 @@ wxString ConnectWebViewPanel::get_login_script(bool refresh) console.error('Login error occurred', msg); window._prusaSlicer.postMessage(msg); }; - window.fetch('/slicer/login', {method: 'POST', headers: {Authorization: 'Bearer %s'}}) - .then(function (resp) { - console.log('Login resp', resp); - resp.text() - .then(function (json) { console.log('Login resp body', json); return json; }) - .then(function (body) { - if (resp.status >= 400) errorHandler({status: resp.status, body}); - }); - }) - .catch(function (err){ - errorHandler({message: err.message, stack: err.stack}); + + function delay(ms) { + return new Promise((resolve, reject) => { + setTimeout(resolve, ms); }); + } + + (async () => { + let retry = false; + let backoff = 1000; + const maxBackoff = 64000; + do { + + let error = false; + + try { + console.log('Slicer Login request'); + let resp = await fetch('/slicer/login', {method: 'POST', headers: {Authorization: 'Bearer %s'}}); + let body = await resp.text(); + console.log('Slicer Login resp', resp.status, body); + if (resp.status >= 500) { + retry = true; + } else { + retry = false; + if (resp.status >= 400) + errorHandler({status: resp.status, body}); + } + } catch (e) { + console.error('Slicer Login failed', e.toString()); + retry = true; + } + + if (retry) { + await delay(backoff + 1000 * Math.random()); + if (backoff < maxBackoff) { + backoff *= 2; + } + } + } while (retry); + })(); )", #endif access_token @@ -691,6 +743,7 @@ void ConnectWebViewPanel::on_script_message(wxWebViewEvent& evt) } void ConnectWebViewPanel::on_navigation_request(wxWebViewEvent &evt) { + BOOST_LOG_TRIVIAL(debug) << "Navigation requested to: " << into_u8(evt.GetURL()); if (evt.GetURL() == m_default_url) { m_reached_default_url = true; return;