PageRenderTime 30ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llnotificationhandlerutil.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 507 lines | 375 code | 69 blank | 63 comment | 112 complexity | c7a0920330ae7e45b7fa6ec397f177ef MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llnotificationofferhandler.cpp
  3. * @brief Provides set of utility methods for notifications processing.
  4. *
  5. * $LicenseInfo:firstyear=2000&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" // must be first include
  27. #include "llavatarnamecache.h"
  28. #include "llfloaterreg.h"
  29. #include "llnotifications.h"
  30. #include "llurlaction.h"
  31. #include "llagent.h"
  32. #include "llimfloater.h"
  33. #include "llimview.h"
  34. #include "llnearbychat.h"
  35. #include "llnotificationhandler.h"
  36. using namespace LLNotificationsUI;
  37. // static
  38. std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups;
  39. // static
  40. void LLSysHandler::init()
  41. {
  42. std::set<std::string> online_offline_group;
  43. online_offline_group.insert("FriendOnline");
  44. online_offline_group.insert("FriendOffline");
  45. sExclusiveNotificationGroups.push_back(online_offline_group);
  46. }
  47. LLSysHandler::LLSysHandler()
  48. {
  49. if(sExclusiveNotificationGroups.empty())
  50. {
  51. init();
  52. }
  53. }
  54. void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif)
  55. {
  56. LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel);
  57. if (channel == NULL)
  58. {
  59. return;
  60. }
  61. class ExclusiveMatcher: public LLScreenChannel::Matcher
  62. {
  63. public:
  64. ExclusiveMatcher(const std::set<std::string>& excl_group,
  65. const std::string& from_name) :
  66. mExclGroup(excl_group), mFromName(from_name)
  67. {
  68. }
  69. bool matches(const LLNotificationPtr notification) const
  70. {
  71. for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it
  72. != mExclGroup.end(); it++)
  73. {
  74. std::string from_name = LLHandlerUtil::getSubstitutionName(notification);
  75. if (notification->getName() == *it && from_name == mFromName)
  76. {
  77. return true;
  78. }
  79. }
  80. return false;
  81. }
  82. private:
  83. const std::set<std::string>& mExclGroup;
  84. const std::string& mFromName;
  85. };
  86. for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it
  87. != sExclusiveNotificationGroups.end(); it++)
  88. {
  89. std::set<std::string> group = *it;
  90. std::set<std::string>::iterator g_it = group.find(notif->getName());
  91. if (g_it != group.end())
  92. {
  93. channel->killMatchedToasts(ExclusiveMatcher(group,
  94. LLHandlerUtil::getSubstitutionName(notif)));
  95. }
  96. }
  97. }
  98. const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),
  99. REVOKED_MODIFY_RIGHTS("RevokedModifyRights"),
  100. OBJECT_GIVE_ITEM("ObjectGiveItem"),
  101. OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"),
  102. PAYMENT_RECEIVED("PaymentReceived"),
  103. PAYMENT_SENT("PaymentSent"),
  104. ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"),
  105. USER_GIVE_ITEM("UserGiveItem"),
  106. INVENTORY_ACCEPTED("InventoryAccepted"),
  107. INVENTORY_DECLINED("InventoryDeclined"),
  108. OFFER_FRIENDSHIP("OfferFriendship"),
  109. FRIENDSHIP_ACCEPTED("FriendshipAccepted"),
  110. FRIENDSHIP_OFFERED("FriendshipOffered"),
  111. FRIENDSHIP_ACCEPTED_BYME("FriendshipAcceptedByMe"),
  112. FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"),
  113. FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"),
  114. SERVER_OBJECT_MESSAGE("ServerObjectMessage"),
  115. TELEPORT_OFFERED("TeleportOffered"),
  116. TELEPORT_OFFER_SENT("TeleportOfferSent"),
  117. IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip");
  118. // static
  119. bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)
  120. {
  121. return GRANTED_MODIFY_RIGHTS == notification->getName()
  122. || REVOKED_MODIFY_RIGHTS == notification->getName()
  123. || PAYMENT_RECEIVED == notification->getName()
  124. || PAYMENT_SENT == notification->getName()
  125. || OFFER_FRIENDSHIP == notification->getName()
  126. || FRIENDSHIP_OFFERED == notification->getName()
  127. || FRIENDSHIP_ACCEPTED == notification->getName()
  128. || FRIENDSHIP_ACCEPTED_BYME == notification->getName()
  129. || FRIENDSHIP_DECLINED_BYME == notification->getName()
  130. || SERVER_OBJECT_MESSAGE == notification->getName()
  131. || INVENTORY_ACCEPTED == notification->getName()
  132. || INVENTORY_DECLINED == notification->getName()
  133. || USER_GIVE_ITEM == notification->getName()
  134. || TELEPORT_OFFERED == notification->getName()
  135. || TELEPORT_OFFER_SENT == notification->getName()
  136. || IM_SYSTEM_MESSAGE_TIP == notification->getName();
  137. }
  138. // static
  139. bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification)
  140. {
  141. return notification->getType() == "notifytip"
  142. && FRIEND_ONLINE != notification->getName()
  143. && FRIEND_OFFLINE != notification->getName()
  144. && INVENTORY_ACCEPTED != notification->getName()
  145. && INVENTORY_DECLINED != notification->getName()
  146. && IM_SYSTEM_MESSAGE_TIP != notification->getName();
  147. }
  148. // static
  149. bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification)
  150. {
  151. return OFFER_FRIENDSHIP == notification->getName()
  152. || USER_GIVE_ITEM == notification->getName()
  153. || TELEPORT_OFFERED == notification->getName();
  154. }
  155. // static
  156. bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification)
  157. {
  158. return OFFER_FRIENDSHIP == notification->getName()
  159. || USER_GIVE_ITEM == notification->getName()
  160. || TELEPORT_OFFERED == notification->getName();
  161. }
  162. // static
  163. bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification)
  164. {
  165. return OFFER_FRIENDSHIP == notification->getName()
  166. || USER_GIVE_ITEM == notification->getName()
  167. || TELEPORT_OFFERED == notification->getName();
  168. }
  169. // static
  170. bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification)
  171. {
  172. return canLogToIM(notification) && canSpawnIMSession(notification);
  173. }
  174. // static
  175. bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification)
  176. {
  177. if(INVENTORY_DECLINED == notification->getName()
  178. || INVENTORY_ACCEPTED == notification->getName())
  179. {
  180. // return false for inventory accepted/declined notifications if respective IM window is open (EXT-5909)
  181. return ! isIMFloaterOpened(notification);
  182. }
  183. if(FRIENDSHIP_ACCEPTED == notification->getName())
  184. {
  185. // don't show FRIENDSHIP_ACCEPTED if IM window is opened and focused - EXT-6441
  186. return ! isIMFloaterFocused(notification);
  187. }
  188. if(OFFER_FRIENDSHIP == notification->getName()
  189. || USER_GIVE_ITEM == notification->getName()
  190. || TELEPORT_OFFERED == notification->getName())
  191. {
  192. // When ANY offer arrives, show toast, unless IM window is already open - EXT-5904
  193. return ! isIMFloaterOpened(notification);
  194. }
  195. return true;
  196. }
  197. // static
  198. LLIMFloater* LLHandlerUtil::findIMFloater(const LLNotificationPtr& notification)
  199. {
  200. LLUUID from_id = notification->getPayload()["from_id"];
  201. LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id);
  202. return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
  203. }
  204. // static
  205. bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)
  206. {
  207. bool res = false;
  208. LLIMFloater* im_floater = findIMFloater(notification);
  209. if (im_floater != NULL)
  210. {
  211. res = im_floater->getVisible() == TRUE;
  212. }
  213. return res;
  214. }
  215. bool LLHandlerUtil::isIMFloaterFocused(const LLNotificationPtr& notification)
  216. {
  217. bool res = false;
  218. LLIMFloater* im_floater = findIMFloater(notification);
  219. if (im_floater != NULL)
  220. {
  221. res = im_floater->hasFocus() == TRUE;
  222. }
  223. return res;
  224. }
  225. // static
  226. void LLHandlerUtil::logToIM(const EInstantMessage& session_type,
  227. const std::string& session_name, const std::string& from_name,
  228. const std::string& message, const LLUUID& session_owner_id,
  229. const LLUUID& from_id)
  230. {
  231. std::string from = from_name;
  232. if (from_name.empty())
  233. {
  234. from = SYSTEM_FROM;
  235. }
  236. LLUUID session_id = LLIMMgr::computeSessionID(session_type,
  237. session_owner_id);
  238. LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
  239. session_id);
  240. if (session == NULL)
  241. {
  242. // replace interactive system message marker with correct from string value
  243. if (INTERACTIVE_SYSTEM_FROM == from_name)
  244. {
  245. from = SYSTEM_FROM;
  246. }
  247. // Build a new format username or firstname_lastname for legacy names
  248. // to use it for a history log filename.
  249. std::string user_name = LLCacheName::buildUsername(session_name);
  250. LLIMModel::instance().logToFile(user_name, from, from_id, message);
  251. }
  252. else
  253. {
  254. // store active session id
  255. const LLUUID & active_session_id =
  256. LLIMModel::instance().getActiveSessionID();
  257. // set searched session as active to avoid IM toast popup
  258. LLIMModel::instance().setActiveSessionID(session_id);
  259. S32 unread = session->mNumUnread;
  260. S32 participant_unread = session->mParticipantUnreadMessageCount;
  261. LLIMModel::instance().addMessageSilently(session_id, from, from_id,
  262. message);
  263. // we shouldn't increment counters when logging, so restore them
  264. session->mNumUnread = unread;
  265. session->mParticipantUnreadMessageCount = participant_unread;
  266. // update IM floater messages
  267. updateIMFLoaterMesages(session_id);
  268. // restore active session id
  269. if (active_session_id.isNull())
  270. {
  271. LLIMModel::instance().resetActiveSessionID();
  272. }
  273. else
  274. {
  275. LLIMModel::instance().setActiveSessionID(active_session_id);
  276. }
  277. }
  278. }
  279. // static
  280. void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)
  281. {
  282. logToIMP2P(notification, false);
  283. }
  284. void log_name_callback(const std::string& full_name, const std::string& from_name,
  285. const std::string& message, const LLUUID& from_id)
  286. {
  287. LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, full_name, from_name, message,
  288. from_id, LLUUID());
  289. }
  290. // static
  291. void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)
  292. {
  293. // don't create IM p2p session with objects, it's necessary condition to log
  294. if (notification->getName() != OBJECT_GIVE_ITEM)
  295. {
  296. LLUUID from_id = notification->getPayload()["from_id"];
  297. if (from_id.isNull())
  298. {
  299. llwarns << " from_id for notification " << notification->getName() << " is null " << llendl;
  300. return;
  301. }
  302. if(to_file_only)
  303. {
  304. gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID()));
  305. }
  306. else
  307. {
  308. gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id));
  309. }
  310. }
  311. }
  312. // static
  313. void LLHandlerUtil::logGroupNoticeToIMGroup(
  314. const LLNotificationPtr& notification)
  315. {
  316. const LLSD& payload = notification->getPayload();
  317. LLGroupData groupData;
  318. if (!gAgent.getGroupData(payload["group_id"].asUUID(), groupData))
  319. {
  320. llwarns
  321. << "Group notice for unknown group: "
  322. << payload["group_id"].asUUID() << llendl;
  323. return;
  324. }
  325. const std::string group_name = groupData.mName;
  326. const std::string sender_name = payload["sender_name"].asString();
  327. // we can't retrieve sender id from group notice system message, so try to lookup it from cache
  328. LLUUID sender_id;
  329. gCacheName->getUUID(sender_name, sender_id);
  330. logToIM(IM_SESSION_GROUP_START, group_name, sender_name, payload["message"],
  331. payload["group_id"], sender_id);
  332. }
  333. // static
  334. void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type)
  335. {
  336. LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
  337. if(nearby_chat)
  338. {
  339. LLChat chat_msg(notification->getMessage());
  340. chat_msg.mSourceType = type;
  341. chat_msg.mFromName = SYSTEM_FROM;
  342. chat_msg.mFromID = LLUUID::null;
  343. nearby_chat->addMessage(chat_msg);
  344. }
  345. }
  346. // static
  347. LLUUID LLHandlerUtil::spawnIMSession(const std::string& name, const LLUUID& from_id)
  348. {
  349. LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id);
  350. LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
  351. session_id);
  352. if (session == NULL)
  353. {
  354. session_id = LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, from_id);
  355. }
  356. return session_id;
  357. }
  358. // static
  359. std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notification)
  360. {
  361. std::string res = notification->getSubstitutions().has("NAME")
  362. ? notification->getSubstitutions()["NAME"]
  363. : notification->getSubstitutions()["[NAME]"];
  364. if (res.empty())
  365. {
  366. LLUUID from_id = notification->getPayload()["FROM_ID"];
  367. //*TODO all keys everywhere should be made of the same case, there is a mix of keys in lower and upper cases
  368. if (from_id.isNull())
  369. {
  370. from_id = notification->getPayload()["from_id"];
  371. }
  372. if(!gCacheName->getFullName(from_id, res))
  373. {
  374. res = "";
  375. }
  376. }
  377. return res;
  378. }
  379. // static
  380. void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification)
  381. {
  382. const std::string name = LLHandlerUtil::getSubstitutionName(notification);
  383. LLUUID from_id = notification->getPayload()["from_id"];
  384. LLUUID session_id = spawnIMSession(name, from_id);
  385. // add offer to session
  386. LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession(
  387. session_id);
  388. llassert_always(session != NULL);
  389. LLSD offer;
  390. offer["notification_id"] = notification->getID();
  391. offer["from"] = SYSTEM_FROM;
  392. offer["time"] = LLLogChat::timestamp(false);
  393. offer["index"] = (LLSD::Integer)session->mMsgs.size();
  394. session->mMsgs.push_front(offer);
  395. // update IM floater and counters
  396. LLSD arg;
  397. arg["session_id"] = session_id;
  398. arg["num_unread"] = ++(session->mNumUnread);
  399. arg["participant_unread"] = ++(session->mParticipantUnreadMessageCount);
  400. LLIMModel::getInstance()->mNewMsgSignal(arg);
  401. }
  402. // static
  403. void LLHandlerUtil::updateIMFLoaterMesages(const LLUUID& session_id)
  404. {
  405. LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
  406. if (im_floater != NULL && im_floater->getVisible())
  407. {
  408. im_floater->updateMessages();
  409. }
  410. }
  411. // static
  412. void LLHandlerUtil::updateVisibleIMFLoaterMesages(const LLNotificationPtr& notification)
  413. {
  414. const std::string name = LLHandlerUtil::getSubstitutionName(notification);
  415. LLUUID from_id = notification->getPayload()["from_id"];
  416. LLUUID session_id = spawnIMSession(name, from_id);
  417. updateIMFLoaterMesages(session_id);
  418. }
  419. // static
  420. void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification)
  421. {
  422. const std::string name = LLHandlerUtil::getSubstitutionName(notification);
  423. LLUUID from_id = notification->getPayload()["from_id"];
  424. LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id);
  425. LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession(
  426. session_id);
  427. if (session == NULL)
  428. {
  429. return;
  430. }
  431. LLSD arg;
  432. arg["session_id"] = session_id;
  433. session->mNumUnread--;
  434. arg["num_unread"] = session->mNumUnread;
  435. session->mParticipantUnreadMessageCount--;
  436. arg["participant_unread"] = session->mParticipantUnreadMessageCount;
  437. LLIMModel::getInstance()->mNewMsgSignal(arg);
  438. }