From fb3df4790e27345a1e45f4a4675e756c1e551f21 Mon Sep 17 00:00:00 2001
From: William Todd Stinson <stinson@lindenlab.com>
Date: Tue, 30 Oct 2012 15:59:42 -0700
Subject: CHUI-459: Creating a fetchAvatarName() method for the
 LLConversationItemParticipant class to allow the class to query for the
 avatar display name directly.  Also, added a field to store the avatar name
 cache callback connection so that we can disconnect properly on object
 destruction to avoid a crash with the callback attempting to access recently
 freed memory.

---
 indra/newview/llconversationmodel.cpp  | 32 ++++++++++++++++++++++++++++++--
 indra/newview/llconversationmodel.h    | 12 +++++++++---
 indra/newview/llimfloatercontainer.cpp | 11 +----------
 indra/newview/llparticipantlist.cpp    |  3 +--
 4 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 67a1aed675..33631a027b 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -369,7 +369,8 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display
 	LLConversationItem(display_name,uuid,root_view_model),
 	mIsMuted(false),
 	mIsModerator(false),
-	mDistToAgent(-1.0)
+	mDistToAgent(-1.0),
+	mAvatarNameCacheConnection()
 {
 	mConvType = CONV_PARTICIPANT;
 }
@@ -378,11 +379,38 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid,
 	LLConversationItem(uuid,root_view_model),
 	mIsMuted(false),
 	mIsModerator(false),
-	mDistToAgent(-1.0)
+	mDistToAgent(-1.0),
+	mAvatarNameCacheConnection()
 {
 	mConvType = CONV_PARTICIPANT;
 }
 
+LLConversationItemParticipant::~LLConversationItemParticipant()
+{
+	// Disconnect any previous avatar name cache connection to ensure
+	// that the callback method is not called after destruction
+	if (mAvatarNameCacheConnection.connected())
+	{
+		mAvatarNameCacheConnection.disconnect();
+	}
+}
+
+void LLConversationItemParticipant::fetchAvatarName()
+{
+	// Disconnect any previous avatar name cache connection
+	if (mAvatarNameCacheConnection.connected())
+	{
+		mAvatarNameCacheConnection.disconnect();
+	}
+
+	// Request the avatar name from the cache
+	llassert(getUUID().notNull());
+	if (getUUID().notNull())
+	{
+		mAvatarNameCacheConnection = LLAvatarNameCache::get(getUUID(), boost::bind(&LLConversationItemParticipant::onAvatarNameCache, this, _2));
+	}
+}
+
 void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags)
 {
     menuentry_vec_t items;
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 1d082852f5..481d46af58 100755
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -27,9 +27,11 @@
 #ifndef LL_LLCONVERSATIONMODEL_H
 #define LL_LLCONVERSATIONMODEL_H
 
+#include <boost/signals2.hpp>
+
+#include "llavatarname.h"
 #include "llfolderviewitem.h"
 #include "llfolderviewmodel.h"
-#include "llavatarname.h"
 #include "llviewerfoldertype.h"
 
 // Implementation of conversations list
@@ -177,7 +179,7 @@ class LLConversationItemParticipant : public LLConversationItem
 public:
 	LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model);
 	LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model);
-	virtual ~LLConversationItemParticipant() {}
+	virtual ~LLConversationItemParticipant();
 	
 	virtual const std::string& getDisplayName() const { return mDisplayName; }
 
@@ -189,17 +191,21 @@ public:
 	void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; }
 
     void buildContextMenu(LLMenuGL& menu, U32 flags);
-	void onAvatarNameCache(const LLAvatarName& av_name);
 
 	virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); }
 
+	void fetchAvatarName();
+
 	void dumpDebugData();
 
 private:
+	void onAvatarNameCache(const LLAvatarName& av_name);
+
 	bool mIsMuted;		// default is false
 	bool mIsModerator;	// default is false
 	std::string mDisplayName;
 	F64  mDistToAgent;  // Distance to the agent. A negative (meaningless) value means the distance has not been set.
+	boost::signals2::connection mAvatarNameCacheConnection;
 };
 
 // We don't want to ever filter conversations but we need to declare that class to create a conversation view model.
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index f46ecd905a..00ae0b8fd8 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -358,16 +358,7 @@ void LLIMFloaterContainer::processParticipantsStyleUpdate()
 		{
 			LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
 			// Get the avatar name for this participant id from the cache and update the model
-			LLUUID participant_id = participant_model->getUUID();
-			LLAvatarName av_name;
-			LLAvatarNameCache::get(participant_id,&av_name);
-			// Avoid updating the model though if the cache is still waiting for its first update
-			if (!av_name.mDisplayName.empty())
-			{
-				participant_model->onAvatarNameCache(av_name);
-			}
-			// Bind update to the next cache name signal
-			LLAvatarNameCache::get(participant_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant_model, _2));
+			participant_model->fetchAvatarName();
 			// Next participant
 			current_participant_model++;
 		}
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index b263143bd1..e199cb5776 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -676,8 +676,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
 		LLAvatarName avatar_name;
 		bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name);
 		participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel);
-		// Binds avatar's name update callback
-		LLAvatarNameCache::get(avatar_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant, _2));
+		participant->fetchAvatarName();
 		if (mAvatarList)
 		{
 			mAvatarList->getIDs().push_back(avatar_id);
-- 
cgit v1.2.3