/indra/newview/llnotificationstorage.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 221 lines · 139 code · 45 blank · 37 comment · 19 complexity · fe36554904878f1a6474d104f20f81d4 MD5 · raw file

  1. /**
  2. * @file llnotificationstorage.cpp
  3. * @brief LLPersistentNotificationStorage class implementation
  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" // must be first include
  27. #include "llnotificationstorage.h"
  28. #include "llxmlnode.h" // for linux compilers
  29. #include "llchannelmanager.h"
  30. #include "llscreenchannel.h"
  31. #include "llscriptfloater.h"
  32. #include "llsdserialize.h"
  33. #include "llviewermessage.h"
  34. //////////////////////////////////////////////////////////////////////////
  35. class LLResponderRegistry
  36. {
  37. public:
  38. static void registerResponders();
  39. static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params);
  40. private:
  41. template<typename RESPONDER_TYPE>
  42. static LLNotificationResponderInterface* create(const LLSD& params)
  43. {
  44. RESPONDER_TYPE* responder = new RESPONDER_TYPE();
  45. responder->fromLLSD(params);
  46. return responder;
  47. }
  48. typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t;
  49. static void add(const std::string& notification_name, const responder_constructor_t& ctr);
  50. private:
  51. typedef std::map<std::string, responder_constructor_t> build_map_t;
  52. static build_map_t sBuildMap;
  53. };
  54. //////////////////////////////////////////////////////////////////////////
  55. LLPersistentNotificationStorage::LLPersistentNotificationStorage()
  56. {
  57. mFileName = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" );
  58. }
  59. bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)
  60. {
  61. // we ignore "load" messages, but rewrite the persistence file on any other
  62. const std::string sigtype = payload["sigtype"].asString();
  63. if ("load" != sigtype)
  64. {
  65. saveNotifications();
  66. }
  67. return false;
  68. }
  69. void LLPersistentNotificationStorage::saveNotifications()
  70. {
  71. // TODO - think about save optimization.
  72. llofstream notify_file(mFileName.c_str());
  73. if (!notify_file.is_open())
  74. {
  75. llwarns << "Failed to open " << mFileName << llendl;
  76. return;
  77. }
  78. LLSD output;
  79. LLSD& data = output["data"];
  80. LLNotificationChannelPtr history_channel = LLNotifications::instance().getChannel("Persistent");
  81. LLNotificationSet::iterator it = history_channel->begin();
  82. for ( ; history_channel->end() != it; ++it)
  83. {
  84. LLNotificationPtr notification = *it;
  85. // After a notification was placed in Persist channel, it can become
  86. // responded, expired or canceled - in this case we are should not save it
  87. if(notification->isRespondedTo() || notification->isCancelled()
  88. || notification->isExpired())
  89. {
  90. continue;
  91. }
  92. data.append(notification->asLLSD());
  93. }
  94. LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
  95. formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);
  96. }
  97. void LLPersistentNotificationStorage::loadNotifications()
  98. {
  99. LLResponderRegistry::registerResponders();
  100. LLNotifications::instance().getChannel("Persistent")->
  101. connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
  102. llifstream notify_file(mFileName.c_str());
  103. if (!notify_file.is_open())
  104. {
  105. llwarns << "Failed to open " << mFileName << llendl;
  106. return;
  107. }
  108. LLSD input;
  109. LLPointer<LLSDParser> parser = new LLSDXMLParser();
  110. if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0)
  111. {
  112. llwarns << "Failed to parse open notifications" << llendl;
  113. return;
  114. }
  115. if (input.isUndefined())
  116. {
  117. return;
  118. }
  119. LLSD& data = input["data"];
  120. if (data.isUndefined())
  121. {
  122. return;
  123. }
  124. using namespace LLNotificationsUI;
  125. LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->
  126. findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
  127. LLNotifications& instance = LLNotifications::instance();
  128. for (LLSD::array_const_iterator notification_it = data.beginArray();
  129. notification_it != data.endArray();
  130. ++notification_it)
  131. {
  132. LLSD notification_params = *notification_it;
  133. LLNotificationPtr notification(new LLNotification(notification_params));
  134. LLNotificationResponderPtr responder(LLResponderRegistry::
  135. createResponder(notification_params["name"], notification_params["responder"]));
  136. notification->setResponseFunctor(responder);
  137. instance.add(notification);
  138. // hide script floaters so they don't confuse the user and don't overlap startup toast
  139. LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false);
  140. if(notification_channel)
  141. {
  142. // hide saved toasts so they don't confuse the user
  143. notification_channel->hideToast(notification->getID());
  144. }
  145. }
  146. }
  147. //////////////////////////////////////////////////////////////////////////
  148. //////////////////////////////////////////////////////////////////////////
  149. //////////////////////////////////////////////////////////////////////////
  150. LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap;
  151. void LLResponderRegistry::registerResponders()
  152. {
  153. sBuildMap.clear();
  154. add("ObjectGiveItem", &create<LLOfferInfo>);
  155. add("UserGiveItem", &create<LLOfferInfo>);
  156. }
  157. LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params)
  158. {
  159. build_map_t::const_iterator it = sBuildMap.find(notification_name);
  160. if(sBuildMap.end() == it)
  161. {
  162. return NULL;
  163. }
  164. responder_constructor_t ctr = it->second;
  165. return ctr(params);
  166. }
  167. void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr)
  168. {
  169. if(sBuildMap.find(notification_name) != sBuildMap.end())
  170. {
  171. llwarns << "Responder is already registered : " << notification_name << llendl;
  172. llassert(!"Responder already registered");
  173. }
  174. sBuildMap[notification_name] = ctr;
  175. }
  176. // EOF