PageRenderTime 222ms CodeModel.GetById 59ms app.highlight 58ms RepoModel.GetById 102ms app.codeStats 0ms

/indra/newview/llviewerdisplayname.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 208 lines | 120 code | 32 blank | 56 comment | 7 complexity | 7829639dba21f9887ffccd278180f66e MD5 | raw file
  1/** 
  2 * @file llviewerdisplayname.cpp
  3 * @brief Wrapper for display name functionality
  4 *
  5 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llviewerdisplayname.h"
 30
 31// viewer includes
 32#include "llagent.h"
 33#include "llviewerregion.h"
 34#include "llvoavatar.h"
 35
 36// library includes
 37#include "llavatarnamecache.h"
 38#include "llhttpclient.h"
 39#include "llhttpnode.h"
 40#include "llnotificationsutil.h"
 41#include "llui.h"					// getLanguage()
 42
 43namespace LLViewerDisplayName
 44{
 45	// Fired when viewer receives server response to display name change
 46	set_name_signal_t sSetDisplayNameSignal;
 47
 48	// Fired when there is a change in the agent's name
 49	name_changed_signal_t sNameChangedSignal;
 50
 51	void addNameChangedCallback(const name_changed_signal_t::slot_type& cb) 
 52	{ 
 53		sNameChangedSignal.connect(cb); 
 54	}
 55
 56}
 57
 58class LLSetDisplayNameResponder : public LLHTTPClient::Responder
 59{
 60public:
 61	// only care about errors
 62	/*virtual*/ void error(U32 status, const std::string& reason)
 63	{
 64		LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
 65		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
 66	}
 67};
 68
 69void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot)
 70{
 71	// TODO: simple validation here
 72
 73	LLViewerRegion* region = gAgent.getRegion();
 74	llassert(region);
 75	std::string cap_url = region->getCapability("SetDisplayName");
 76	if (cap_url.empty())
 77	{
 78		// this server does not support display names, report error
 79		slot(false, "unsupported", LLSD());
 80		return;
 81	}
 82
 83	// People API can return localized error messages.  Indicate our
 84	// language preference via header.
 85	LLSD headers;
 86	headers["Accept-Language"] = LLUI::getLanguage();
 87
 88	// People API requires both the old and new value to change a variable.
 89	// Our display name will be in cache before the viewer's UI is available
 90	// to request a change, so we can use direct lookup without callback.
 91	LLAvatarName av_name;
 92	if (!LLAvatarNameCache::get( gAgent.getID(), &av_name))
 93	{
 94		slot(false, "name unavailable", LLSD());
 95		return;
 96	}
 97
 98	// People API expects array of [ "old value", "new value" ]
 99	LLSD change_array = LLSD::emptyArray();
100	change_array.append(av_name.mDisplayName);
101	change_array.append(display_name);
102	
103	llinfos << "Set name POST to " << cap_url << llendl;
104
105	// Record our caller for when the server sends back a reply
106	sSetDisplayNameSignal.connect(slot);
107	
108	// POST the requested change.  The sim will not send a response back to
109	// this request directly, rather it will send a separate message after it
110	// communicates with the back-end.
111	LLSD body;
112	body["display_name"] = change_array;
113	LLHTTPClient::post(cap_url, body, new LLSetDisplayNameResponder, headers);
114}
115
116class LLSetDisplayNameReply : public LLHTTPNode
117{
118	LOG_CLASS(LLSetDisplayNameReply);
119public:
120	/*virtual*/ void post(
121		LLHTTPNode::ResponsePtr response,
122		const LLSD& context,
123		const LLSD& input) const
124	{
125		LLSD body = input["body"];
126
127		S32 status = body["status"].asInteger();
128		bool success = (status == 200);
129		std::string reason = body["reason"].asString();
130		LLSD content = body["content"];
131
132		llinfos << "status " << status << " reason " << reason << llendl;
133
134		// If viewer's concept of display name is out-of-date, the set request
135		// will fail with 409 Conflict.  If that happens, fetch up-to-date
136		// name information.
137		if (status == 409)
138		{
139			LLUUID agent_id = gAgent.getID();
140			// Flush stale data
141			LLAvatarNameCache::erase( agent_id );
142			// Queue request for new data
143			LLAvatarName ignored;
144			LLAvatarNameCache::get( agent_id, &ignored );
145			// Kill name tag, as it is wrong
146			LLVOAvatar::invalidateNameTag( agent_id );
147		}
148
149		// inform caller of result
150		LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content);
151		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
152	}
153};
154
155
156class LLDisplayNameUpdate : public LLHTTPNode
157{
158	/*virtual*/ void post(
159		LLHTTPNode::ResponsePtr response,
160		const LLSD& context,
161		const LLSD& input) const
162	{
163		LLSD body = input["body"];
164		LLUUID agent_id = body["agent_id"];
165		std::string old_display_name = body["old_display_name"];
166		// By convention this record is called "agent" in the People API
167		LLSD name_data = body["agent"];
168
169		// Inject the new name data into cache
170		LLAvatarName av_name;
171		av_name.fromLLSD( name_data );
172
173		llinfos << "name-update now " << LLDate::now()
174			<< " next_update " << LLDate(av_name.mNextUpdate)
175			<< llendl;
176
177		// Name expiration time may be provided in headers, or we may use a
178		// default value
179		// *TODO: get actual headers out of ResponsePtr
180		//LLSD headers = response->mHeaders;
181		LLSD headers;
182		av_name.mExpires = 
183			LLAvatarNameCache::nameExpirationFromHeaders(headers);
184
185		LLAvatarNameCache::insert(agent_id, av_name);
186
187		// force name tag to update
188		LLVOAvatar::invalidateNameTag(agent_id);
189
190		LLSD args;
191		args["OLD_NAME"] = old_display_name;
192		args["SLID"] = av_name.mUsername;
193		args["NEW_NAME"] = av_name.mDisplayName;
194		LLNotificationsUtil::add("DisplayNameUpdate", args);
195		if (agent_id == gAgent.getID())
196		{
197			LLViewerDisplayName::sNameChangedSignal();
198		}
199	}
200};
201
202LLHTTPRegistration<LLSetDisplayNameReply>
203    gHTTPRegistrationMessageSetDisplayNameReply(
204		"/message/SetDisplayNameReply");
205
206LLHTTPRegistration<LLDisplayNameUpdate>
207    gHTTPRegistrationMessageDisplayNameUpdate(
208		"/message/DisplayNameUpdate");