diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2018-10-04 16:35:38 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2018-10-04 16:35:38 -0400 |
commit | 05068186c349294caf4fef3c970f9d75a9f30460 (patch) | |
tree | 58374bd2e5b519ad9b7943c9fab2a4aded52240a /indra/newview | |
parent | b1955d4247a4d28a3a4c259036390ff632e80008 (diff) |
DRTVWR-474: Make login coroutine sync with updater process on failure.
Specifically, introduce an LLEventMailDrop("LoginSync"). When the updater
detects that an update is required, it will post to that rendezvous point.
When login.cgi responds with login failure, make the login coroutine wait (a
few seconds) for that ping from the updater.
If we receive that ping and if it contains a "reply" key, make the fail.login
listener respond to the updater with an indication of whether to proceed with
update.
If both login.cgi and the updater concur that an update is required, produce a
new confirmation message for the user and then (once user responds) tell the
updater to proceed. Otherwise, produce the usual login-failure message and
tell the updater never mind.
Introduce LLCoro::OverrideConsuming to provide temporary save/restore of the
set_consuming() / get_consuming() flag. It's a good idea to set the consuming
flag when retrieving data from an LLEventMailDrop.
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/lllogininstance.cpp | 63 | ||||
-rw-r--r-- | indra/newview/lllogininstance.h | 6 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 13 |
3 files changed, 71 insertions, 11 deletions
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index bc93fa2c20..126c6be388 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -253,14 +253,12 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event) mLoginState = event["state"].asString(); mResponseData = event["data"]; - + if(event.has("transfer_rate")) { mTransferRate = event["transfer_rate"].asReal(); } - - // Call the method registered in constructor, if any, for more specific // handling mDispatcher.try_call(event); @@ -276,6 +274,14 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) // Login has failed. // Figure out why and respond... LLSD response = event["data"]; + LLSD updater = response["updater"]; + + // Always provide a response to the updater, if in fact the updater + // contacted us, if in fact the ping contains a 'reply' key. Most code + // paths tell it not to proceed with updating. + ResponsePtr resp(std::make_shared<LLEventAPI::Response> + (LLSDMap("update", false), updater)); + std::string reason_response = response["reason"].asString(); std::string message_response = response["message"].asString(); LL_DEBUGS("LLLogin") << "reason " << reason_response @@ -328,17 +334,44 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) } else if(reason_response == "update") { - // This shouldn't happen - the viewer manager should have forced an update; - // possibly the user ran the viewer directly and bypassed the update check + // This can happen if the user clicked Login quickly, before we heard + // back from the Viewer Version Manager, but login failed because + // login.cgi is insisting on a required update. We were called with an + // event that bundles both the login.cgi 'response' and the + // synchronization event from the 'updater'. std::string required_version = response["message_args"]["VERSION"]; LL_WARNS("LLLogin") << "Login failed because an update to version " << required_version << " is required." << LL_ENDL; if (gViewerWindow) gViewerWindow->setShowProgress(FALSE); - LLSD data(LLSD::emptyMap()); - data["VERSION"] = required_version; - LLNotificationsUtil::add("RequiredUpdate", data, LLSD::emptyMap(), boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2)); + LLSD args(LLSDMap("VERSION", required_version)); + if (updater.isUndefined()) + { + // If the updater failed to shake hands, better advise the user to + // download the update him/herself. + LLNotificationsUtil::add( + "RequiredUpdate", + args, + updater, + boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2)); + } + else + { + // If we've heard from the updater that an update is required, + // then display the prompt that assures the user we'll take care + // of it. This is the one case in which we bind 'resp': + // instead of destroying our Response object (and thus sending a + // negative reply to the updater) as soon as we exit this + // function, bind our shared_ptr so it gets passed into + // syncWithUpdater. That ensures that the response is delayed + // until the user has responded to the notification. + LLNotificationsUtil::add( + "PauseForUpdate", + args, + updater, + boost::bind(&LLLoginInstance::syncWithUpdater, this, resp, _1, _2)); + } } else if( reason_response == "key" || reason_response == "presence" @@ -361,6 +394,19 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) } } +void LLLoginInstance::syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response) +{ + LL_INFOS("LLLogin") << "LLLoginInstance::syncWithUpdater" << LL_ENDL; + // 'resp' points to an instance of LLEventAPI::Response that will be + // destroyed as soon as we return and the notification response functor is + // unregistered. Modify it so that it tells the updater to go ahead and + // perform the update. Naturally, if we allowed the user a choice as to + // whether to proceed or not, this assignment would reflect the user's + // selection. + (*resp)["update"] = true; + attemptComplete(); +} + void LLLoginInstance::handleLoginDisallowed(const LLSD& notification, const LLSD& response) { attemptComplete(); @@ -420,7 +466,6 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) return true; } - std::string construct_start_string() { std::string start; diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 651ad10afb..b759b43474 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -28,8 +28,10 @@ #define LL_LLLOGININSTANCE_H #include "lleventdispatcher.h" +#include "lleventapi.h" #include <boost/scoped_ptr.hpp> #include <boost/function.hpp> +#include <memory> // std::shared_ptr #include "llsecapi.h" class LLLogin; class LLEventStream; @@ -68,6 +70,7 @@ public: LLNotificationsInterface& getNotificationsInterface() const { return *mNotifications; } private: + typedef std::shared_ptr<LLEventAPI::Response> ResponsePtr; void constructAuthParams(LLPointer<LLCredential> user_credentials); void updateApp(bool mandatory, const std::string& message); bool updateDialogCallback(const LLSD& notification, const LLSD& response); @@ -77,7 +80,8 @@ private: void handleLoginSuccess(const LLSD& event); void handleDisconnect(const LLSD& event); void handleIndeterminate(const LLSD& event); - void handleLoginDisallowed(const LLSD& notification, const LLSD& response); + void handleLoginDisallowed(const LLSD& notification, const LLSD& response); + void syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response); bool handleTOSResponse(bool v, const std::string& key); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 9eaa5330c3..5f9b8adc89 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3841,7 +3841,6 @@ Finished download of raw terrain file to: name="RequiredUpdate" type="alertmodal"> Version [VERSION] is required for login. -This should have been updated for you but apparently was not. Please download from https://secondlife.com/support/downloads/ <tag>confirm</tag> <usetemplate @@ -3851,6 +3850,18 @@ Please download from https://secondlife.com/support/downloads/ <notification icon="alertmodal.tga" + name="PauseForUpdate" + type="alertmodal"> +Version [VERSION] is required for login. +Click OK to download and install. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="LoginFailedUnknown" type="alertmodal"> Sorry, login failed for an unrecognized reason. |