From e3a4e3dc10a96b0822674cea262f41774e55a660 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 9 Oct 2009 19:42:59 -0400
Subject: [PATCH] DEV-40930: Added ["change"] key to login-module status
 events. Changed existing event calls to use state as "offline" or "online",
 with "change" indicating the reason for this status event. Changed
 disconnect() to send state "offline", change "disconnect" -- instead of
 replaying last auth failure. Changed unit tests accordingly. Changed
 LLLoginInstance::handleLoginEvent() to use LLEventDispatcher to route calls
 to handleLoginFailure() et al. Added LLEventDispatcher::get() to allow
 retrieving Callable by name and testing for empty().

---
 indra/llcommon/lleventdispatcher.cpp          | 10 ++++++
 indra/llcommon/lleventdispatcher.h            |  4 +++
 indra/newview/lllogininstance.cpp             | 34 +++++++++++--------
 indra/newview/lllogininstance.h               |  7 ++--
 indra/newview/tests/lllogininstance_test.cpp  |  7 ++++
 indra/viewer_components/login/lllogin.cpp     | 29 ++++++++++------
 .../login/tests/lllogin_test.cpp              | 16 ++++-----
 7 files changed, 71 insertions(+), 36 deletions(-)

diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp
index 2dbd59b1560..6b1413d0549 100644
--- a/indra/llcommon/lleventdispatcher.cpp
+++ b/indra/llcommon/lleventdispatcher.cpp
@@ -109,6 +109,16 @@ bool LLEventDispatcher::attemptCall(const std::string& name, const LLSD& event)
     return true;                    // tell caller we were able to call
 }
 
+LLEventDispatcher::Callable LLEventDispatcher::get(const std::string& name) const
+{
+    DispatchMap::const_iterator found = mDispatch.find(name);
+    if (found == mDispatch.end())
+    {
+        return Callable();
+    }
+    return found->second.first;
+}
+
 LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key):
     LLEventDispatcher(pumpname, key),
     mPump(pumpname, true),          // allow tweaking for uniqueness
diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h
index ef83ebabc1f..671f2a4d1cf 100644
--- a/indra/llcommon/lleventdispatcher.h
+++ b/indra/llcommon/lleventdispatcher.h
@@ -80,6 +80,10 @@ class LL_COMMON_API LLEventDispatcher
     /// @a required prototype specified at add() time, die with LL_ERRS.
     void operator()(const LLSD& event) const;
 
+    /// Fetch the Callable for the specified name. If no such name was
+    /// registered, return an empty() Callable.
+    Callable get(const std::string& name) const;
+
 private:
     template <class CLASS, typename METHOD>
     void addMethod(const std::string& name, const METHOD& method, const LLSD& required)
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 8bf769a1321..e5f347ddc40 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -68,10 +68,14 @@ LLLoginInstance::LLLoginInstance() :
 	mUserInteraction(true),
 	mSkipOptionalUpdate(false),
 	mAttemptComplete(false),
-	mTransferRate(0.0f)
+	mTransferRate(0.0f),
+	mDispatcher("LLLoginInstance", "change")
 {
 	mLoginModule->getEventPump().listen("lllogininstance", 
 		boost::bind(&LLLoginInstance::handleLoginEvent, this, _1));
+	mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
+	mDispatcher.add("connect",    boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
+	mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
 }
 
 LLLoginInstance::~LLLoginInstance()
@@ -185,9 +189,9 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)
 	std::cout << "LoginListener called!: \n";
 	std::cout << event << "\n";
 
-	if(!(event.has("state") && event.has("progress")))
+	if(!(event.has("state") && event.has("change") && event.has("progress")))
 	{
-		llerrs << "Unknown message from LLLogin!" << llendl;
+		llerrs << "Unknown message from LLLogin: " << event << llendl;
 	}
 
 	mLoginState = event["state"].asString();
@@ -198,19 +202,17 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)
 		mTransferRate = event["transfer_rate"].asReal();
 	}
 
-	if(mLoginState == "offline")
+	// Call the method registered in constructor, if any, for more specific
+	// handling
+	LLEventDispatcher::Callable method(mDispatcher.get(event["change"]));
+	if (! method.empty())
 	{
-		handleLoginFailure(event);
+		method(event);
 	}
-	else if(mLoginState == "online")
-	{
-		handleLoginSuccess(event);
-	}
-
 	return false;
 }
 
-bool LLLoginInstance::handleLoginFailure(const LLSD& event)
+void LLLoginInstance::handleLoginFailure(const LLSD& event)
 {
 	// Login has failed. 
 	// Figure out why and respond...
@@ -264,11 +266,9 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event)
 	{
 		attemptComplete();
 	}
-
-	return false;
 }
 
-bool LLLoginInstance::handleLoginSuccess(const LLSD& event)
+void LLLoginInstance::handleLoginSuccess(const LLSD& event)
 {
 	if(gSavedSettings.getBOOL("ForceMandatoryUpdate"))
 	{
@@ -286,7 +286,11 @@ bool LLLoginInstance::handleLoginSuccess(const LLSD& event)
 	{
 		attemptComplete();
 	}
-	return false;
+}
+
+void LLLoginInstance::handleDisconnect(const LLSD& event)
+{
+    // placeholder
 }
 
 bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 6a2ccf919e3..19d7449bc15 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -33,6 +33,7 @@
 #ifndef LL_LLLOGININSTANCE_H
 #define LL_LLLOGININSTANCE_H
 
+#include "lleventdispatcher.h"
 #include <boost/scoped_ptr.hpp>
 #include <boost/function.hpp>
 class LLLogin;
@@ -85,8 +86,9 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	bool updateDialogCallback(const LLSD& notification, const LLSD& response);
 
 	bool handleLoginEvent(const LLSD& event);
-	bool handleLoginFailure(const LLSD& event);
-	bool handleLoginSuccess(const LLSD& event);
+	void handleLoginFailure(const LLSD& event);
+	void handleLoginSuccess(const LLSD& event);
+	void handleDisconnect(const LLSD& event);
 
 	bool handleTOSResponse(bool v, const std::string& key);
 
@@ -106,6 +108,7 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	int mLastExecEvent;
 	UpdaterLauncherCallback mUpdaterLauncher;
 	boost::scoped_ptr<LLEventStream> mUpdateAppResponse;
+	LLEventDispatcher mDispatcher;
 };
 
 #endif
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index 75db76df27e..009be35f641 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -225,6 +225,7 @@ namespace tut
 		// Dummy success response.
 		LLSD response;
 		response["state"] = "online";
+		response["change"] = "connect";
 		response["progress"] = 1.0;
 		response["transfer_rate"] = 7;
 		response["data"] = "test_data";
@@ -240,6 +241,7 @@ namespace tut
 
 		response.clear();
 		response["state"] = "offline";
+		response["change"] = "disconnect";
 		response["progress"] = 0.0;
 		response["transfer_rate"] = 0;
 		response["data"] = "test_data";
@@ -267,6 +269,7 @@ namespace tut
 		// TOS failure response.
 		LLSD response;
 		response["state"] = "offline";
+		response["change"] = "fail.login";
 		response["progress"] = 0.0;
 		response["transfer_rate"] = 7;
 		response["data"]["reason"] = "tos";
@@ -326,6 +329,7 @@ namespace tut
 		// Update needed failure response.
 		LLSD response;
 		response["state"] = "offline";
+		response["change"] = "fail.login";
 		response["progress"] = 0.0;
 		response["transfer_rate"] = 7;
 		response["data"]["reason"] = "update";
@@ -351,6 +355,7 @@ namespace tut
 		// Update needed failure response.
 		LLSD response;
 		response["state"] = "offline";
+		response["change"] = "fail.login";
 		response["progress"] = 0.0;
 		response["transfer_rate"] = 7;
 		response["data"]["reason"] = "update";
@@ -376,6 +381,7 @@ namespace tut
 		// Update needed failure response.
 		LLSD response;
 		response["state"] = "offline";
+		response["change"] = "fail.login";
 		response["progress"] = 0.0;
 		response["transfer_rate"] = 7;
 		response["data"]["reason"] = "optional";
@@ -401,6 +407,7 @@ namespace tut
 		// Update needed failure response.
 		LLSD response;
 		response["state"] = "offline";
+		response["change"] = "fail.login";
 		response["progress"] = 0.0;
 		response["transfer_rate"] = 7;
 		response["data"]["reason"] = "optional";
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index c0d35f31d3d..7a30315b9a8 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -70,10 +70,12 @@ class LLLogin::Impl
 	LLEventPump& getEventPump() { return mPump; }
 
 private:
-	void sendProgressEvent(const std::string& desc, const LLSD& data = LLSD::emptyMap())
+	void sendProgressEvent(const std::string& state, const std::string& change,
+						   const LLSD& data = LLSD())
 	{
 		LLSD status_data;
-		status_data["state"] = desc;
+		status_data["state"] = state;
+		status_data["change"] = change;
 		status_data["progress"] = 0.0f;
 
 		if(mAuthResponse.has("transfer_rate"))
@@ -81,7 +83,7 @@ class LLLogin::Impl
 			status_data["transfer_rate"] = mAuthResponse["transfer_rate"];
 		}
 
-		if(data.size() != 0)
+		if(data.isDefined())
 		{
 			status_data["data"] = data;
 		}
@@ -133,7 +135,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
     LLSD rewrittenURIs;
     {
         LLEventTimeout filter(replyPump);
-        sendProgressEvent("srvrequest");
+        sendProgressEvent("offline", "srvrequest");
 
         // Request SRV record.
         LL_INFOS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL;
@@ -172,7 +174,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
             LLSD progress_data;
             progress_data["attempt"] = attempts;
             progress_data["request"] = request;
-            sendProgressEvent("authenticating", progress_data);
+            sendProgressEvent("offline", "authenticating", progress_data);
 
             // We expect zero or more "Downloading" status events, followed by
             // exactly one event with some other status. Use postAndWait() the
@@ -187,7 +189,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
                                      waitForEventOn(self, replyPump)))
             {
                 // Still Downloading -- send progress update.
-                sendProgressEvent("downloading");
+                sendProgressEvent("offline", "downloading");
             }
             status = mAuthResponse["status"].asString();
 
@@ -215,9 +217,14 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
             // StatusComplete does not imply auth success. Check the
             // actual outcome of the request. We've already handled the
             // "indeterminate" case in the loop above.
-            sendProgressEvent((mAuthResponse["responses"]["login"].asString() == "true")?
-                              "online" : "offline",
-                              mAuthResponse["responses"]);
+            if (mAuthResponse["responses"]["login"].asString() == "true")
+            {
+                sendProgressEvent("online", "connect", mAuthResponse["responses"]);
+            }
+            else
+            {
+                sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+            }
             return;             // Done!
         }
         // If we don't recognize status at all, trouble
@@ -236,12 +243,12 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
     // Here we got through all the rewrittenURIs without succeeding. Tell
     // caller this didn't work out so well. Of course, the only failure data
     // we can reasonably show are from the last of the rewrittenURIs.
-    sendProgressEvent("offline", mAuthResponse["responses"]);
+    sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
 }
 
 void LLLogin::Impl::disconnect()
 {
-    sendProgressEvent("offline", mAuthResponse["responses"]);
+    sendProgressEvent("offline", "disconnect");
 }
 
 //*********************
diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp
index 51f00c83445..a8ae2883d54 100644
--- a/indra/viewer_components/login/tests/lllogin_test.cpp
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp
@@ -265,12 +265,12 @@ namespace tut
 
 		login.connect("login.bar.com", credentials);
 
-		ensure_equals("SRV state", listener.lastEvent()["state"].asString(), "srvrequest"); 
+		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
 
 		dummyLLAres.sendReply();
 
 		// Test Authenticating State prior to first response.
-		ensure_equals("Auth state 1", listener.lastEvent()["state"].asString(), "authenticating"); 
+		ensure_equals("Auth state 1", listener.lastEvent()["change"].asString(), "authenticating"); 
 		ensure_equals("Attempt 1", listener.lastEvent()["data"]["attempt"].asInteger(), 1); 
 		ensure_equals("URI 1", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.foo.com"); 
 
@@ -285,7 +285,7 @@ namespace tut
 		dummyXMLRPC.setResponse(data);
 		dummyXMLRPC.sendReply();
 
-		ensure_equals("Fail back to authenticate 1", listener.lastEvent()["state"].asString(), "authenticating"); 
+		ensure_equals("Fail back to authenticate 1", listener.lastEvent()["change"].asString(), "authenticating"); 
 		ensure_equals("Attempt 2", listener.lastEvent()["data"]["attempt"].asInteger(), 2); 
 		ensure_equals("URI 2", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com"); 
 
@@ -301,7 +301,7 @@ namespace tut
 		dummyXMLRPC.setResponse(data);
 		dummyXMLRPC.sendReply();
 
-		ensure_equals("Fail back to authenticate 2", listener.lastEvent()["state"].asString(), "authenticating"); 
+		ensure_equals("Fail back to authenticate 2", listener.lastEvent()["change"].asString(), "authenticating"); 
 		ensure_equals("Attempt 3", listener.lastEvent()["data"]["attempt"].asInteger(), 3); 
 		ensure_equals("URI 3", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.indeterminate.com"); 
 
@@ -350,11 +350,11 @@ namespace tut
 
 		login.connect("login.bar.com", credentials);
 
-		ensure_equals("SRV state", listener.lastEvent()["state"].asString(), "srvrequest"); 
+		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
 
 		dummyLLAres.sendReply();
 
-		ensure_equals("Auth state", listener.lastEvent()["state"].asString(), "authenticating"); 
+		ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); 
 
 		// Send the failed auth request reponse
 		LLSD data;
@@ -397,11 +397,11 @@ namespace tut
 
 		login.connect("login.bar.com", credentials);
 
-		ensure_equals("SRV state", listener.lastEvent()["state"].asString(), "srvrequest"); 
+		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
 
 		dummyLLAres.sendReply();
 
-		ensure_equals("Auth state", listener.lastEvent()["state"].asString(), "authenticating"); 
+		ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); 
 
 		// Send the failed auth request reponse
 		LLSD data;
-- 
GitLab