From 8369276a4967185985cb5957b22cda6897e2df29 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Fri, 21 Jun 2019 20:55:39 +0300 Subject: DRTVWR-493 LLViewerMedia to singleton --- indra/newview/llstartup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0d99b35aee..d3be7c64f8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3543,7 +3543,7 @@ bool process_login_success_response() if(!openid_url.empty()) { std::string openid_token = response["openid_token"]; - LLViewerMedia::openIDSetup(openid_url, openid_token); + LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token); } gMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS; -- cgit v1.3 From 30cc3ff01f39952b6138fad4095ea032d4b832a4 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Fri, 21 Jun 2019 21:31:40 +0300 Subject: DRTVWR-493 LLViewerParcelMedia to singleton --- indra/newview/llappviewer.cpp | 1 - indra/newview/llpanelnearbymedia.cpp | 28 +++---- indra/newview/llstartup.cpp | 3 - indra/newview/lltoolpie.cpp | 10 +-- indra/newview/llviewermedia.cpp | 13 +-- indra/newview/llviewerparcelmedia.cpp | 112 +++++++++++++------------- indra/newview/llviewerparcelmedia.h | 87 ++++++++++---------- indra/newview/llviewerparcelmediaautoplay.cpp | 4 +- indra/newview/llviewerparcelmgr.cpp | 2 +- 9 files changed, 131 insertions(+), 129 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index dd79ad5280..a574588b1a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2042,7 +2042,6 @@ bool LLAppViewer::cleanup() //Note: //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown() //because some new image might be generated during cleaning up media. --bao - SUBSYSTEM_CLEANUP(LLViewerParcelMedia); gTextureList.shutdown(); // shutdown again in case a callback added something LLUIImageList::getInstance()->cleanUp(); diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index a85e9e3882..2dca55514d 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -567,7 +567,7 @@ void LLPanelNearByMedia::refreshParcelItems() if (NULL != mParcelMediaItem) { std::string name, url, tooltip; - getNameAndUrlHelper(LLViewerParcelMedia::getParcelMedia(), name, url, ""); + getNameAndUrlHelper(LLViewerParcelMedia::getInstance()->getParcelMedia(), name, url, ""); if (name.empty() || name == url) { tooltip = url; @@ -576,13 +576,13 @@ void LLPanelNearByMedia::refreshParcelItems() { tooltip = name + " : " + url; } - LLViewerMediaImpl *impl = LLViewerParcelMedia::getParcelMedia(); + LLViewerMediaImpl *impl = LLViewerParcelMedia::getInstance()->getParcelMedia(); updateListItem(mParcelMediaItem, mParcelMediaName, tooltip, -2, // Proximity closer than anything else, before Parcel Audio impl == NULL || impl->isMediaDisabled(), - impl != NULL && !LLViewerParcelMedia::getURL().empty(), + impl != NULL && !LLViewerParcelMedia::getInstance()->getURL().empty(), impl != NULL && impl->isMediaTimeBased() && impl->isMediaPlaying(), MEDIA_CLASS_ALL, "parcel media"); @@ -790,14 +790,14 @@ void LLPanelNearByMedia::onClickEnableParcelMedia() { if ( ! LLViewerMedia::getInstance()->isParcelMediaPlaying() ) { - LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); } } void LLPanelNearByMedia::onClickDisableParcelMedia() { // This actually unloads the impl, as opposed to "stop"ping the media - LLViewerParcelMedia::stop(); + LLViewerParcelMedia::getInstance()->stop(); } void LLPanelNearByMedia::onCheckItem(LLUICtrl* ctrl, const LLUUID &row_id) @@ -855,22 +855,22 @@ void LLPanelNearByMedia::onZoomMedia(void* user_data) void LLPanelNearByMedia::onClickParcelMediaPlay() { - LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); } void LLPanelNearByMedia::onClickParcelMediaStop() { - if (LLViewerParcelMedia::getParcelMedia()) + if (LLViewerParcelMedia::getInstance()->getParcelMedia()) { // This stops the media playing, as opposed to unloading it like // LLViewerParcelMedia::stop() does - LLViewerParcelMedia::getParcelMedia()->stop(); + LLViewerParcelMedia::getInstance()->getParcelMedia()->stop(); } } void LLPanelNearByMedia::onClickParcelMediaPause() { - LLViewerParcelMedia::pause(); + LLViewerParcelMedia::getInstance()->pause(); } void LLPanelNearByMedia::onClickParcelAudioPlay() @@ -1008,7 +1008,7 @@ void LLPanelNearByMedia::updateControls() showDisabledControls(); } else { - LLViewerMediaImpl* impl = LLViewerParcelMedia::getParcelMedia(); + LLViewerMediaImpl* impl = LLViewerParcelMedia::getInstance()->getParcelMedia(); if (NULL == impl) { // Just means it hasn't started yet @@ -1119,7 +1119,7 @@ void LLPanelNearByMedia::onClickSelectedMediaPlay() if (selected_media_id != PARCEL_AUDIO_LIST_ITEM_UUID) { LLViewerMediaImpl *impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ? - ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + ((LLViewerMediaImpl*)LLViewerParcelMedia::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); if (NULL != impl) { if (impl->isMediaTimeBased() && impl->isMediaPaused()) @@ -1130,7 +1130,7 @@ void LLPanelNearByMedia::onClickSelectedMediaPlay() } else if (impl->isParcelMedia()) { - LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); } } } @@ -1165,7 +1165,7 @@ void LLPanelNearByMedia::onClickSelectedMediaMute() } else { LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ? - ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + ((LLViewerMediaImpl*)LLViewerParcelMedia::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); if (NULL != impl) { F32 volume = impl->getVolume(); @@ -1196,7 +1196,7 @@ void LLPanelNearByMedia::onCommitSelectedMediaVolume() } else { LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ? - ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + ((LLViewerMediaImpl*)LLViewerParcelMedia::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); if (NULL != impl) { impl->setVolume(mVolumeSlider->getValueF32()); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index d3be7c64f8..8be453ad6c 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2806,9 +2806,6 @@ void LLStartUp::multimediaInit() std::string msg = LLTrans::getString("LoginInitializingMultimedia"); set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str()); display_startup(); - - // LLViewerMedia::initClass(); - LLViewerParcelMedia::initClass(); } void LLStartUp::fontInit() diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 82111cb78a..63e84ccbbd 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1457,19 +1457,19 @@ static void handle_click_action_play() LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (!parcel) return; - LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); + LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getInstance()->getStatus(); switch(status) { case LLViewerMediaImpl::MEDIA_PLAYING: - LLViewerParcelMedia::pause(); + LLViewerParcelMedia::getInstance()->pause(); break; case LLViewerMediaImpl::MEDIA_PAUSED: - LLViewerParcelMedia::start(); + LLViewerParcelMedia::getInstance()->start(); break; default: - LLViewerParcelMedia::play(parcel); + LLViewerParcelMedia::getInstance()->play(parcel); break; } } @@ -1706,7 +1706,7 @@ static ECursorType cursor_from_parcel_media(U8 click_action) open_cursor = UI_CURSOR_TOOLMEDIAOPEN; - LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); + LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getInstance()->getStatus(); switch(status) { case LLViewerMediaImpl::MEDIA_PLAYING: diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 1e218eef12..857799889b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -952,7 +952,7 @@ void LLViewerMedia::setAllMediaEnabled(bool val) { if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia()) { - LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); } static LLCachedControl audio_streaming_music(gSavedSettings, "AudioStreamingMusic", true); @@ -974,7 +974,7 @@ void LLViewerMedia::setAllMediaEnabled(bool val) } else { // This actually unloads the impl, as opposed to "stop"ping the media - LLViewerParcelMedia::stop(); + LLViewerParcelMedia::getInstance()->stop(); if (gAudiop) { LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade(); @@ -1023,7 +1023,7 @@ void LLViewerMedia::setAllMediaPaused(bool val) { if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia()) { - LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); } static LLCachedControl audio_streaming_music(gSavedSettings, "AudioStreamingMusic", true); @@ -1045,7 +1045,7 @@ void LLViewerMedia::setAllMediaPaused(bool val) } else { // This actually unloads the impl, as opposed to "stop"ping the media - LLViewerParcelMedia::stop(); + LLViewerParcelMedia::getInstance()->stop(); if (gAudiop) { LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade(); @@ -1056,7 +1056,8 @@ void LLViewerMedia::setAllMediaPaused(bool val) ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMedia::isParcelMediaPlaying() { - return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia()); + viewer_media_t media = LLViewerParcelMedia::getInstance()->getParcelMedia(); + return (LLViewerMedia::hasParcelMedia() && media && media->hasMedia()); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1470,7 +1471,7 @@ bool LLViewerMedia::hasInWorldMedia() ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMedia::hasParcelMedia() { - return !LLViewerParcelMedia::getURL().empty(); + return !LLViewerParcelMedia::getInstance()->getURL().empty(); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index cbc276b7e2..30291d1a93 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -45,31 +45,23 @@ #include "llviewertexture.h" #include "llcorehttputil.h" -// Static Variables -S32 LLViewerParcelMedia::sMediaParcelLocalID = 0; -LLUUID LLViewerParcelMedia::sMediaRegionID; -viewer_media_t LLViewerParcelMedia::sMediaImpl; - - -// static -void LLViewerParcelMedia::initClass() +LLViewerParcelMedia::LLViewerParcelMedia(): +mMediaParcelLocalID(0) { LLMessageSystem* msg = gMessageSystem; - msg->setHandlerFunc("ParcelMediaCommandMessage", processParcelMediaCommandMessage ); - msg->setHandlerFunc("ParcelMediaUpdate", processParcelMediaUpdate ); + msg->setHandlerFunc("ParcelMediaCommandMessage", parcelMediaCommandMessageHandler ); + msg->setHandlerFunc("ParcelMediaUpdate", parcelMediaUpdateHandler ); LLViewerParcelMediaAutoPlay::initClass(); } -//static -void LLViewerParcelMedia::cleanupClass() +LLViewerParcelMedia::~LLViewerParcelMedia() { // This needs to be destroyed before global destructor time. - sMediaImpl = NULL; + mMediaImpl = NULL; } ////////////////////////////////////////////////////////////////////////////////////////// -// static void LLViewerParcelMedia::update(LLParcel* parcel) { if (/*LLViewerMedia::hasMedia()*/ true) @@ -79,7 +71,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) { if(!gAgent.getRegion()) { - sMediaRegionID = LLUUID() ; + mMediaRegionID = LLUUID() ; stop() ; LL_DEBUGS("Media") << "no agent region, bailing out." << LL_ENDL; return ; @@ -89,11 +81,11 @@ void LLViewerParcelMedia::update(LLParcel* parcel) S32 parcelid = parcel->getLocalID(); LLUUID regionid = gAgent.getRegion()->getRegionID(); - if (parcelid != sMediaParcelLocalID || regionid != sMediaRegionID) + if (parcelid != mMediaParcelLocalID || regionid != mMediaRegionID) { LL_DEBUGS("Media") << "New parcel, parcel id = " << parcelid << ", region id = " << regionid << LL_ENDL; - sMediaParcelLocalID = parcelid; - sMediaRegionID = regionid; + mMediaParcelLocalID = parcelid; + mMediaRegionID = regionid; } std::string mediaUrl = std::string ( parcel->getMediaURL () ); @@ -108,19 +100,19 @@ void LLViewerParcelMedia::update(LLParcel* parcel) LLStringUtil::trim(mediaUrl); // If no parcel media is playing, nothing left to do - if(sMediaImpl.isNull()) + if(mMediaImpl.isNull()) { return; } // Media is playing...has something changed? - else if (( sMediaImpl->getMediaURL() != mediaUrl ) - || ( sMediaImpl->getMediaTextureID() != parcel->getMediaID() ) - || ( sMediaImpl->getMimeType() != parcel->getMediaType() )) + else if (( mMediaImpl->getMediaURL() != mediaUrl ) + || ( mMediaImpl->getMediaTextureID() != parcel->getMediaID() ) + || ( mMediaImpl->getMimeType() != parcel->getMediaType() )) { // Only play if the media types are the same. - if(sMediaImpl->getMimeType() == parcel->getMediaType()) + if(mMediaImpl->getMimeType() == parcel->getMediaType()) { play(parcel); } @@ -176,30 +168,30 @@ void LLViewerParcelMedia::play(LLParcel* parcel) S32 media_width = parcel->getMediaWidth(); S32 media_height = parcel->getMediaHeight(); - if(sMediaImpl) + if(mMediaImpl) { // If the url and mime type are the same, call play again - if(sMediaImpl->getMediaURL() == media_url - && sMediaImpl->getMimeType() == mime_type - && sMediaImpl->getMediaTextureID() == placeholder_texture_id) + if(mMediaImpl->getMediaURL() == media_url + && mMediaImpl->getMimeType() == mime_type + && mMediaImpl->getMediaTextureID() == placeholder_texture_id) { LL_DEBUGS("Media") << "playing with existing url " << media_url << LL_ENDL; - sMediaImpl->play(); + mMediaImpl->play(); } // Else if the texture id's are the same, navigate and rediscover type // MBW -- This causes other state from the previous parcel (texture size, autoscale, and looping) to get re-used incorrectly. // It's also not really necessary -- just creating a new instance is fine. -// else if(sMediaImpl->getMediaTextureID() == placeholder_texture_id) +// else if(mMediaImpl->getMediaTextureID() == placeholder_texture_id) // { -// sMediaImpl->navigateTo(media_url, mime_type, true); +// mMediaImpl->navigateTo(media_url, mime_type, true); // } else { // Since the texture id is different, we need to generate a new impl // Delete the old one first so they don't fight over the texture. - sMediaImpl = NULL; + mMediaImpl = NULL; // A new impl will be created below. } @@ -208,19 +200,19 @@ void LLViewerParcelMedia::play(LLParcel* parcel) // Don't ever try to play if the media type is set to "none/none" if(stricmp(mime_type.c_str(), LLMIMETypes::getDefaultMimeType().c_str()) != 0) { - if(!sMediaImpl) + if(!mMediaImpl) { LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL; // There is no media impl, make a new one - sMediaImpl = LLViewerMedia::getInstance()->newMediaImpl( + mMediaImpl = LLViewerMedia::getInstance()->newMediaImpl( placeholder_texture_id, media_width, media_height, media_auto_scale, media_loop); - sMediaImpl->setIsParcelMedia(true); - sMediaImpl->navigateTo(media_url, mime_type, true); + mMediaImpl->setIsParcelMedia(true); + mMediaImpl->navigateTo(media_url, mime_type, true); } //LLFirstUse::useMedia(); @@ -232,7 +224,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel) // static void LLViewerParcelMedia::stop() { - if(sMediaImpl.isNull()) + if(mMediaImpl.isNull()) { return; } @@ -241,27 +233,27 @@ void LLViewerParcelMedia::stop() LLViewerMediaFocus::getInstance()->clearFocus(); // This will unload & kill the media instance. - sMediaImpl = NULL; + mMediaImpl = NULL; } // static void LLViewerParcelMedia::pause() { - if(sMediaImpl.isNull()) + if(mMediaImpl.isNull()) { return; } - sMediaImpl->pause(); + mMediaImpl->pause(); } // static void LLViewerParcelMedia::start() { - if(sMediaImpl.isNull()) + if(mMediaImpl.isNull()) { return; } - sMediaImpl->start(); + mMediaImpl->start(); //LLFirstUse::useMedia(); @@ -271,17 +263,17 @@ void LLViewerParcelMedia::start() // static void LLViewerParcelMedia::seek(F32 time) { - if(sMediaImpl.isNull()) + if(mMediaImpl.isNull()) { return; } - sMediaImpl->seek(time); + mMediaImpl->seek(time); } // static void LLViewerParcelMedia::focus(bool focus) { - sMediaImpl->focus(focus); + mMediaImpl->focus(focus); } // static @@ -289,9 +281,9 @@ LLPluginClassMediaOwner::EMediaStatus LLViewerParcelMedia::getStatus() { LLPluginClassMediaOwner::EMediaStatus result = LLPluginClassMediaOwner::MEDIA_NONE; - if(sMediaImpl.notNull() && sMediaImpl->hasMedia()) + if(mMediaImpl.notNull() && mMediaImpl->hasMedia()) { - result = sMediaImpl->getMediaPlugin()->getStatus(); + result = mMediaImpl->getMediaPlugin()->getStatus(); } return result; @@ -300,15 +292,15 @@ LLPluginClassMediaOwner::EMediaStatus LLViewerParcelMedia::getStatus() // static std::string LLViewerParcelMedia::getMimeType() { - return sMediaImpl.notNull() ? sMediaImpl->getMimeType() : LLMIMETypes::getDefaultMimeType(); + return mMediaImpl.notNull() ? mMediaImpl->getMimeType() : LLMIMETypes::getDefaultMimeType(); } //static std::string LLViewerParcelMedia::getURL() { std::string url; - if(sMediaImpl.notNull()) - url = sMediaImpl->getMediaURL(); + if(mMediaImpl.notNull()) + url = mMediaImpl->getMediaURL(); if(stricmp(LLViewerParcelMgr::getInstance()->getAgentParcel()->getMediaType().c_str(), LLMIMETypes::getDefaultMimeType().c_str()) != 0) { @@ -325,19 +317,24 @@ std::string LLViewerParcelMedia::getURL() //static std::string LLViewerParcelMedia::getName() { - if(sMediaImpl.notNull()) - return sMediaImpl->getName(); + if(mMediaImpl.notNull()) + return mMediaImpl->getName(); return ""; } viewer_media_t LLViewerParcelMedia::getParcelMedia() { - return sMediaImpl; + return mMediaImpl; } ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg, void ** ) +void LLViewerParcelMedia::parcelMediaCommandMessageHandler(LLMessageSystem *msg, void **) +{ + getInstance()->processParcelMediaCommandMessage(msg); +} + +void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg) { // extract the agent id // LLUUID agent_id; @@ -392,7 +389,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg if (flags & (1<getAgentParcel(); play(parcel); @@ -403,7 +400,12 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void ** ) +void LLViewerParcelMedia::parcelMediaUpdateHandler(LLMessageSystem *msg, void **) +{ + getInstance()->processParcelMediaUpdate(msg); +} + +void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg) { LLUUID media_id; std::string media_url; diff --git a/indra/newview/llviewerparcelmedia.h b/indra/newview/llviewerparcelmedia.h index 534f65b419..779a65bdf8 100644 --- a/indra/newview/llviewerparcelmedia.h +++ b/indra/newview/llviewerparcelmedia.h @@ -37,50 +37,53 @@ class LLViewerParcelMediaNavigationObserver; // This class understands land parcels, network traffic, LSL media // transport commands, and talks to the LLViewerMedia class to actually // do playback. It allows us to remove code from LLViewerParcelMgr. -class LLViewerParcelMedia : public LLViewerMediaObserver +class LLViewerParcelMedia : public LLViewerMediaObserver, public LLSingleton { + LLSINGLETON(LLViewerParcelMedia); + ~LLViewerParcelMedia(); LOG_CLASS(LLViewerParcelMedia); - public: - static void initClass(); - static void cleanupClass(); - - static void update(LLParcel* parcel); - // called when the agent's parcel has a new URL, or the agent has - // walked on to a new parcel with media - - static void play(LLParcel* parcel); - // user clicked play button in media transport controls - - static void stop(); - // user clicked stop button in media transport controls - - static void pause(); - static void start(); - // restart after pause - no need for all the setup - - static void focus(bool focus); - - static void seek(F32 time); - // jump to timecode time - - static LLPluginClassMediaOwner::EMediaStatus getStatus(); - static std::string getMimeType(); - static std::string getURL(); - static std::string getName(); - static viewer_media_t getParcelMedia(); - - static void processParcelMediaCommandMessage( LLMessageSystem *msg, void ** ); - static void processParcelMediaUpdate( LLMessageSystem *msg, void ** ); - static void sendMediaNavigateMessage(const std::string& url); - - // inherited from LLViewerMediaObserver - virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); - - public: - static S32 sMediaParcelLocalID; - static LLUUID sMediaRegionID; - // HACK: this will change with Media on a Prim - static viewer_media_t sMediaImpl; +public: + void update(LLParcel* parcel); + // called when the agent's parcel has a new URL, or the agent has + // walked on to a new parcel with media + + void play(LLParcel* parcel); + // user clicked play button in media transport controls + + void stop(); + // user clicked stop button in media transport controls + + void pause(); + void start(); + // restart after pause - no need for all the setup + + void focus(bool focus); + + void seek(F32 time); + // jump to timecode time + + LLPluginClassMediaOwner::EMediaStatus getStatus(); + std::string getMimeType(); + std::string getURL(); + std::string getName(); + viewer_media_t getParcelMedia(); + bool hasParcelMedia() { return mMediaImpl.notNull(); } + + static void parcelMediaCommandMessageHandler( LLMessageSystem *msg, void ** ); + static void parcelMediaUpdateHandler( LLMessageSystem *msg, void ** ); + void sendMediaNavigateMessage(const std::string& url); + + // inherited from LLViewerMediaObserver + virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + +private: + void processParcelMediaCommandMessage(LLMessageSystem *msg); + void processParcelMediaUpdate(LLMessageSystem *msg); + + S32 mMediaParcelLocalID; + LLUUID mMediaRegionID; + // HACK: this will change with Media on a Prim + viewer_media_t mMediaImpl; }; diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp index 57ee583eae..d38a434d6c 100644 --- a/indra/newview/llviewerparcelmediaautoplay.cpp +++ b/indra/newview/llviewerparcelmediaautoplay.cpp @@ -122,7 +122,7 @@ BOOL LLViewerParcelMediaAutoPlay::tick() (mTimeInParcel > AUTOPLAY_TIME) && // and if we've been here for so many seconds (!this_media_url.empty()) && // and if the parcel has media (stricmp(this_media_type.c_str(), LLMIMETypes::getDefaultMimeType().c_str()) != 0) && - (LLViewerParcelMedia::sMediaImpl.isNull())) // and if the media is not already playing + (!LLViewerParcelMedia::getInstance()->hasParcelMedia())) // and if the media is not already playing { if (this_media_texture_id.notNull()) // and if the media texture is good { @@ -144,7 +144,7 @@ BOOL LLViewerParcelMediaAutoPlay::tick() if (gSavedSettings.getBOOL("ParcelMediaAutoPlayEnable")) { // and last but not least, only play when autoplay is enabled - LLViewerParcelMedia::play(this_parcel); + LLViewerParcelMedia::getInstance()->play(this_parcel); } } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 416d5d8e2e..6cc88d0c0b 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1822,7 +1822,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use else { // Check for video - LLViewerParcelMedia::update(parcel); + LLViewerParcelMedia::getInstance()->update(parcel); // Then check for music if (gAudiop) -- cgit v1.3 From 779b5627c5e9c76a06938cd4e73a5b8f0440cabc Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 3 Jul 2019 20:06:47 +0300 Subject: DRTVWR-493 LLAvatarNameCache to singletone --- indra/llmessage/llavatarnamecache.cpp | 281 ++++++++++--------------- indra/llmessage/llavatarnamecache.h | 98 ++++++++- indra/newview/llappviewer.cpp | 13 +- indra/newview/llavatarlist.cpp | 2 +- indra/newview/llfloaterconversationpreview.cpp | 2 +- indra/newview/llfloaterimcontainer.cpp | 4 +- indra/newview/llfloaterimnearbychat.cpp | 2 +- indra/newview/llfloaterpreference.cpp | 4 +- indra/newview/llimprocessing.cpp | 2 +- indra/newview/llimview.cpp | 2 +- indra/newview/llnotificationhandlerutil.cpp | 2 +- indra/newview/llstartup.cpp | 9 +- indra/newview/llviewermenu.cpp | 1 - 13 files changed, 220 insertions(+), 202 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index ba1a2a035e..6a287f0cc5 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -49,101 +49,22 @@ #include #include -namespace LLAvatarNameCache -{ - use_display_name_signal_t mUseDisplayNamesSignal; - - // Cache starts in a paused state until we can determine if the - // current region supports display names. - bool sRunning = false; - - // Use the People API (modern) for fetching name if true. Use the old legacy protocol if false. - // For testing, there's a UsePeopleAPI setting that can be flipped (must restart viewer). - bool sUsePeopleAPI = true; - - // Base lookup URL for name service. - // On simulator, loaded from indra.xml - // On viewer, usually a simulator capability (at People API team's request) - // Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/" - std::string sNameLookupURL; - - // Accumulated agent IDs for next query against service - typedef std::set ask_queue_t; - ask_queue_t sAskQueue; - - // Agent IDs that have been requested, but with no reply. - // Maps agent ID to frame time request was made. - typedef std::map pending_queue_t; - pending_queue_t sPendingQueue; - - // Callbacks to fire when we received a name. - // May have multiple callbacks for a single ID, which are - // represented as multiple slots bound to the signal. - // Avoid copying signals via pointers. - typedef std::map signal_map_t; - signal_map_t sSignalMap; - - // The cache at last, i.e. avatar names we know about. - typedef std::map cache_t; - cache_t sCache; - - // Send bulk lookup requests a few times a second at most. - // Only need per-frame timing resolution. - LLFrameTimer sRequestTimer; - - // Maximum time an unrefreshed cache entry is allowed. - const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0; - - // Time when unrefreshed cached names were checked last. - static F64 sLastExpireCheck; - - // Time-to-live for a temp cache entry. - const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0; - - LLCore::HttpRequest::ptr_t sHttpRequest; - LLCore::HttpHeaders::ptr_t sHttpHeaders; - LLCore::HttpOptions::ptr_t sHttpOptions; - LLCore::HttpRequest::policy_t sHttpPolicy; - LLCore::HttpRequest::priority_t sHttpPriority; - - //----------------------------------------------------------------------- - // Internal methods - //----------------------------------------------------------------------- - - // Handle name response off network. - void processName(const LLUUID& agent_id, - const LLAvatarName& av_name); - - void requestNamesViaCapability(); - - // Legacy name system callbacks - void legacyNameCallback(const LLUUID& agent_id, - const std::string& full_name, - bool is_group); - void legacyNameFetch(const LLUUID& agent_id, - const std::string& full_name, - bool is_group); - - void requestNamesViaLegacy(); - - // Do a single callback to a given slot - void fireSignal(const LLUUID& agent_id, - const callback_slot_t& slot, - const LLAvatarName& av_name); - - // Is a request in-flight over the network? - bool isRequestPending(const LLUUID& agent_id); - // Erase expired names from cache - void eraseUnrefreshed(); +// Time-to-live for a temp cache entry. +const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0; +// Maximum time an unrefreshed cache entry is allowed. +const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0; - bool expirationFromCacheControl(const LLSD& headers, F64 *expires); +// Send bulk lookup requests a few times a second at most. +// Only need per-frame timing resolution. +static LLFrameTimer sRequestTimer; - // This is a coroutine. - void requestAvatarNameCache_(std::string url, std::vector agentIds); - - void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult); -} +// static to avoid unnessesary dependencies +LLCore::HttpRequest::ptr_t sHttpRequest; +LLCore::HttpHeaders::ptr_t sHttpHeaders; +LLCore::HttpOptions::ptr_t sHttpOptions; +LLCore::HttpRequest::policy_t sHttpPolicy; +LLCore::HttpRequest::priority_t sHttpPriority; /* Sample response: @@ -187,6 +108,30 @@ namespace LLAvatarNameCache // Coroutine for sending and processing avatar name cache requests. // Do not call directly. See documentation in lleventcoro.h and llcoro.h for // further explanation. + +LLAvatarNameCache::LLAvatarNameCache() +{ + // Will be set to running later + // For now fail immediate lookups and query async ones. + mRunning = false; + + mUsePeopleAPI = true; + + sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); + sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()); + sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()); + sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID; + sHttpPriority = 0; +} + +LLAvatarNameCache::~LLAvatarNameCache() +{ + sHttpRequest.reset(); + sHttpHeaders.reset(); + sHttpOptions.reset(); + mCache.clear(); +} + void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector agentIds) { LL_DEBUGS("AvNameCache") << "Entering coroutine " << LLCoros::instance().getName() @@ -205,7 +150,7 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vectorhandleAgentError(agent_id); } return; } - LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults); + LLAvatarNameCache::getInstance()->handleAvNameCacheSuccess(results, httpResults); } catch (...) @@ -300,15 +245,15 @@ void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &h } } LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result " - << LLAvatarNameCache::sCache.size() << " cached names" + << LLAvatarNameCache::mCache.size() << " cached names" << LL_ENDL; } // Provide some fallback for agents that return errors void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) { - std::map::iterator existing = sCache.find(agent_id); - if (existing == sCache.end()) + std::map::iterator existing = mCache.find(agent_id); + if (existing == mCache.end()) { // there is no existing cache entry, so make a temporary name from legacy LL_WARNS("AvNameCache") << "LLAvatarNameCache get legacy for agent " @@ -322,7 +267,7 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) // been returned by the get method, there is no need to signal anyone // Clear this agent from the pending list - LLAvatarNameCache::sPendingQueue.erase(agent_id); + LLAvatarNameCache::mPendingQueue.erase(agent_id); LLAvatarName& av_name = existing->second; LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL; @@ -341,19 +286,19 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& } // Add to the cache - sCache[agent_id] = av_name; + mCache[agent_id] = av_name; // Suppress request from the queue - sPendingQueue.erase(agent_id); + mPendingQueue.erase(agent_id); // Signal everyone waiting on this name - signal_map_t::iterator sig_it = sSignalMap.find(agent_id); - if (sig_it != sSignalMap.end()) + signal_map_t::iterator sig_it = mSignalMap.find(agent_id); + if (sig_it != mSignalMap.end()) { callback_signal_t* signal = sig_it->second; (*signal)(agent_id, av_name); - sSignalMap.erase(agent_id); + mSignalMap.erase(agent_id); delete signal; signal = NULL; @@ -379,16 +324,16 @@ void LLAvatarNameCache::requestNamesViaCapability() U32 ids = 0; ask_queue_t::const_iterator it; - while(!sAskQueue.empty()) + while(!mAskQueue.empty()) { - it = sAskQueue.begin(); + it = mAskQueue.begin(); LLUUID agent_id = *it; - sAskQueue.erase(it); + mAskQueue.erase(it); if (url.empty()) { // ...starting new request - url += sNameLookupURL; + url += mNameLookupURL; url += "?ids="; ids = 1; } @@ -402,7 +347,7 @@ void LLAvatarNameCache::requestNamesViaCapability() agent_ids.push_back(agent_id); // mark request as pending - sPendingQueue[agent_id] = now; + mPendingQueue[agent_id] = now; if (url.size() > NAME_URL_SEND_THRESHOLD) { @@ -432,7 +377,7 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, // Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy // protocol, we do not get an expiration date for each name and there's no reason to ask the // data again and again so we set the expiration time to the largest value admissible. - std::map::iterator av_record = sCache.find(agent_id); + std::map::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id); LLAvatarName& av_name = av_record->second; av_name.setExpires(MAX_UNREFRESHED_TIME); } @@ -451,7 +396,7 @@ void LLAvatarNameCache::legacyNameFetch(const LLUUID& agent_id, av_name.fromString(full_name); // Add to cache: we're still using the new cache even if we're using the old (legacy) protocol. - processName(agent_id, av_name); + LLAvatarNameCache::getInstance()->processName(agent_id, av_name); } void LLAvatarNameCache::requestNamesViaLegacy() @@ -460,15 +405,15 @@ void LLAvatarNameCache::requestNamesViaLegacy() F64 now = LLFrameTimer::getTotalSeconds(); std::string full_name; ask_queue_t::const_iterator it; - for (S32 requests = 0; !sAskQueue.empty() && requests < MAX_REQUESTS; ++requests) + for (S32 requests = 0; !mAskQueue.empty() && requests < MAX_REQUESTS; ++requests) { - it = sAskQueue.begin(); + it = mAskQueue.begin(); LLUUID agent_id = *it; - sAskQueue.erase(it); + mAskQueue.erase(it); // Mark as pending first, just in case the callback is immediately // invoked below. This should never happen in practice. - sPendingQueue[agent_id] = now; + mPendingQueue[agent_id] = now; LL_DEBUGS("AvNameCache") << "agent " << agent_id << LL_ENDL; @@ -477,26 +422,6 @@ void LLAvatarNameCache::requestNamesViaLegacy() } } -void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI) -{ - sRunning = running; - sUsePeopleAPI = usePeopleAPI; - - sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); - sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()); - sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()); - sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID; - sHttpPriority = 0; -} - -void LLAvatarNameCache::cleanupClass() -{ - sHttpRequest.reset(); - sHttpHeaders.reset(); - sHttpOptions.reset(); - sCache.clear(); -} - bool LLAvatarNameCache::importFile(std::istream& istr) { LLSD data; @@ -517,9 +442,9 @@ bool LLAvatarNameCache::importFile(std::istream& istr) { agent_id.set(it->first); av_name.fromLLSD( it->second ); - sCache[agent_id] = av_name; + mCache[agent_id] = av_name; } - LL_INFOS("AvNameCache") << "LLAvatarNameCache loaded " << sCache.size() << LL_ENDL; + LL_INFOS("AvNameCache") << "LLAvatarNameCache loaded " << mCache.size() << LL_ENDL; // Some entries may have expired since the cache was stored, // but they will be flushed in the first call to eraseUnrefreshed // from LLAvatarNameResponder::idle @@ -531,9 +456,9 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr) { LLSD agents; F64 max_unrefreshed = LLFrameTimer::getTotalSeconds() - MAX_UNREFRESHED_TIME; - LL_INFOS("AvNameCache") << "LLAvatarNameCache at exit cache has " << sCache.size() << LL_ENDL; - cache_t::const_iterator it = sCache.begin(); - for ( ; it != sCache.end(); ++it) + LL_INFOS("AvNameCache") << "LLAvatarNameCache at exit cache has " << mCache.size() << LL_ENDL; + cache_t::const_iterator it = mCache.begin(); + for ( ; it != mCache.end(); ++it) { const LLUUID& agent_id = it->first; const LLAvatarName& av_name = it->second; @@ -552,23 +477,28 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr) void LLAvatarNameCache::setNameLookupURL(const std::string& name_lookup_url) { - sNameLookupURL = name_lookup_url; + mNameLookupURL = name_lookup_url; } bool LLAvatarNameCache::hasNameLookupURL() { - return !sNameLookupURL.empty(); + return !mNameLookupURL.empty(); +} + +void LLAvatarNameCache::setUsePeopleAPI(bool use_api) +{ + mUsePeopleAPI = use_api; } bool LLAvatarNameCache::usePeopleAPI() { - return hasNameLookupURL() && sUsePeopleAPI; + return hasNameLookupURL() && mUsePeopleAPI; } void LLAvatarNameCache::idle() { // By convention, start running at first idle() call - sRunning = true; + mRunning = true; // *TODO: Possibly re-enabled this based on People API load measurements // 100 ms is the threshold for "user speed" operations, so we can @@ -579,7 +509,7 @@ void LLAvatarNameCache::idle() return; } - if (!sAskQueue.empty()) + if (!mAskQueue.empty()) { if (usePeopleAPI()) { @@ -592,7 +522,7 @@ void LLAvatarNameCache::idle() } } - if (sAskQueue.empty()) + if (mAskQueue.empty()) { // cleared the list, reset the request timer. sRequestTimer.resetWithExpiry(SECS_BETWEEN_REQUESTS); @@ -607,8 +537,8 @@ bool LLAvatarNameCache::isRequestPending(const LLUUID& agent_id) bool isPending = false; const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; - pending_queue_t::const_iterator it = sPendingQueue.find(agent_id); - if (it != sPendingQueue.end()) + pending_queue_t::const_iterator it = mPendingQueue.find(agent_id); + if (it != mPendingQueue.end()) { // in the list of requests in flight, retry if too old F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; @@ -622,11 +552,11 @@ void LLAvatarNameCache::eraseUnrefreshed() F64 now = LLFrameTimer::getTotalSeconds(); F64 max_unrefreshed = now - MAX_UNREFRESHED_TIME; - if (!sLastExpireCheck || sLastExpireCheck < max_unrefreshed) + if (!mLastExpireCheck || mLastExpireCheck < max_unrefreshed) { - sLastExpireCheck = now; + mLastExpireCheck = now; S32 expired = 0; - for (cache_t::iterator it = sCache.begin(); it != sCache.end();) + for (cache_t::iterator it = mCache.begin(); it != mCache.end();) { const LLAvatarName& av_name = it->second; if (av_name.mExpires < max_unrefreshed) @@ -635,7 +565,7 @@ void LLAvatarNameCache::eraseUnrefreshed() << " user '" << av_name.getAccountName() << "' " << "expired " << now - av_name.mExpires << " secs ago" << LL_ENDL; - sCache.erase(it++); + mCache.erase(it++); expired++; } else @@ -644,19 +574,24 @@ void LLAvatarNameCache::eraseUnrefreshed() } } LL_INFOS("AvNameCache") << "LLAvatarNameCache expired " << expired << " cached avatar names, " - << sCache.size() << " remaining" << LL_ENDL; + << mCache.size() << " remaining" << LL_ENDL; } } +//static, wrapper +bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) +{ + return LLAvatarNameCache::getInstance()->getName(agent_id, av_name); +} // fills in av_name if it has it in the cache, even if expired (can check expiry time) // returns bool specifying if av_name was filled, false otherwise -bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) +bool LLAvatarNameCache::getName(const LLUUID& agent_id, LLAvatarName *av_name) { - if (sRunning) + if (mRunning) { // ...only do immediate lookups when cache is running - std::map::iterator it = sCache.find(agent_id); - if (it != sCache.end()) + std::map::iterator it = mCache.find(agent_id); + if (it != mCache.end()) { *av_name = it->second; @@ -667,7 +602,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) { LL_DEBUGS("AvNameCache") << "LLAvatarNameCache refresh agent " << agent_id << LL_ENDL; - sAskQueue.insert(agent_id); + mAskQueue.insert(agent_id); } } @@ -678,7 +613,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) if (!isRequestPending(agent_id)) { LL_DEBUGS("AvNameCache") << "LLAvatarNameCache queue request for agent " << agent_id << LL_ENDL; - sAskQueue.insert(agent_id); + mAskQueue.insert(agent_id); } return false; @@ -693,15 +628,21 @@ void LLAvatarNameCache::fireSignal(const LLUUID& agent_id, signal(agent_id, av_name); } +// static, wrapper LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) +{ + return LLAvatarNameCache::getInstance()->getNameCallback(agent_id, slot); +} + +LLAvatarNameCache::callback_connection_t LLAvatarNameCache::getNameCallback(const LLUUID& agent_id, callback_slot_t slot) { callback_connection_t connection; - if (sRunning) + if (mRunning) { // ...only do immediate lookups when cache is running - std::map::iterator it = sCache.find(agent_id); - if (it != sCache.end()) + std::map::iterator it = mCache.find(agent_id); + if (it != mCache.end()) { const LLAvatarName& av_name = it->second; @@ -717,17 +658,17 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag // schedule a request if (!isRequestPending(agent_id)) { - sAskQueue.insert(agent_id); + mAskQueue.insert(agent_id); } // always store additional callback, even if request is pending - signal_map_t::iterator sig_it = sSignalMap.find(agent_id); - if (sig_it == sSignalMap.end()) + signal_map_t::iterator sig_it = mSignalMap.find(agent_id); + if (sig_it == mSignalMap.end()) { // ...new callback for this id callback_signal_t* signal = new callback_signal_t(); connection = signal->connect(slot); - sSignalMap[agent_id] = signal; + mSignalMap[agent_id] = signal; } else { @@ -760,20 +701,20 @@ void LLAvatarNameCache::setUseUsernames(bool use) void LLAvatarNameCache::erase(const LLUUID& agent_id) { - sCache.erase(agent_id); + mCache.erase(agent_id); } void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name) { // *TODO: update timestamp if zero? - sCache[agent_id] = av_name; + mCache[agent_id] = av_name; } LLUUID LLAvatarNameCache::findIdByName(const std::string& name) { std::map::iterator it; - std::map::iterator end = sCache.end(); - for (it = sCache.begin(); it != end; ++it) + std::map::iterator end = mCache.end(); + for (it = mCache.begin(); it != end; ++it) { if (it->second.getUserName() == name) { diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 63e067c939..ba89d569f3 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -29,21 +29,20 @@ #define LLAVATARNAMECACHE_H #include "llavatarname.h" // for convenience +#include "llsingleton.h" #include +#include class LLSD; class LLUUID; -namespace LLAvatarNameCache +class LLAvatarNameCache : public LLSingleton { + LLSINGLETON(LLAvatarNameCache); + ~LLAvatarNameCache(); +public: typedef boost::signals2::signal use_display_name_signal_t; - // Until the cache is set running, immediate lookups will fail and - // async lookups will be queued. This allows us to block requests - // until we know if the first region supports display names. - void initClass(bool running, bool usePeopleAPI); - void cleanupClass(); - // Import/export the name cache to file. bool importFile(std::istream& istr); void exportFile(std::ostream& ostr); @@ -55,6 +54,7 @@ namespace LLAvatarNameCache // Do we have a valid lookup URL, i.e. are we trying to use the // more recent display name lookup system? bool hasNameLookupURL(); + void setUsePeopleAPI(bool use_api); bool usePeopleAPI(); // Periodically makes a batch request for display names not already in @@ -63,7 +63,8 @@ namespace LLAvatarNameCache // If name is in cache, returns true and fills in provided LLAvatarName // otherwise returns false. - bool get(const LLUUID& agent_id, LLAvatarName *av_name); + static bool get(const LLUUID& agent_id, LLAvatarName *av_name); + bool getName(const LLUUID& agent_id, LLAvatarName *av_name); // Callback types for get() below typedef boost::signals2::signal< @@ -74,7 +75,8 @@ namespace LLAvatarNameCache // Fetches name information and calls callbacks. // If name information is in cache, callbacks will be called immediately. - callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot); + static callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot); + callback_connection_t getNameCallback(const LLUUID& agent_id, callback_slot_t slot); // Set display name: flips the switch and triggers the callbacks. void setUseDisplayNames(bool use); @@ -100,7 +102,83 @@ namespace LLAvatarNameCache F64 nameExpirationFromHeaders(const LLSD& headers); void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb); -} + +private: + // Handle name response off network. + void processName(const LLUUID& agent_id, + const LLAvatarName& av_name); + + void requestNamesViaCapability(); + + // Legacy name system callbacks + static void legacyNameCallback(const LLUUID& agent_id, + const std::string& full_name, + bool is_group); + static void legacyNameFetch(const LLUUID& agent_id, + const std::string& full_name, + bool is_group); + + void requestNamesViaLegacy(); + + // Do a single callback to a given slot + void fireSignal(const LLUUID& agent_id, + const callback_slot_t& slot, + const LLAvatarName& av_name); + + // Is a request in-flight over the network? + bool isRequestPending(const LLUUID& agent_id); + + // Erase expired names from cache + void eraseUnrefreshed(); + + bool expirationFromCacheControl(const LLSD& headers, F64 *expires); + + // This is a coroutine. + static void requestAvatarNameCache_(std::string url, std::vector agentIds); + + void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult); + +private: + + use_display_name_signal_t mUseDisplayNamesSignal; + + // Cache starts in a paused state until we can determine if the + // current region supports display names. + bool mRunning; + + // Use the People API (modern) for fetching name if true. Use the old legacy protocol if false. + // For testing, there's a UsePeopleAPI setting that can be flipped (must restart viewer). + bool mUsePeopleAPI; + + // Base lookup URL for name service. + // On simulator, loaded from indra.xml + // On viewer, usually a simulator capability (at People API team's request) + // Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/" + std::string mNameLookupURL; + + // Accumulated agent IDs for next query against service + typedef std::set ask_queue_t; + ask_queue_t mAskQueue; + + // Agent IDs that have been requested, but with no reply. + // Maps agent ID to frame time request was made. + typedef std::map pending_queue_t; + pending_queue_t mPendingQueue; + + // Callbacks to fire when we received a name. + // May have multiple callbacks for a single ID, which are + // represented as multiple slots bound to the signal. + // Avoid copying signals via pointers. + typedef std::map signal_map_t; + signal_map_t mSignalMap; + + // The cache at last, i.e. avatar names we know about. + typedef std::map cache_t; + cache_t mCache; + + // Time when unrefreshed cached names were checked last. + F64 mLastExpireCheck; +}; // Parse a cache-control header to get the max-age delta-seconds. // Returns true if header has max-age param and it parses correctly. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 151039acce..823ded7a50 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4509,7 +4509,7 @@ void LLAppViewer::loadNameCache() llifstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { - if ( ! LLAvatarNameCache::importFile(name_cache_stream)) + if ( ! LLAvatarNameCache::getInstance()->importFile(name_cache_stream)) { LL_WARNS("AppInit") << "removing invalid '" << filename << "'" << LL_ENDL; name_cache_stream.close(); @@ -4536,7 +4536,7 @@ void LLAppViewer::saveNameCache() llofstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { - LLAvatarNameCache::exportFile(name_cache_stream); + LLAvatarNameCache::getInstance()->exportFile(name_cache_stream); } // real names cache @@ -5143,7 +5143,8 @@ void LLAppViewer::idleNameCache() // granted to neighbor regions before the main agent gets there. Can't // do it in the move-into-region code because cap not guaranteed to be // granted yet, for example on teleport. - bool had_capability = LLAvatarNameCache::hasNameLookupURL(); + LLAvatarNameCache *name_cache = LLAvatarNameCache::getInstance(); + bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL(); std::string name_lookup_url; name_lookup_url.reserve(128); // avoid a memory allocation below name_lookup_url = region->getCapability("GetDisplayNames"); @@ -5160,12 +5161,12 @@ void LLAppViewer::idleNameCache() { name_lookup_url += '/'; } - LLAvatarNameCache::setNameLookupURL(name_lookup_url); + name_cache->setNameLookupURL(name_lookup_url); } else { // Display names not available on this region - LLAvatarNameCache::setNameLookupURL( std::string() ); + name_cache->setNameLookupURL( std::string() ); } // Error recovery - did we change state? @@ -5175,7 +5176,7 @@ void LLAppViewer::idleNameCache() LLVOAvatar::invalidateNameTags(); } - LLAvatarNameCache::idle(); + name_cache->idle(); } // diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 513f25e301..b0715a3afd 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -154,7 +154,7 @@ LLAvatarList::LLAvatarList(const Params& p) mLITUpdateTimer->start(); } - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLAvatarList::handleDisplayNamesOptionChanged, this)); + LLAvatarNameCache::getInstance()->addUseDisplayNamesCallback(boost::bind(&LLAvatarList::handleDisplayNamesOptionChanged, this)); } diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 66198b3bf6..4905ce5fc2 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -221,7 +221,7 @@ void LLFloaterConversationPreview::showHistory() else { std::string legacy_name = gCacheName->buildLegacyName(from); - from_id = LLAvatarNameCache::findIdByName(legacy_name); + from_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); } LLChat chat; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 30d05ae287..21420b122b 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -237,7 +237,7 @@ BOOL LLFloaterIMContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"), false); - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); + LLAvatarNameCache::getInstance()->addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); if (! mMessagesPane->isCollapsed() && ! mConversationsPane->isCollapsed()) @@ -267,7 +267,7 @@ BOOL LLFloaterIMContainer::postBuild() // We'll take care of view updates on idle gIdleCallbacks.addFunction(idle, this); // When display name option change, we need to reload all participant names - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMContainer::processParticipantsStyleUpdate, this)); + LLAvatarNameCache::getInstance()->addUseDisplayNamesCallback(boost::bind(&LLFloaterIMContainer::processParticipantsStyleUpdate, this)); mParticipantRefreshTimer.setTimerExpirySec(0); mParticipantRefreshTimer.start(); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index f9efd13608..a6531ed7e1 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -228,7 +228,7 @@ void LLFloaterIMNearbyChat::loadHistory() else { std::string legacy_name = gCacheName->buildLegacyName(from); - from_id = LLAvatarNameCache::findIdByName(legacy_name); + from_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); } LLChat chat; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 98e4cefebb..64a71c502d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -278,13 +278,13 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response void handleNameTagOptionChanged(const LLSD& newvalue) { - LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); + LLAvatarNameCache::getInstance()->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); LLVOAvatar::invalidateNameTags(); } void handleDisplayNamesOptionChanged(const LLSD& newvalue) { - LLAvatarNameCache::setUseDisplayNames(newvalue.asBoolean()); + LLAvatarNameCache::getInstance()->setUseDisplayNames(newvalue.asBoolean()); LLVOAvatar::invalidateNameTags(); } diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index d59c301210..3606a439a6 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -695,7 +695,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, // The group notice packet does not have an AgentID. Obtain one from the name cache. // If last name is "Resident" strip it out so the cache name lookup works. std::string legacy_name = gCacheName->buildLegacyName(original_name); - agent_id = LLAvatarNameCache::findIdByName(legacy_name); + agent_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); if (agent_id.isNull()) { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8ec8c0a563..fc2f50b3f6 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -806,7 +806,7 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list& histo { // convert it to a legacy name if we have a complete name std::string legacy_name = gCacheName->buildLegacyName(from); - from_id = LLAvatarNameCache::findIdByName(legacy_name); + from_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); } std::string timestamp = msg[LL_IM_TIME]; diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 6a58196760..9a3f1a853a 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -177,7 +177,7 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( { // Legacy support and fallback method // if we can't retrieve sender id from group notice system message, try to lookup it from cache - sender_id = LLAvatarNameCache::findIdByName(sender_name); + sender_id = LLAvatarNameCache::getInstance()->findIdByName(sender_name); } logToIM(IM_SESSION_GROUP_START, group_name, sender_name, payload["message"], diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8be453ad6c..15b3ba75c9 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2833,9 +2833,10 @@ void LLStartUp::initNameCache() // Start cache in not-running state until we figure out if we have // capabilities for display name lookup - LLAvatarNameCache::initClass(false,gSavedSettings.getBOOL("UsePeopleAPI")); - LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); - LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); + LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance(); + cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI")); + cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); + cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); } @@ -2850,8 +2851,6 @@ void LLStartUp::initExperiences() void LLStartUp::cleanupNameCache() { - SUBSYSTEM_CLEANUP(LLAvatarNameCache); - delete gCacheName; gCacheName = NULL; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8f90225359..f1c073ed84 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8653,7 +8653,6 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - SUBSYSTEM_CLEANUP(LLAvatarNameCache); if (gCacheName) gCacheName->clear(); } -- cgit v1.3 From 47cbcb61f8b7cbfb0f14043118c4e50b100d0068 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 4 Jul 2019 20:24:38 +0300 Subject: DRTVWR-493 Cleaned up unneded inits. --- indra/newview/llappviewer.cpp | 2 -- indra/newview/llface.cpp | 6 ------ indra/newview/llface.h | 2 -- indra/newview/llstartup.cpp | 2 -- indra/newview/lltoastalertpanel.cpp | 13 ++++++++++--- indra/newview/lltoastalertpanel.h | 15 --------------- indra/newview/llweb.cpp | 27 --------------------------- indra/newview/llweb.h | 2 -- 8 files changed, 10 insertions(+), 59 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 823ded7a50..076594a5c8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -896,8 +896,6 @@ bool LLAppViewer::init() // LLKeyboard relies on LLUI to know what some accelerator keys are called. LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString ); - LLWeb::initClass(); // do this after LLUI - // Provide the text fields with callbacks for opening Urls LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null)); LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false)); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index b2da5bb9f8..004e4a6262 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -228,12 +228,6 @@ void LLFace::destroy() mVObjp = NULL; } - -// static -void LLFace::initClass() -{ -} - void LLFace::setWorldMatrix(const LLMatrix4 &mat) { LL_ERRS() << "Faces on this drawable are not independently modifiable\n" << LL_ENDL; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 736d45b7ad..83547c75e8 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -80,8 +80,6 @@ public: PARTICLE = 0x0080, }; - static void initClass(); - static void cacheFaceInVRAM(const LLVolumeFace& vf); public: diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 15b3ba75c9..7f9f0da315 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1226,8 +1226,6 @@ bool idle_startup() LLSurface::initClasses(); display_startup(); - - LLFace::initClass(); display_startup(); LLDrawable::initClass(); diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 495c9c1f44..941cb410fc 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -45,6 +45,7 @@ #include "llrootview.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" // for gSavedSettings +#include "llweb.h" #include @@ -52,7 +53,6 @@ const S32 MAX_ALLOWED_MSG_WIDTH = 400; const F32 DEFAULT_BUTTON_DELAY = 0.5f; /*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL; -/*static*/ LLToastAlertPanel::URLLoader* LLToastAlertPanel::sURLLoader; //----------------------------------------------------------------------------- // Private methods @@ -555,9 +555,16 @@ void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button ) response[button_data->mButton->getName()] = true; // If we declared a URL and chose the URL option, go to the url - if (!button_data->mURL.empty() && sURLLoader != NULL) + if (!button_data->mURL.empty()) { - sURLLoader->load(button_data->mURL, button_data->mURLExternal); + if (button_data->mURLExternal) + { + LLWeb::loadURLExternal(button_data->mURL); + } + else + { + LLWeb::loadURL(button_data->mURL); + } } mNotification->respond(response); // new notification reponse diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index d1be5e018e..15bf11d42c 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -52,20 +52,6 @@ class LLToastAlertPanel public: typedef bool (*display_callback_t)(S32 modal); - class URLLoader - { - public: - virtual void load(const std::string& url, bool force_open_externally = 0) = 0; - virtual ~URLLoader() - { - } - }; - - static void setURLLoader(URLLoader* loader) - { - sURLLoader = loader; - } - public: // User's responsibility to call show() after creating these. LLToastAlertPanel( LLNotificationPtr notep, bool is_modal ); @@ -94,7 +80,6 @@ private: BOOL hasTitleBar() const; private: - static URLLoader* sURLLoader; static LLControlGroup* sSettings; struct ButtonData diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 0cdc7f0d88..a34c5826ed 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -39,7 +39,6 @@ #include "lllogininstance.h" #include "llparcel.h" #include "llsd.h" -#include "lltoastalertpanel.h" #include "llui.h" #include "lluri.h" #include "llversioninfo.h" @@ -57,32 +56,6 @@ bool on_load_url_external_response(const LLSD& notification, const LLSD& response, bool async ); -class URLLoader : public LLToastAlertPanel::URLLoader -{ - virtual void load(const std::string& url , bool force_open_externally) - { - if (force_open_externally) - { - LLWeb::loadURLExternal(url); - } - else - { - LLWeb::loadURL(url); - } - } -}; -static URLLoader sAlertURLLoader; - - -// static -void LLWeb::initClass() -{ - LLToastAlertPanel::setURLLoader(&sAlertURLLoader); -} - - - - // static void LLWeb::loadURL(const std::string& url, const std::string& target, const std::string& uuid) { diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 7149ce9baf..0426f00f27 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -46,8 +46,6 @@ public: BROWSER_INT_LL_EXT_OTHERS = 1, BROWSER_INTERNAL_ONLY = 2 }; - - static void initClass(); /// Load the given url in the operating system's web browser, async if we want to return immediately /// before browser has spawned -- cgit v1.3 From 17fae30f721c716bab1dd78cc5f8ac6b0aad49e0 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 25 Jul 2019 15:17:11 +0300 Subject: DRTVWR-493 LLImage to LLParamSingleton --- indra/llcommon/llsingleton.h | 205 ++++++++++++++++++++++++++++++++++++++ indra/llimage/llimage.cpp | 34 +++---- indra/llimage/llimage.h | 31 +++--- indra/llimage/llimagej2c.cpp | 4 +- indra/newview/llappviewer.cpp | 3 +- indra/newview/llconversationlog.h | 5 +- indra/newview/llstartup.cpp | 2 +- 7 files changed, 240 insertions(+), 44 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 859e271e26..b127f4f529 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -446,6 +446,177 @@ public: return sData.mInitState == DELETED; } +protected: + static EInitState getInitState() + { + return sData.mInitState; + } + +private: + struct SingletonData + { + // explicitly has a default constructor so that member variables are zero initialized in BSS + // and only changed by singleton logic, not constructor running during startup + EInitState mInitState; + DERIVED_TYPE* mInstance; + }; + static SingletonData sData; +}; + + +template +class LLParamSingleton : public LLSingletonBase +{ +private: + + template + static DERIVED_TYPE* constructSingleton(Args&&... args) + { + return new DERIVED_TYPE(std::forward(args)...); + } + + // We know of no way to instruct the compiler that every subclass + // constructor MUST be private. + // However, we can make the LLPARAMSINGLETON() macro both declare + // a private constructor and provide the required friend declaration. + // How can we ensure that every subclass uses LLPARAMSINGLETON()? + // By making that macro provide a definition for this pure virtual + // method. If you get "can't instantiate class due to missing pure + // virtual method" for this method, then add LLPARAMSINGLETON(yourclass) + // in the subclass body. + virtual void you_must_use_LLSINGLETON_macro() = 0; + +protected: + // Pass DERIVED_TYPE explicitly to LLSingletonBase's constructor because, + // until our subclass constructor completes, *this isn't yet a + // full-fledged DERIVED_TYPE. + LLParamSingleton() : LLSingletonBase(LLSingletonBase::tag()) + { + // populate base-class function pointer with the static + // deleteSingleton() function for this particular specialization + mDeleteSingleton = &deleteSingleton; + + // add this new instance to the master list + LLSingleton_manage_master().add(this); + } + +public: + + virtual ~LLParamSingleton() + { + // remove this instance from the master list + LLSingleton_manage_master().remove(this); + sData.mInstance = NULL; + sData.mInitState = DELETED; + } + + // Passes arguments to DERIVED_TYPE's constructor and sets apropriate states + template + static void initParamSingleton(Args&&... args) + { + sData.mInitState = CONSTRUCTING; + sData.mInstance = constructSingleton(std::forward(args)...); + sData.mInitState = INITIALIZED; + // initialize singleton after constructing it so that it can + // reference other singletons which in turn depend on it, thus + // breaking cyclic dependencies + sData.mInstance->initSingleton(); + // pop this off stack of initializing singletons + LLSingleton_manage_master().pop_initializing(sData.mInstance); + } + + /** + * @brief Immediately delete the singleton. + * + * A subsequent call to LLProxy::getInstance() will construct a new + * instance of the class. + * + * Without an explicit call to LLSingletonBase::deleteAll(), LLSingletons + * are implicitly destroyed after main() has exited and the C++ runtime is + * cleaning up statically-constructed objects. Some classes derived from + * LLSingleton have objects that are part of a runtime system that is + * terminated before main() exits. Calling the destructor of those objects + * after the termination of their respective systems can cause crashes and + * other problems during termination of the project. Using this method to + * destroy the singleton early can prevent these crashes. + * + * An example where this is needed is for a LLSingleton that has an APR + * object as a member that makes APR calls on destruction. The APR system is + * shut down explicitly before main() exits. This causes a crash on exit. + * Using this method before the call to apr_terminate() and NOT calling + * getInstance() again will prevent the crash. + */ + static void deleteSingleton() + { + delete sData.mInstance; + sData.mInstance = NULL; + sData.mInitState = DELETED; + } + + static DERIVED_TYPE* getInstance() + { + switch (sData.mInitState) + { + case UNINITIALIZED: + logerrs("Uninitialized param singleton ", + demangle(typeid(DERIVED_TYPE).name()).c_str()); + return NULL; + + case CONSTRUCTING: + logerrs("Tried to access singleton ", + demangle(typeid(DERIVED_TYPE).name()).c_str(), + " from singleton constructor!"); + return NULL; + + case INITIALIZING: + logerrs("State not supported by ", + demangle(typeid(DERIVED_TYPE).name()).c_str(), + " since it is a parametric singleton!"); + break; + + case INITIALIZED: + break; + + case DELETED: + logerrs("Trying to access deleted param singleton ", + demangle(typeid(DERIVED_TYPE).name()).c_str()); + + break; + } + + // By this point, if DERIVED_TYPE was pushed onto the initializing + // stack, it has been popped off. So the top of that stack, if any, is + // an LLSingleton that directly depends on DERIVED_TYPE. If this call + // came from another LLSingleton, rather than from vanilla application + // code, record the dependency. + sData.mInstance->capture_dependency( + LLSingleton_manage_master().get_initializing(sData.mInstance), + sData.mInitState); + return sData.mInstance; + } + + // Reference version of getInstance() + // Preferred over getInstance() as it disallows checking for NULL + static DERIVED_TYPE& instance() + { + return *getInstance(); + } + + // Has this singleton been created yet? + // Use this to avoid accessing singletons before they can safely be constructed. + static bool instanceExists() + { + return sData.mInitState == INITIALIZED; + } + + // Has this singleton been deleted? This can be useful during shutdown + // processing to avoid "resurrecting" a singleton we thought we'd already + // cleaned up. + static bool wasDeleted() + { + return sData.mInitState == DELETED; + } + private: struct SingletonData { @@ -460,6 +631,9 @@ private: template typename LLSingleton::SingletonData LLSingleton::sData; +template +typename LLParamSingleton::SingletonData LLParamSingleton::sData; + /** * Use LLSINGLETON(Foo); at the start of an LLSingleton subclass body * when you want to declare an out-of-line constructor: @@ -510,4 +684,35 @@ private: \ /* LLSINGLETON() is carefully implemented to permit exactly this */ \ LLSINGLETON(DERIVED_CLASS) {} +/** +* Use LLPARAMSINGLETON(Foo); at the start of an LLParamSingleton subclass body +* when you want to declare an out-of-line constructor: +* +* @code +* class Foo: public LLParamSingleton +* { +* // use this macro at start of every LLSingleton subclass +* LLPARAMSINGLETON(Foo); +* public: +* // ... +* }; +* // ... +* [inline] +* Foo::Foo() { ... } +* @endcode +* +* Unfortunately, this mechanism does not permit you to define even a simple +* (but nontrivial) constructor within the class body. Use LLPARAMSINGLETON() +* and define the constructor outside the class body. If you must define it +* in a header file, use 'inline' (unless it's a template class) to avoid +* duplicate-symbol errors at link time. +*/ +#define LLPARAMSINGLETON(DERIVED_CLASS, ...) \ +private: \ + /* implement LLSingleton pure virtual method whose sole purpose */ \ + /* is to remind people to use this macro */ \ + virtual void you_must_use_LLSINGLETON_macro() {} \ + friend class LLParamSingleton; \ + DERIVED_CLASS(__VA_ARGS__) + #endif diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 680fbf548f..9dea876114 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -583,39 +583,29 @@ static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 src // LLImage //--------------------------------------------------------------------------- -//static -std::string LLImage::sLastErrorMessage; -LLMutex* LLImage::sMutex = NULL; -bool LLImage::sUseNewByteRange = false; -S32 LLImage::sMinimalReverseByteRangePercent = 75; - -//static -void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) +LLImage::LLImage(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) { - sUseNewByteRange = use_new_byte_range; - sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; - sMutex = new LLMutex(); + mMutex = new LLMutex(); + mUseNewByteRange = use_new_byte_range; + mMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; } -//static -void LLImage::cleanupClass() +LLImage::~LLImage() { - delete sMutex; - sMutex = NULL; + delete mMutex; + mMutex = NULL; } -//static -const std::string& LLImage::getLastError() +const std::string& LLImage::getLastErrorMessage() { static const std::string noerr("No Error"); - return sLastErrorMessage.empty() ? noerr : sLastErrorMessage; + return mLastErrorMessage.empty() ? noerr : mLastErrorMessage; } -//static -void LLImage::setLastError(const std::string& message) +void LLImage::setLastErrorMessage(const std::string& message) { - LLMutexLock m(sMutex); - sLastErrorMessage = message; + LLMutexLock m(mMutex); + mLastErrorMessage = message; } //--------------------------------------------------------------------------- diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 8ec49d3f0f..e5526ba9c0 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -30,6 +30,7 @@ #include "lluuid.h" #include "llstring.h" #include "llpointer.h" +#include "llsingleton.h" #include "lltrace.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 @@ -88,23 +89,25 @@ typedef enum e_image_codec //============================================================================ // library initialization class -class LLImage +class LLImage : public LLParamSingleton { + LLPARAMSINGLETON(LLImage, bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); + ~LLImage(); public: - static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); - static void cleanupClass(); - static const std::string& getLastError(); - static void setLastError(const std::string& message); - - static bool useNewByteRange() { return sUseNewByteRange; } - static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; } - -protected: - static LLMutex* sMutex; - static std::string sLastErrorMessage; - static bool sUseNewByteRange; - static S32 sMinimalReverseByteRangePercent; + const std::string& getLastErrorMessage(); + static const std::string& getLastError() { return getInstance()->getLastErrorMessage(); }; + void setLastErrorMessage(const std::string& message); + static void setLastError(const std::string& message) { getInstance()->setLastErrorMessage(message); } + + bool useNewByteRange() { return mUseNewByteRange; } + S32 getReverseByteRangePercent() { return mMinimalReverseByteRangePercent; } + +private: + LLMutex* mMutex; + std::string mLastErrorMessage; + bool mUseNewByteRange; + S32 mMinimalReverseByteRangePercent; }; //============================================================================ diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 4bff21610f..71cab0554d 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -281,7 +281,7 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r S32 bytes; S32 new_bytes = (S32) (sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor); S32 old_bytes = (S32)((F32)(w*h*comp)*rate); - bytes = (LLImage::useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes); + bytes = (LLImage::getInstance()->useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes); bytes = llmax(bytes, calcHeaderSizeJ2C()); return bytes; } @@ -322,7 +322,7 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes) { S32 bytes_needed = calcDataSize(discard_level); // Use TextureReverseByteRange percent (see settings.xml) of the optimal size to qualify as correct rendering for the given discard level - if (bytes >= (bytes_needed*LLImage::getReverseByteRangePercent()/100)) + if (bytes >= (bytes_needed*LLImage::getInstance()->getReverseByteRangePercent()/100)) { break; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0435c3d398..cb4655cd87 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2040,7 +2040,6 @@ bool LLAppViewer::cleanup() LLUIImageList::getInstance()->cleanUp(); // This should eventually be done in LLAppViewer - SUBSYSTEM_CLEANUP(LLImage); SUBSYSTEM_CLEANUP(LLVFSThread); SUBSYSTEM_CLEANUP(LLLFSThread); @@ -2148,7 +2147,7 @@ bool LLAppViewer::initThreads() { static const bool enable_threads = true; - LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); + LLImage::initParamSingleton(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); LLVFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 035cbcb945..38247f8eff 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -107,11 +107,10 @@ private: * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. */ -class LLConversationLog : public LLSingleton, LLIMSessionObserver +class LLConversationLog : public LLParamSingleton, LLIMSessionObserver { - LLSINGLETON(LLConversationLog); + LLPARAMSINGLETON(LLConversationLog); public: - void removeConversation(const LLConversation& conversation); /** diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7f9f0da315..82e1d6be4a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1289,7 +1289,7 @@ bool idle_startup() display_startup(); LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); - LLConversationLog::getInstance(); + LLConversationLog::initParamSingleton(); return FALSE; } -- cgit v1.3 From d6030c7376b930d0bfc40c29ec9888e3db851c06 Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Mon, 12 Aug 2019 19:54:20 +0300 Subject: SL-11719 Initialize the conversation dialog on login screen appearance to avoid crash --- indra/newview/llstartup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 82e1d6be4a..e4cabbaddd 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -806,6 +806,8 @@ bool idle_startup() gLoginMenuBarView->setEnabled( TRUE ); show_debug_menus(); + LLConversationLog::initParamSingleton(); + // Hide the splash screen LLSplashScreen::hide(); // Push our window frontmost @@ -1288,8 +1290,6 @@ bool idle_startup() display_startup(); LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); - - LLConversationLog::initParamSingleton(); return FALSE; } -- cgit v1.3 From 24a0601a50f81b8f1a21c2c64c118702dd93f645 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 13 Aug 2019 20:19:46 +0300 Subject: DRTVWR-493 Reworked a number of inits --- indra/newview/llappviewer.cpp | 6 ++---- indra/newview/lldonotdisturbnotificationstorage.cpp | 2 +- indra/newview/lldonotdisturbnotificationstorage.h | 5 +++-- indra/newview/llfeaturemanager.cpp | 2 +- indra/newview/llfeaturemanager.h | 5 +++-- indra/newview/llpersistentnotificationstorage.cpp | 1 + indra/newview/llpersistentnotificationstorage.h | 6 +++--- indra/newview/llstartup.cpp | 4 ++-- indra/newview/llviewerwindow.cpp | 2 -- indra/newview/llvocache.cpp | 5 +++-- indra/newview/llvocache.h | 9 ++++----- indra/newview/llvoiceclient.cpp | 3 ++- indra/newview/llvoiceclient.h | 7 ++++--- 13 files changed, 29 insertions(+), 28 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 84cd326f06..1874743644 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1243,7 +1243,7 @@ bool LLAppViewer::init() // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. LLVoiceChannel::initClass(); - LLVoiceClient::getInstance()->init(gServicePump); + LLVoiceClient::initParamSingleton(gServicePump); LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); joystick = LLViewerJoystick::getInstance(); @@ -4123,7 +4123,7 @@ bool LLAppViewer::initCache() mPurgeCache = false; BOOL read_only = mSecondInstance ? TRUE : FALSE; LLAppViewer::getTextureCache()->setReadOnly(read_only) ; - LLVOCache::getInstance()->setReadOnly(read_only); + LLVOCache::initParamSingleton(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion(), read_only); bool texture_cache_mismatch = false; if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) @@ -4195,8 +4195,6 @@ bool LLAppViewer::initCache() S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); texture_cache_size -= extra; - LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()) ; - LLSplashScreen::update(LLTrans::getString("StartupInitializingVFS")); // Init the VFS diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 7d2712eec7..cb5f9c8a2c 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -48,7 +48,6 @@ const char * LLDoNotDisturbNotificationStorage::offerName = "UserGiveItem"; LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) { - } LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() @@ -74,6 +73,7 @@ LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() { nameToPayloadParameterMap[toastName] = "SESSION_ID"; nameToPayloadParameterMap[offerName] = "object_id"; + initialize(); } LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage() diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index e6cb7835e3..c6f0bf1ab5 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -45,7 +45,7 @@ public: BOOL tick(); }; -class LLDoNotDisturbNotificationStorage : public LLSingleton, public LLNotificationStorage +class LLDoNotDisturbNotificationStorage : public LLParamSingleton, public LLNotificationStorage { LLSINGLETON(LLDoNotDisturbNotificationStorage); ~LLDoNotDisturbNotificationStorage(); @@ -55,7 +55,6 @@ public: static const char * toastName; static const char * offerName; - void initialize(); bool getDirty(); void resetDirty(); void saveNotifications(); @@ -66,6 +65,8 @@ public: protected: private: + void initialize(); + bool mDirty; LLDoNotDisturbNotificationStorageTimer mTimer; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 8d07035b97..aa9cba0c18 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -522,7 +522,7 @@ void LLFeatureManager::cleanupFeatureTables() mMaskList.clear(); } -void LLFeatureManager::init() +void LLFeatureManager::initSingleton() { // load the tables loadFeatureTables(); diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index f77861a1a7..42a226cd18 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -100,9 +100,10 @@ class LLFeatureManager : public LLFeatureList, public LLSingleton, public LLNotificationStorage +class LLPersistentNotificationStorage : public LLParamSingleton, public LLNotificationStorage { LLSINGLETON(LLPersistentNotificationStorage); ~LLPersistentNotificationStorage(); @@ -53,11 +53,11 @@ public: void saveNotifications(); void loadNotifications(); - void initialize(); - protected: private: + void initialize(); + bool onPersistentChannelChanged(const LLSD& payload); bool mLoaded; }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index e4cabbaddd..d7b8080efd 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -895,8 +895,8 @@ bool idle_startup() LLFile::mkdir(gDirUtilp->getLindenUserDir()); // As soon as directories are ready initialize notification storages - LLPersistentNotificationStorage::getInstance()->initialize(); - LLDoNotDisturbNotificationStorage::getInstance()->initialize(); + LLPersistentNotificationStorage::initParamSingleton(); + LLDoNotDisturbNotificationStorage::initParamSingleton(); // Set PerAccountSettingsFile to the default value. gSavedSettings.setString("PerAccountSettingsFile", diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b8960d7604..cde2128b99 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1796,8 +1796,6 @@ LLViewerWindow::LLViewerWindow(const Params& p) // LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL; - LLFeatureManager::getInstance()->init(); - // Initialize OpenGL Renderer if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || !gGLManager.mHasVertexBufferObject) diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index fb28d9bdb5..0e6511f6b5 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1045,14 +1045,15 @@ const char* object_cache_dirname = "objectcache"; const char* header_filename = "object.cache"; -LLVOCache::LLVOCache(): +LLVOCache::LLVOCache(ELLPath location, U32 size, U32 cache_version, bool read_only) : mInitialized(false), - mReadOnly(true), + mReadOnly(read_only), mNumEntries(0), mCacheSize(1) { mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); mLocalAPRFilePoolp = new LLVolatileAPRPool() ; + initCache(location, size, cache_version); } LLVOCache::~LLVOCache() diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 594d38249b..41b5246480 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -221,9 +221,9 @@ private: // //Note: LLVOCache is not thread-safe // -class LLVOCache : public LLSingleton +class LLVOCache : public LLParamSingleton { - LLSINGLETON(LLVOCache); + LLSINGLETON(LLVOCache, ELLPath location, U32 size, U32 cache_version, bool read_only); ~LLVOCache() ; private: @@ -259,19 +259,18 @@ private: typedef std::map handle_entry_map_t; public: - void initCache(ELLPath location, U32 size, U32 cache_version) ; void removeCache(ELLPath location, bool started = false) ; void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled); void removeEntry(U64 handle) ; - void setReadOnly(bool read_only) {mReadOnly = read_only;} - U32 getCacheEntries() { return mNumEntries; } U32 getCacheEntriesMax() { return mCacheSize; } private: + void initCache(ELLPath location, U32 size, U32 cache_version); + void setDirNames(ELLPath location); // determine the cache filename for the region from the region handle void getObjectCacheFilename(U64 handle, std::string& filename); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 5c107cc10b..d8c8cb0461 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -116,7 +116,7 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv /////////////////////////////////////////////////////////////////////////////////////////////// -LLVoiceClient::LLVoiceClient() +LLVoiceClient::LLVoiceClient(LLPumpIO *pump) : mVoiceModule(NULL), m_servicePump(NULL), @@ -133,6 +133,7 @@ LLVoiceClient::LLVoiceClient() mDisableMic(false) { updateSettings(); + init(pump); } //--------------------------------------------------- diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 758e9cecd7..f95b853c31 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -310,9 +310,9 @@ public: }; -class LLVoiceClient: public LLSingleton +class LLVoiceClient: public LLParamSingleton { - LLSINGLETON(LLVoiceClient); + LLSINGLETON(LLVoiceClient, LLPumpIO *pump); LOG_CLASS(LLVoiceClient); ~LLVoiceClient(); @@ -320,7 +320,6 @@ public: typedef boost::signals2::signal micro_changed_signal_t; micro_changed_signal_t mMicroChangedSignal; - void init(LLPumpIO *pump); // Call this once at application startup (creates connector) void terminate(); // Call this to clean up during shutdown const LLVoiceVersionInfo getVersion(); @@ -472,6 +471,8 @@ public: // Returns NULL if voice effects are not supported, or not enabled. LLVoiceEffectInterface* getVoiceEffectInterface() const; //@} +private: + void init(LLPumpIO *pump); protected: LLVoiceModuleInterface* mVoiceModule; -- cgit v1.3 From a8bc48b334428ab0d809c93d3d70b8a84df6723e Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 4 Sep 2019 17:30:50 +0300 Subject: SL-11866 [D493] Some startup elements can be executed twice, added protections --- indra/newview/llstartup.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index d7b8080efd..5e9ad1cbce 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -806,7 +806,11 @@ bool idle_startup() gLoginMenuBarView->setEnabled( TRUE ); show_debug_menus(); - LLConversationLog::initParamSingleton(); + if (!LLConversationLog::instanceExists()) + { + // Check existance since this part can be reached twice if login fails + LLConversationLog::initParamSingleton(); + } // Hide the splash screen LLSplashScreen::hide(); @@ -895,8 +899,13 @@ bool idle_startup() LLFile::mkdir(gDirUtilp->getLindenUserDir()); // As soon as directories are ready initialize notification storages - LLPersistentNotificationStorage::initParamSingleton(); - LLDoNotDisturbNotificationStorage::initParamSingleton(); + if (!LLPersistentNotificationStorage::instanceExists()) + { + // check existance since this part of code can be reached + // twice due to login failures + LLPersistentNotificationStorage::initParamSingleton(); + LLDoNotDisturbNotificationStorage::initParamSingleton(); + } // Set PerAccountSettingsFile to the default value. gSavedSettings.setString("PerAccountSettingsFile", -- cgit v1.3 From 5ce0d6268b4750fb376c293d566736052185f638 Mon Sep 17 00:00:00 2001 From: maxim_productengine Date: Thu, 10 Oct 2019 16:35:11 +0300 Subject: SL-12093 FIXED [ordered shutdown] conversation.log erased at log in when all logs are set to be saved --- indra/newview/llstartup.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5e9ad1cbce..6cbd83d656 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -806,12 +806,6 @@ bool idle_startup() gLoginMenuBarView->setEnabled( TRUE ); show_debug_menus(); - if (!LLConversationLog::instanceExists()) - { - // Check existance since this part can be reached twice if login fails - LLConversationLog::initParamSingleton(); - } - // Hide the splash screen LLSplashScreen::hide(); // Push our window frontmost @@ -948,6 +942,12 @@ bool idle_startup() LLFile::mkdir(gDirUtilp->getChatLogsDir()); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); + //Initialize conversation log only when chat log directories are ready + if (!LLConversationLog::instanceExists()) + { + // Check existance since this part can be reached twice if login fails + LLConversationLog::initParamSingleton(); + } //good a place as any to create user windlight directories std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", "")); -- cgit v1.3 From bd42fd13b038dea5bddf06ed8da7b51d08b38bae Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 14 Oct 2019 20:49:16 +0300 Subject: SL-11719 Fixed init of conversation log --- indra/newview/llconversationlog.cpp | 24 ++++++++++++++---------- indra/newview/llconversationlog.h | 8 +++++++- indra/newview/llstartup.cpp | 12 ++++++------ 3 files changed, 27 insertions(+), 17 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 9ccf9b98f7..f7c61efce0 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -189,16 +189,6 @@ LLConversationLog::LLConversationLog() : mAvatarNameCacheConnection(), mLoggingEnabled(false) { - if(gSavedPerAccountSettings.controlExists("KeepConversationLogTranscripts")) - { - LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get(); - S32 log_mode = keep_log_ctrlp->getValue(); - keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - if (log_mode > 0) - { - enableLogging(log_mode); - } - } } void LLConversationLog::enableLogging(S32 log_mode) @@ -443,6 +433,20 @@ bool LLConversationLog::moveLog(const std::string &originDirectory, const std::s return true; } +void LLConversationLog::initLoggingState() +{ + if (gSavedPerAccountSettings.controlExists("KeepConversationLogTranscripts")) + { + LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get(); + S32 log_mode = keep_log_ctrlp->getValue(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + if (log_mode > 0) + { + enableLogging(log_mode); + } + } +} + std::string LLConversationLog::getFileName() { std::string filename = "conversation"; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index f241276abb..46e46a3278 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -107,7 +107,7 @@ private: * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. */ -class LLConversationLog : public LLParamSingleton, LLIMSessionObserver +class LLConversationLog : public LLSingleton, LLIMSessionObserver { LLSINGLETON(LLConversationLog); public: @@ -147,6 +147,12 @@ public: bool getIsLoggingEnabled() { return mLoggingEnabled; } bool isLogEmpty() { return mConversations.empty(); } + /** + * inits connection to per account settings, + * loads saved file and inits enabled state + */ + void initLoggingState(); + /** * constructs file name in which conversations log will be saved * file name is conversation.log diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6cbd83d656..a861def704 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -942,12 +942,6 @@ bool idle_startup() LLFile::mkdir(gDirUtilp->getChatLogsDir()); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); - //Initialize conversation log only when chat log directories are ready - if (!LLConversationLog::instanceExists()) - { - // Check existance since this part can be reached twice if login fails - LLConversationLog::initParamSingleton(); - } //good a place as any to create user windlight directories std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", "")); @@ -1298,6 +1292,12 @@ bool idle_startup() LLStartUp::initExperiences(); display_startup(); + + // If logging should be enebled, turns it on and loads history from disk + // Note: does not happen on init of singleton because preferences can use + // this instance without logging in + LLConversationLog::getInstance()->initLoggingState(); + LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); return FALSE; -- cgit v1.3 From 19caca91e98e41187f76c9925c31b8fba33c2902 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 7 Jan 2020 00:52:04 +0200 Subject: SL-12486 Better data deletion --- indra/newview/llappviewer.cpp | 15 +- indra/newview/llappviewer.h | 4 +- indra/newview/llfloaterforgetuser.cpp | 231 ++++++++++++++++----- indra/newview/llfloaterforgetuser.h | 9 +- indra/newview/llsecapi.h | 4 + indra/newview/llsechandler_basic.cpp | 13 ++ indra/newview/llsechandler_basic.h | 4 + indra/newview/llstartup.cpp | 9 + indra/newview/llstartup.h | 1 + .../newview/skins/default/xui/en/notifications.xml | 12 ++ 10 files changed, 245 insertions(+), 57 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index bbb726ddb0..b232a8c3bb 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -671,7 +671,8 @@ LLAppViewer::LLAppViewer() mReportedCrash(false), mNumSessions(0), mPurgeCache(false), - mPurgeOnExit(false), + mPurgeCacheOnExit(false), + mPurgeUserDataOnExit(false), mSecondInstance(false), mSavedFinalSnapshot(false), mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. @@ -1949,7 +1950,7 @@ bool LLAppViewer::cleanup() LLConversationLog::instance().cache(); } - if (mPurgeOnExit) + if (mPurgeCacheOnExit) { LL_INFOS() << "Purging all cache files on exit" << LL_ENDL; gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); @@ -1990,6 +1991,14 @@ bool LLAppViewer::cleanup() } } + if (mPurgeUserDataOnExit) + { + // Ideally we should not save anything from this session since it is going to be purged now, + // but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code + std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId(); + gDirUtilp->deleteDirAndContents(user_path); + } + // Delete workers first // shotdown all worker threads before deleting them in case of co-dependencies mAppCoreHttp.requestStop(); @@ -4461,7 +4470,7 @@ void LLAppViewer::badNetworkHandler() // Flush all of our caches on exit in the case of disconnect due to // invalid packets. - mPurgeOnExit = TRUE; + mPurgeCacheOnExit = TRUE; std::ostringstream message; message << diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 788fe6a19b..1298ba51e2 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -190,6 +190,7 @@ public: void addOnIdleCallback(const boost::function& cb); // add a callback to fire (once) when idle + void purgeUserDataOnExit() { mPurgeUserDataOnExit = true; } void purgeCache(); // Clear the local cache. void purgeCacheImmediate(); //clear local cache immediately. S32 updateTextureThreads(F32 max_time); @@ -281,7 +282,8 @@ private: std::string mSerialNumber; bool mPurgeCache; - bool mPurgeOnExit; + bool mPurgeCacheOnExit; + bool mPurgeUserDataOnExit; LLViewerJoystick* joystick; bool mSavedFinalSnapshot; diff --git a/indra/newview/llfloaterforgetuser.cpp b/indra/newview/llfloaterforgetuser.cpp index 363951041a..6271ccfa18 100644 --- a/indra/newview/llfloaterforgetuser.cpp +++ b/indra/newview/llfloaterforgetuser.cpp @@ -29,11 +29,15 @@ #include "llfloaterforgetuser.h" +#include "llappviewer.h" #include "llcheckboxctrl.h" #include "llfavoritesbar.h" +#include "llnotificationsutil.h" #include "llpanellogin.h" // for helper function getUserName() and to repopulate list if nessesary #include "llscrolllistctrl.h" #include "llsecapi.h" +#include "llstartup.h" +#include "llviewercontrol.h" #include "llviewernetwork.h" @@ -54,55 +58,65 @@ LLFloaterForgetUser::~LLFloaterForgetUser() BOOL LLFloaterForgetUser::postBuild() { - // Note, storage works per grid, whatever is selected currently in login screen or logged in. - // Since login screen can change grid, store the value. - mGrid = LLGridManager::getInstance()->getGrid(); + mScrollList = getChild("user_list"); - LLScrollListCtrl *scroll_list = getChild("user_list"); - if (gSecAPIHandler->hasCredentialMap("login_list", mGrid)) - { - LLSecAPIHandler::credential_map_t credencials; - gSecAPIHandler->loadCredentialMap("login_list", mGrid, credencials); - LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin(); - LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end(); - while (cr_iter != cr_end) + bool show_grid_marks = gSavedSettings.getBOOL("ForceShowGrid"); + show_grid_marks |= !LLGridManager::getInstance()->isInProductionGrid(); + + std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); + + if (!show_grid_marks) + { + // Figure out if there are records for more than one grid in storage + for (std::map::iterator grid_iter = known_grids.begin(); + grid_iter != known_grids.end(); + grid_iter++) { - if (cr_iter->second.notNull()) // basic safety + if (!grid_iter->first.empty() + && grid_iter->first != MAINGRID) // a workaround since 'mIsInProductionGrid' might not be set { - LLScrollListItem::Params item_params; - item_params.value(cr_iter->first); - item_params.columns.add() - .value(LLPanelLogin::getUserName(cr_iter->second)) - .column("user") - .font(LLFontGL::getFontSansSerifSmall()); - scroll_list->addRow(item_params, ADD_BOTTOM); + if (!gSecAPIHandler->emptyCredentialMap("login_list", grid_iter->first)) + { + show_grid_marks = true; + break; + } + + // "Legacy" viewer support + LLPointer cred = gSecAPIHandler->loadCredential(grid_iter->first); + if (cred.notNull()) + { + const LLSD &ident = cred->getIdentifier(); + if (ident.isMap() && ident.has("type")) + { + show_grid_marks = true; + break; + } + } } - cr_iter++; } - scroll_list->selectFirstItem(); + } + + if (!show_grid_marks) + { + // just load maingrid + loadGridToList(MAINGRID, false); } else { - LLPointer cred = gSecAPIHandler->loadCredential(mGrid); - if (cred.notNull()) + for (std::map::iterator grid_iter = known_grids.begin(); + grid_iter != known_grids.end(); + grid_iter++) { - const LLSD &ident = cred->getIdentifier(); - if (ident.isMap() && ident.has("type")) + if (!grid_iter->first.empty()) { - LLScrollListItem::Params item_params; - item_params.value(cred->userID()); - item_params.columns.add() - .value(LLPanelLogin::getUserName(cred)) - .column("user") - .font(LLFontGL::getFontSansSerifSmall()); - scroll_list->addRow(item_params, ADD_BOTTOM); - scroll_list->selectFirstItem(); + loadGridToList(grid_iter->first, true); } } } - bool enable_button = scroll_list->getFirstSelectedIndex() != -1; + mScrollList->selectFirstItem(); + bool enable_button = mScrollList->getFirstSelectedIndex() != -1; LLCheckBoxCtrl *chk_box = getChild("delete_data"); chk_box->setEnabled(enable_button); chk_box->set(FALSE); @@ -117,43 +131,156 @@ void LLFloaterForgetUser::onForgetClicked() { mLoginPanelDirty = true; LLScrollListCtrl *scroll_list = getChild("user_list"); - std::string user_key = scroll_list->getSelectedValue(); + LLCheckBoxCtrl *chk_box = getChild("delete_data"); + BOOL delete_data = chk_box->getValue(); + LLSD user_data = scroll_list->getSelectedValue(); + const std::string user_id = user_data["user_id"]; + const std::string grid = user_data["grid"]; + const std::string user_name = user_data["label"]; // for favorites - // remove creds - gSecAPIHandler->removeFromCredentialMap("login_list", mGrid, user_key); + if (delete_data && user_id == LLStartUp::getUserId() && grid == LLGridManager::getInstance()->getGrid()) + { + // we can't delete data for user that is currently logged in + LLNotificationsUtil::add("LoginCantRemoveCurUsername", LLSD(), LLSD(), boost::bind(onConfirmLogout, _1, _2, user_name)); + return; + } + + // key is used for name of user's folder and in credencials + // user_name is edentical to favorite's username + forgetUser(user_id, user_name, grid, delete_data); - LLPointer cred = gSecAPIHandler->loadCredential(mGrid); - if (cred.notNull() && cred->userID() == user_key) + // Update UI + scroll_list->deleteSelectedItems(); + scroll_list->selectFirstItem(); + if (scroll_list->getFirstSelectedIndex() == -1) + { + LLButton *button = getChild("forget"); + button->setEnabled(false); + chk_box->setEnabled(false); + } +} + +//static +void LLFloaterForgetUser::forgetUser(const std::string &userid, const std::string &fav_id, const std::string &grid, bool delete_data) +{ + // Remove creds + gSecAPIHandler->removeFromCredentialMap("login_list", grid, userid); + + LLPointer cred = gSecAPIHandler->loadCredential(grid); + if (cred.notNull() && cred->userID() == userid) { gSecAPIHandler->deleteCredential(cred); } // Clean data - LLCheckBoxCtrl *chk_box = getChild("delete_data"); - BOOL delete_data = chk_box->getValue(); if (delete_data) { - // key is edentical to one we use for name of user's folder - std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + user_key; + std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + userid; gDirUtilp->deleteDirAndContents(user_path); - // Clean favorites, label is edentical to username - LLFavoritesOrderStorage::removeFavoritesRecordOfUser(scroll_list->getSelectedItemLabel(), mGrid); + // Clean favorites + LLFavoritesOrderStorage::removeFavoritesRecordOfUser(fav_id, grid); // Note: we do not clean user-related files from cache because there are id dependent (inventory) // files and cache has separate cleaning mechanism either way. // Also this only cleans user from current grid, not all of them. } +} +// static +bool LLFloaterForgetUser::onConfirmLogout(const LLSD& notification, const LLSD& response, const std::string &fav_id) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + // Remove creds + gSecAPIHandler->removeFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), LLStartUp::getUserId()); - // Update UI - scroll_list->deleteSelectedItems(); - scroll_list->selectFirstItem(); - if (scroll_list->getFirstSelectedIndex() == -1) + LLPointer cred = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid()); + if (cred.notNull() && cred->userID() == LLStartUp::getUserId()) + { + gSecAPIHandler->deleteCredential(cred); + } + + // Clean favorites + LLFavoritesOrderStorage::removeFavoritesRecordOfUser(fav_id, LLGridManager::getInstance()->getGrid()); + + // mark data for removal + LLAppViewer::instance()->purgeUserDataOnExit(); + LLAppViewer::instance()->requestQuit(); + } + return false; +} + +void LLFloaterForgetUser::loadGridToList(const std::string &grid, bool show_grid_name) +{ + std::string grid_label; + if (show_grid_name) { - LLButton *button = getChild("forget"); - button->setEnabled(false); - chk_box->setEnabled(false); + grid_label = LLGridManager::getInstance()->getGridId(grid); //login id (shortened label) + } + if (gSecAPIHandler->hasCredentialMap("login_list", grid)) + { + LLSecAPIHandler::credential_map_t credencials; + gSecAPIHandler->loadCredentialMap("login_list", grid, credencials); + + LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin(); + LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end(); + while (cr_iter != cr_end) + { + if (cr_iter->second.notNull()) // basic safety + { + std::string user_label = LLPanelLogin::getUserName(cr_iter->second); + LLSD user_data; + user_data["user_id"] = cr_iter->first; + user_data["label"] = user_label; + user_data["grid"] = grid; + + if (show_grid_name) + { + user_label += " (" + grid_label + ")"; + } + + LLScrollListItem::Params item_params; + item_params.value(user_data); + item_params.columns.add() + .value(user_label) + .column("user") + .font(LLFontGL::getFontSansSerifSmall()); + mScrollList->addRow(item_params, ADD_BOTTOM); + } + cr_iter++; + } + } + else + { + // "Legacy" viewer support + LLPointer cred = gSecAPIHandler->loadCredential(grid); + if (cred.notNull()) + { + const LLSD &ident = cred->getIdentifier(); + if (ident.isMap() && ident.has("type")) + { + std::string user_label = LLPanelLogin::getUserName(cred); + LLSD user_data; + user_data["user_id"] = cred->userID(); + user_data["label"] = user_label; + user_data["grid"] = grid; + + if (show_grid_name) + { + user_label += " (" + grid_label + ")"; + } + + LLScrollListItem::Params item_params; + item_params.value(user_data); + item_params.columns.add() + .value(user_label) + .column("user") + .font(LLFontGL::getFontSansSerifSmall()); + mScrollList->addRow(item_params, ADD_BOTTOM); + } + } } } diff --git a/indra/newview/llfloaterforgetuser.h b/indra/newview/llfloaterforgetuser.h index 119aece2d1..0ab47d3d69 100644 --- a/indra/newview/llfloaterforgetuser.h +++ b/indra/newview/llfloaterforgetuser.h @@ -29,6 +29,8 @@ #include "llfloater.h" +class LLScrollListCtrl; + class LLFloaterForgetUser : public LLFloater { public: @@ -37,10 +39,15 @@ public: BOOL postBuild(); void onForgetClicked(); + static void forgetUser(const std::string &userid, const std::string &fav_id, const std::string &grid, bool delete_data); private: + static bool onConfirmLogout(const LLSD& notification, const LLSD& response, const std::string &favorites_id); + void loadGridToList(const std::string &grid, bool show_grid_name); + + LLScrollListCtrl *mScrollList; + bool mLoginPanelDirty; - std::string mGrid; }; #endif diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index c0f0a367c7..5cde0d549e 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -491,6 +491,10 @@ public: virtual bool hasCredentialMap(const std::string& storage, const std::string& grid)=0; + // returns true im map is empty or does not exist + virtual bool emptyCredentialMap(const std::string& storage, + const std::string& grid)=0; + // load map of credentials from specific storage typedef std::map > credential_map_t; virtual void loadCredentialMap(const std::string& storage, diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index a8bb54a90e..2932ae45a3 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1664,6 +1664,19 @@ bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const st return credential.isMap(); } +// returns true if map is empty or does not exist +bool LLSecAPIBasicHandler::emptyCredentialMap(const std::string& storage, const std::string& grid) +{ + if (storage == DEFAULT_CREDENTIAL_STORAGE) + { + LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL; + } + + LLSD credential = getProtectedData(storage, grid); + + return !credential.isMap() || credential.emptyMap(); +} + // Load map of credentials from specified credential store, given the grid void LLSecAPIBasicHandler::loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map) { diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h index 426b5d392a..0bc7f5230f 100644 --- a/indra/newview/llsechandler_basic.h +++ b/indra/newview/llsechandler_basic.h @@ -293,6 +293,10 @@ public: virtual bool hasCredentialMap(const std::string& storage, const std::string& grid); + // returns true if map is empty or does not exist + virtual bool emptyCredentialMap(const std::string& storage, + const std::string& grid); + // load map of credentials from specific storage virtual void loadCredentialMap(const std::string& storage, const std::string& grid, diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 08012686f9..684d3bd421 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2715,6 +2715,15 @@ std::string& LLStartUp::getInitialOutfitName() return sInitialOutfit; } +std::string LLStartUp::getUserId() +{ + if (gUserCredential.isNull()) + { + return ""; + } + return gUserCredential->userID(); +} + // Loads a bitmap to display during load void init_start_screen(S32 location_id) { diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index db37207022..5ce74b8fae 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -115,6 +115,7 @@ public: static void saveInitialOutfit(); static std::string& getInitialOutfitName(); + static std::string getUserId(); static bool dispatchURL(); // if we have a SLURL or sim string ("Ahern/123/45") that started diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 70f3139488..d99f5fa7d9 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3558,6 +3558,18 @@ If this is your first time using [SECOND_LIFE], you will need to create an accou Already remembered user can be forgotten from Me > Preferences > Advanced > Remembered Usernames. + + confirm +Forgetting the logged-in user requires you to log out. + + +