/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. #include "llviewerprecompiledheaders.h"
  27. #include "llviewerdisplayname.h"
  28. // viewer includes
  29. #include "llagent.h"
  30. #include "llviewerregion.h"
  31. #include "llvoavatar.h"
  32. // library includes
  33. #include "llavatarnamecache.h"
  34. #include "llhttpclient.h"
  35. #include "llhttpnode.h"
  36. #include "llnotificationsutil.h"
  37. #include "llui.h" // getLanguage()
  38. namespace LLViewerDisplayName
  39. {
  40. // Fired when viewer receives server response to display name change
  41. set_name_signal_t sSetDisplayNameSignal;
  42. // Fired when there is a change in the agent's name
  43. name_changed_signal_t sNameChangedSignal;
  44. void addNameChangedCallback(const name_changed_signal_t::slot_type& cb)
  45. {
  46. sNameChangedSignal.connect(cb);
  47. }
  48. }
  49. class LLSetDisplayNameResponder : public LLHTTPClient::Responder
  50. {
  51. public:
  52. // only care about errors
  53. /*virtual*/ void error(U32 status, const std::string& reason)
  54. {
  55. LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
  56. LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
  57. }
  58. };
  59. void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot)
  60. {
  61. // TODO: simple validation here
  62. LLViewerRegion* region = gAgent.getRegion();
  63. llassert(region);
  64. std::string cap_url = region->getCapability("SetDisplayName");
  65. if (cap_url.empty())
  66. {
  67. // this server does not support display names, report error
  68. slot(false, "unsupported", LLSD());
  69. return;
  70. }
  71. // People API can return localized error messages. Indicate our
  72. // language preference via header.
  73. LLSD headers;
  74. headers["Accept-Language"] = LLUI::getLanguage();
  75. // People API requires both the old and new value to change a variable.
  76. // Our display name will be in cache before the viewer's UI is available
  77. // to request a change, so we can use direct lookup without callback.
  78. LLAvatarName av_name;
  79. if (!LLAvatarNameCache::get( gAgent.getID(), &av_name))
  80. {
  81. slot(false, "name unavailable", LLSD());
  82. return;
  83. }
  84. // People API expects array of [ "old value", "new value" ]
  85. LLSD change_array = LLSD::emptyArray();
  86. change_array.append(av_name.mDisplayName);
  87. change_array.append(display_name);
  88. llinfos << "Set name POST to " << cap_url << llendl;
  89. // Record our caller for when the server sends back a reply
  90. sSetDisplayNameSignal.connect(slot);
  91. // POST the requested change. The sim will not send a response back to
  92. // this request directly, rather it will send a separate message after it
  93. // communicates with the back-end.
  94. LLSD body;
  95. body["display_name"] = change_array;
  96. LLHTTPClient::post(cap_url, body, new LLSetDisplayNameResponder, headers);
  97. }
  98. class LLSetDisplayNameReply : public LLHTTPNode
  99. {
  100. LOG_CLASS(LLSetDisplayNameReply);
  101. public:
  102. /*virtual*/ void post(
  103. LLHTTPNode::ResponsePtr response,
  104. const LLSD& context,
  105. const LLSD& input) const
  106. {
  107. LLSD body = input["body"];
  108. S32 status = body["status"].asInteger();
  109. bool success = (status == 200);
  110. std::string reason = body["reason"].asString();
  111. LLSD content = body["content"];
  112. llinfos << "status " << status << " reason " << reason << llendl;
  113. // If viewer's concept of display name is out-of-date, the set request
  114. // will fail with 409 Conflict. If that happens, fetch up-to-date
  115. // name information.
  116. if (status == 409)
  117. {
  118. LLUUID agent_id = gAgent.getID();
  119. // Flush stale data
  120. LLAvatarNameCache::erase( agent_id );
  121. // Queue request for new data
  122. LLAvatarName ignored;
  123. LLAvatarNameCache::get( agent_id, &ignored );
  124. // Kill name tag, as it is wrong
  125. LLVOAvatar::invalidateNameTag( agent_id );
  126. }
  127. // inform caller of result
  128. LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content);
  129. LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
  130. }
  131. };
  132. class LLDisplayNameUpdate : public LLHTTPNode
  133. {
  134. /*virtual*/ void post(
  135. LLHTTPNode::ResponsePtr response,
  136. const LLSD& context,
  137. const LLSD& input) const
  138. {
  139. LLSD body = input["body"];
  140. LLUUID agent_id = body["agent_id"];
  141. std::string old_display_name = body["old_display_name"];
  142. // By convention this record is called "agent" in the People API
  143. LLSD name_data = body["agent"];
  144. // Inject the new name data into cache
  145. LLAvatarName av_name;
  146. av_name.fromLLSD( name_data );
  147. llinfos << "name-update now " << LLDate::now()
  148. << " next_update " << LLDate(av_name.mNextUpdate)
  149. << llendl;
  150. // Name expiration time may be provided in headers, or we may use a
  151. // default value
  152. // *TODO: get actual headers out of ResponsePtr
  153. //LLSD headers = response->mHeaders;
  154. LLSD headers;
  155. av_name.mExpires =
  156. LLAvatarNameCache::nameExpirationFromHeaders(headers);
  157. LLAvatarNameCache::insert(agent_id, av_name);
  158. // force name tag to update
  159. LLVOAvatar::invalidateNameTag(agent_id);
  160. LLSD args;
  161. args["OLD_NAME"] = old_display_name;
  162. args["SLID"] = av_name.mUsername;
  163. args["NEW_NAME"] = av_name.mDisplayName;
  164. LLNotificationsUtil::add("DisplayNameUpdate", args);
  165. if (agent_id == gAgent.getID())
  166. {
  167. LLViewerDisplayName::sNameChangedSignal();
  168. }
  169. }
  170. };
  171. LLHTTPRegistration<LLSetDisplayNameReply>
  172. gHTTPRegistrationMessageSetDisplayNameReply(
  173. "/message/SetDisplayNameReply");
  174. LLHTTPRegistration<LLDisplayNameUpdate>
  175. gHTTPRegistrationMessageDisplayNameUpdate(
  176. "/message/DisplayNameUpdate");