From a0a4a0736d93e0ab4f397281e38bf21f2f2f1425 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 4 Feb 2014 13:57:10 -0800 Subject: MAINT-3675 NUI:Login Screen - Allow login call to be made from web --- indra/newview/llpanellogin.cpp | 98 +++++++++++++++++++++++++++++++++++++++++- indra/newview/llpanellogin.h | 1 + 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 911ecaad9d..60208c92b0 100755 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -26,6 +26,8 @@ #include "llviewerprecompiledheaders.h" +#include + #include "llpanellogin.h" #include "lllayoutstack.h" @@ -97,6 +99,87 @@ public: } }; +class LLLoginLocationAutoHandler : public LLCommandHandler +{ +public: + // don't allow from external browsers + LLLoginLocationAutoHandler() : LLCommandHandler("location_login", UNTRUSTED_BLOCK) { } + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + { + if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) + { + if ( tokens.size() == 0 || tokens.size() > 4 ) + return false; + + // unescape is important - uris with spaces are escaped in this code path + // (e.g. space -> %20) and the code to log into a region doesn't support that. + const std::string region = LLURI::unescape( tokens[0].asString() ); + + // just region name as payload + if ( tokens.size() == 1 ) + { + // region name only - slurl will end up as center of region + LLSLURL slurl(region); + LLPanelLogin::autologinToLocation(slurl); + } + else + // region name and x coord as payload + if ( tokens.size() == 2 ) + { + // invalid to only specify region and x coordinate + // slurl code will revert to same as region only, so do this anyway + LLSLURL slurl(region); + LLPanelLogin::autologinToLocation(slurl); + } + else + // region name and x/y coord as payload + if ( tokens.size() == 3 ) + { + // region and x/y specified - default z to 0 + F32 xpos; + std::istringstream codec(tokens[1].asString()); + codec >> xpos; + + F32 ypos; + codec.clear(); + codec.str(tokens[2].asString()); + codec >> ypos; + + const LLVector3 location(xpos, ypos, 0.0f); + LLSLURL slurl(region, location); + + LLPanelLogin::autologinToLocation(slurl); + } + else + // region name and x/y/z coord as payload + if ( tokens.size() == 4 ) + { + // region and x/y/z specified - ok + F32 xpos; + std::istringstream codec(tokens[1].asString()); + codec >> xpos; + + F32 ypos; + codec.clear(); + codec.str(tokens[2].asString()); + codec >> ypos; + + F32 zpos; + codec.clear(); + codec.str(tokens[3].asString()); + codec >> zpos; + + const LLVector3 location(xpos, ypos, zpos); + LLSLURL slurl(region, location); + + LLPanelLogin::autologinToLocation(slurl); + }; + } + return true; + } +}; +LLLoginLocationAutoHandler gLoginLocationAutoHandler; + //--------------------------------------------------------------------------- // Public methods //--------------------------------------------------------------------------- @@ -714,6 +797,18 @@ void LLPanelLogin::setLocation(const LLSLURL& slurl) LLStartUp::setStartSLURL(slurl); // calls onUpdateStartSLURL, above } +void LLPanelLogin::autologinToLocation(const LLSLURL& slurl) +{ + LL_DEBUGS("AppInit")<<"automatically logging into Location "<onClickConnect(unused_paramter); + } +} + // static void LLPanelLogin::closePanel() { @@ -786,7 +881,8 @@ void LLPanelLogin::loadLoginPage() if (web_browser->getCurrentNavUrl() != login_uri.asString()) { LL_DEBUGS("AppInit") << "loading: " << login_uri << LL_ENDL; - web_browser->navigateTo( login_uri.asString(), "text/html" ); + //web_browser->navigateTo( login_uri.asString(), "text/html" ); + web_browser->navigateTo("http://127.0.0.1:8000/login.html"); } } diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index c71cfc3783..a614062ccd 100755 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -67,6 +67,7 @@ public: static BOOL areCredentialFieldsDirty(); static void setLocation(const LLSLURL& slurl); + static void autologinToLocation(const LLSLURL& slurl); /// Call when preferences that control visibility may have changed static void updateLocationSelectorsVisibility(); -- cgit v1.2.3 From 385fad27853ed5c5bf37dfe868a9d3eb94e6be10 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 4 Feb 2014 13:58:29 -0800 Subject: Remove debugging code that reset page URL --- indra/newview/llpanellogin.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 60208c92b0..557c67f2d7 100755 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -881,8 +881,7 @@ void LLPanelLogin::loadLoginPage() if (web_browser->getCurrentNavUrl() != login_uri.asString()) { LL_DEBUGS("AppInit") << "loading: " << login_uri << LL_ENDL; - //web_browser->navigateTo( login_uri.asString(), "text/html" ); - web_browser->navigateTo("http://127.0.0.1:8000/login.html"); + web_browser->navigateTo( login_uri.asString(), "text/html" ); } } -- cgit v1.2.3 From cac7a46a5b0b762ac97ffe53f6c0d21a3e90d28f Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Wed, 5 Feb 2014 14:11:37 -0800 Subject: Fix from https://bitbucket.org/oz_linden/viewer-macsignfix via Oz to deal with Mac code signing issues. --- indra/newview/viewer_manifest.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 9a617c2a13..96b4c7268c 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -38,7 +38,7 @@ viewer_dir = os.path.dirname(__file__) # Put it FIRST because some of our build hosts have an ancient install of # indra.util.llmanifest under their system Python! sys.path.insert(0, os.path.join(viewer_dir, os.pardir, "lib", "python")) -from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors, CHANNEL_VENDOR_BASE, RELEASE_CHANNEL +from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors, CHANNEL_VENDOR_BASE, RELEASE_CHANNEL, ManifestError try: from llbase import llsd except ImportError: @@ -818,11 +818,27 @@ class Darwin_i386_Manifest(ViewerManifest): keychain_pwd = open(keychain_pwd_path).read().rstrip() self.run_command('security unlock-keychain -p "%s" "%s/Library/Keychains/viewer.keychain"' % ( keychain_pwd, home_path ) ) - self.run_command('codesign --verbose --force --keychain "%(home_path)s/Library/Keychains/viewer.keychain" --sign %(identity)r %(bundle)r' % { - 'home_path' : home_path, - 'identity': identity, - 'bundle': self.get_dst_prefix() - }) + signed=False + sign_attempts=3 + sign_retry_wait=15 + while (not signed) and (sign_attempts > 0): + try: + sign_attempts-=1; + self.run_command( + 'codesign --verbose --force --keychain "%(home_path)s/Library/Keychains/viewer.keychain" --sign %(identity)r %(bundle)r' % { + 'home_path' : home_path, + 'identity': identity, + 'bundle': self.get_dst_prefix() + }) + signed=True # if no exception was raised, the codesign worked + except ManifestError, err: + if sign_attempts: + print >> sys.stderr, "codesign failed, waiting %d seconds before retrying" % sign_retry_wait + time.sleep(sign_retry_wait) + sign_retry_wait*=2 + else: + print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" + raise imagename="SecondLife_" + '_'.join(self.args['version']) -- cgit v1.2.3 From b6821ae35a1d47497dbc990c30e8dddc1eb4ff41 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Wed, 12 Feb 2014 11:08:16 -0800 Subject: First pass at FirstLogin login page. --- indra/newview/llpanellogin.cpp | 38 +--- indra/newview/skins/default/textures/textures.xml | 4 + .../textures/windows/first_login_image_left.png | Bin 0 -> 280886 bytes .../textures/windows/first_login_image_right.png | Bin 0 -> 263692 bytes .../default/textures/windows/login_sl_logo.png | Bin 0 -> 28583 bytes indra/newview/skins/default/xui/en/main_view.xml | 3 +- .../skins/default/xui/en/panel_login_first.xml | 249 +++++++++++++++++++++ 7 files changed, 259 insertions(+), 35 deletions(-) create mode 100644 indra/newview/skins/default/textures/windows/first_login_image_left.png create mode 100644 indra/newview/skins/default/textures/windows/first_login_image_right.png create mode 100644 indra/newview/skins/default/textures/windows/login_sl_logo.png create mode 100644 indra/newview/skins/default/xui/en/panel_login_first.xml diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 557c67f2d7..f328ffe1a0 100755 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -78,7 +78,6 @@ #include "llsdserialize.h" -const S32 BLACK_BORDER_HEIGHT = 160; const S32 MAX_PASSWORD = 16; LLPanelLogin *LLPanelLogin::sInstance = NULL; @@ -192,7 +191,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, mCallbackData(cb_data), mListener(new LLPanelLoginListener(this)) { - setBackgroundVisible(FALSE); + setBackgroundVisible(TRUE); setBackgroundOpaque(TRUE); // instance management @@ -207,20 +206,16 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, mPasswordModified = FALSE; LLPanelLogin::sInstance = this; + buildFromFile( "panel_login_first.xml"); LLView* login_holder = gViewerWindow->getLoginPanelHolder(); if (login_holder) { + setOrigin(0,0); + reshape(rect.getWidth(), rect.getHeight()); login_holder->addChild(this); } - // Logo - mLogoImage = LLUI::getUIImage("startup_logo"); - - buildFromFile( "panel_login.xml"); - - reshape(rect.getWidth(), rect.getHeight()); - LLLineEditor* password_edit(getChild("password_edit")); password_edit->setKeystrokeCallback(onPassKey, this); // STEAM-14: When user presses Enter with this field in focus, initiate login @@ -408,31 +403,6 @@ LLPanelLogin::~LLPanelLogin() // virtual void LLPanelLogin::draw() { - gGL.pushMatrix(); - { - F32 image_aspect = 1.333333f; - F32 view_aspect = (F32)getRect().getWidth() / (F32)getRect().getHeight(); - // stretch image to maintain aspect ratio - if (image_aspect > view_aspect) - { - gGL.translatef(-0.5f * (image_aspect / view_aspect - 1.f) * getRect().getWidth(), 0.f, 0.f); - gGL.scalef(image_aspect / view_aspect, 1.f, 1.f); - } - - S32 width = getRect().getWidth(); - S32 height = getRect().getHeight(); - - if (getChild("login_widgets")->getVisible()) - { - // draw a background box in black - gl_rect_2d( 0, height - 264, width, 264, LLColor4::black ); - // draw the bottom part of the background image - // just the blue background to the native client UI - mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight()); - }; - } - gGL.popMatrix(); - LLPanel::draw(); } diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index bb891996c9..4aa668c242 100755 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -577,6 +577,10 @@ with the same filename but different name + + + + diff --git a/indra/newview/skins/default/textures/windows/first_login_image_left.png b/indra/newview/skins/default/textures/windows/first_login_image_left.png new file mode 100644 index 0000000000..b1cb30fe67 Binary files /dev/null and b/indra/newview/skins/default/textures/windows/first_login_image_left.png differ diff --git a/indra/newview/skins/default/textures/windows/first_login_image_right.png b/indra/newview/skins/default/textures/windows/first_login_image_right.png new file mode 100644 index 0000000000..bdd3afdd48 Binary files /dev/null and b/indra/newview/skins/default/textures/windows/first_login_image_right.png differ diff --git a/indra/newview/skins/default/textures/windows/login_sl_logo.png b/indra/newview/skins/default/textures/windows/login_sl_logo.png new file mode 100644 index 0000000000..3bc93ab24d Binary files /dev/null and b/indra/newview/skins/default/textures/windows/login_sl_logo.png differ diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index a87027a113..b1eb3caccb 100755 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -67,7 +67,8 @@ diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml new file mode 100644 index 0000000000..5e257df4fd --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_login_first.xml @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/es/floater_lagmeter.xml b/indra/newview/skins/default/xui/es/floater_lagmeter.xml new file mode 100644 index 0000000000..227689a194 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_lagmeter.xml @@ -0,0 +1,154 @@ + + + + Medidor del lag + + + 360 + + + Lag + + + 90 + + + Cliente + + + 10 + + + 15 + + + Normal, ventana en segundo plano + + + Frames del cliente valorados por debajo de [CLIENT_FRAME_RATE_CRITICAL] + + + Frames del cliente valorados entre [CLIENT_FRAME_RATE_CRITICAL] y [CLIENT_FRAME_RATE_WARNING] + + + Normal + + + Posible causa: distancia de dibujo fijada muy alta + + + Posible causa: imágenes cargándose + + + Posible causa: demasiadas imágenes en la memoria + + + Posible causa: demasiados objetos complejos en la escena + + + Red + + + 10 + + + 5 + + + La conexión deja caer más del [NETWORK_PACKET_LOSS_CRITICAL]% de los paquetes + + + La conexión deja caer [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% de los paquetes + + + Normal + + + 600 + + + 300 + + + El tiempo de conexión -ping- supera los [NETWORK_PING_CRITICAL] ms + + + El tiempo de conexión -ping- es de [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms + + + Quizá una mala conexión o un ancho de banda fijado demasiado alto. + + + Quizá una mala conexión o una aplicación de archivos compartidos. + + + Servidor + + + 20 + + + 30 + + + 20 + + + Frecuencia (framerate) por debajo de [SERVER_FRAME_RATE_CRITICAL] + + + Frecuencia (framerate) entre [SERVER_FRAME_RATE_CRITICAL] y [SERVER_FRAME_RATE_WARNING] + + + Normal + + + Posible causa: demasiados objetos físicos + + + Posible causa: demasiados objetos con script + + + Posible causa: demasiado tráfico en la red + + + Posible causa: demasiada gente moviéndose en la región + + + Posible causa: demasiados cálculos de imáganes + + + Posible causa: carga del simulador muy pesada + + + >> + + + << + + -- cgit v1.2.3 From bc029b770c92f9443a30fee88d3b7a22b971b643 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Tue, 22 Jul 2014 19:38:55 +0300 Subject: MAINT-4036 [CHUIBUG]Long pause on first open of preferences or right-clicking a user in friend list: the changeset 009b02c29a52 has been reverted by request from Oz. --- doc/contributions.txt | 2 - indra/newview/llgiveinventory.cpp | 6 +-- indra/newview/lllogchat.cpp | 108 ++++++++++++++++++-------------------- indra/newview/lllogchat.h | 6 --- 4 files changed, 52 insertions(+), 70 deletions(-) diff --git a/doc/contributions.txt b/doc/contributions.txt index 240bce5719..7e8ab46b1a 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -185,7 +185,6 @@ Ansariel Hiller BUG-3764 STORM-1984 STORM-1979 - MAINT-4036 Aralara Rajal Arare Chantilly CHUIBUG-191 @@ -758,7 +757,6 @@ Kitty Barnett STORM-1905 VWR-24217 STORM-1804 - MAINT-4036 Kolor Fall Komiko Okamoto Korvel Noh diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index b2fc41526e..813d2081ce 100755 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -328,10 +328,8 @@ void LLGiveInventory::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im { // Build a new format username or firstname_lastname for legacy names // to use it for a history log filename. - if (LLLogChat::buildIMP2PLogFilename(to_agent, LLStringUtil::null, full_name)) - { - LLIMModel::instance().logToFile(full_name, LLTrans::getString("SECOND_LIFE"), im_session_id, LLTrans::getString("inventory_item_offered-im")); - } + full_name = LLCacheName::buildUsername(full_name); + LLIMModel::instance().logToFile(full_name, LLTrans::getString("SECOND_LIFE"), im_session_id, LLTrans::getString("inventory_item_offered-im")); } } } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 743bb8973b..06e517a861 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -261,46 +261,6 @@ std::string LLLogChat::cleanFileName(std::string filename) return filename; } -bool LLLogChat::buildIMP2PLogFilename(const LLUUID& idAgent, const std::string& strName, std::string& strFilename) -{ - static LLCachedControl fLegacyFilenames(gSavedSettings, "UseLegacyIMLogNames", true); - - // If we have the name cached then we can simply return the username - LLAvatarName avName; - if (LLAvatarNameCache::get(idAgent, &avName)) - { - if (!fLegacyFilenames) - { - strFilename = avName.getUserName(); - } - else - { - strFilename = LLCacheName::cleanFullName(avName.getLegacyName()); - } - return true; - } - else - { - // Try and get it from the legacy cache if we can - std::string strLegacyName; - if (gCacheName->getFullName(idAgent, strLegacyName)) - strLegacyName = strName; - - if (!fLegacyFilenames) - { - // If we don't have it cached 'strName' *should* be a legacy name (or a complete name) and we can construct a username from that - strFilename = LLCacheName::buildUsername(strName); - return strName != strFilename; // If the assumption above was wrong then the two will match which signals failure - } - else - { - // Strip any possible mention of a username - strFilename = LLCacheName::buildLegacyName(strName); - return (!strFilename.empty()); // Assume success as long as the filename isn't an empty string - } - } -} - std::string LLLogChat::timestamp(bool withdate) { std::string timeStr; @@ -610,6 +570,13 @@ void LLLogChat::findTranscriptFiles(std::string pattern, std::vectoradd(dirname, filename)); + LLFile::close(filep); + continue; + } char buffer[LOG_RECALL_SIZE]; fseek(filep, 0, SEEK_END); // seek to end of file @@ -782,34 +749,59 @@ void LLLogChat::deleteTranscripts() // static bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group) { - std::string strFileName; - if (!is_group) - buildIMP2PLogFilename(avatar_id, LLStringUtil::null, strFileName); - else - gCacheName->getGroupName(avatar_id, strFileName); + std::vector list_of_transcriptions; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); - std::string strFilePath = makeLogFileName(strFileName); - if ( (!strFilePath.empty()) && (LLFile::isfile(strFilePath)) ) + if (list_of_transcriptions.size() > 0) { - return true; + LLAvatarName avatar_name; + LLAvatarNameCache::get(avatar_id, &avatar_name); + std::string avatar_user_name = avatar_name.getAccountName(); + if(!is_group) + { + std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); + BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) + { + if (std::string::npos != transcript_file_name.find(avatar_user_name)) + { + return true; + } + } + } + else + { + std::string file_name; + gCacheName->getGroupName(avatar_id, file_name); + file_name = makeLogFileName(file_name); + BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) + { + if (transcript_file_name == file_name) + { + return true; + } + } + } + } - // If a dated file existed it'll return a valid path; otherwise, it returns the undated unverified path so we do need to check it - strFilePath = oldLogFileName(strFileName); - return (!strFilePath.empty()) && (LLFile::isfile(strFilePath)); + return false; } bool LLLogChat::isNearbyTranscriptExist() { - std::string strFilePath = makeLogFileName("chat"); - if ( (!strFilePath.empty()) && (LLFile::isfile(strFilePath)) ) + std::vector list_of_transcriptions; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); + + std::string file_name; + file_name = makeLogFileName("chat"); + BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) { - return true; + if (transcript_file_name == file_name) + { + return true; + } } - - // If a dated file existed it'll return a valid path; otherwise, it returns the undated unverified path so we do need to check it - strFilePath = oldLogFileName("chat"); - return (!strFilePath.empty()) && (LLFile::isfile(strFilePath)); + return false; } //*TODO mark object's names in a special way so that they will be distinguishable form avatar name diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index d1dbf2d119..ca597599dd 100755 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -92,12 +92,6 @@ public: static std::string timestamp(bool withdate = false); static std::string makeLogFileName(std::string(filename)); - - /** - * Attempts to build the correct IM P2P log filename for the specified agent UUID and agent name - */ - static bool buildIMP2PLogFilename(const LLUUID& idAgent, const std::string& strName, std::string& strFilename); - /** *Add functions to get old and non date stamped file names when needed */ -- cgit v1.2.3 From f69b11691d9911264d42a9c53d407a808591ee7c Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 23 Jul 2014 18:29:18 +0300 Subject: MAINT-4283 FIXED [BEAR] Viewer always crashes when opening "Scene Loading Monitor" if you closed it previously with the X --- indra/newview/llscenemonitor.cpp | 5 +++++ indra/newview/llscenemonitor.h | 1 + 2 files changed, 6 insertions(+) diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 5b37fdf41b..179a73413e 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -709,6 +709,11 @@ void LLSceneMonitorView::onClose(bool app_quitting) setVisible(false); } +void LLSceneMonitorView::onClickCloseBtn(bool app_quitting) +{ + setVisible(false); +} + void LLSceneMonitorView::onVisibilityChange(BOOL visible) { if (!LLGLSLShader::sNoFixedFunction && visible) diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index e9ceb2aa2a..5bde3b5aab 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -116,6 +116,7 @@ public: protected: virtual void onClose(bool app_quitting=false); + virtual void onClickCloseBtn(bool app_quitting=false); }; extern LLSceneMonitorView* gSceneMonitorView; -- cgit v1.2.3 From 03361678a6ca109e4ef479c148d36f6d157e8e5a Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 08:08:20 +0200 Subject: Changed: Facebook floater layout. Changed: Facebook floater size. Changed: Aligned all widgets to an unified layout, keep 10 pixels left/right and so on. Removed: Account tab and moved it into Status tab. --- .../skins/default/xui/en/floater_facebook.xml | 39 +++---- .../default/xui/en/panel_facebook_account.xml | 77 ------------- .../default/xui/en/panel_facebook_friends.xml | 21 ++-- .../skins/default/xui/en/panel_facebook_photo.xml | 116 ++++++++++---------- .../skins/default/xui/en/panel_facebook_place.xml | 120 +++++++++------------ .../skins/default/xui/en/panel_facebook_status.xml | 114 +++++++++++++++----- 6 files changed, 221 insertions(+), 266 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/panel_facebook_account.xml diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml index 4535b9084e..2ea34fb751 100644 --- a/indra/newview/skins/default/xui/en/floater_facebook.xml +++ b/indra/newview/skins/default/xui/en/floater_facebook.xml @@ -2,7 +2,6 @@ - + height="462" + width="272"> - + name="panel_facebook_account"/>--> - Loading... - - diff --git a/indra/newview/skins/default/xui/en/panel_facebook_account.xml b/indra/newview/skins/default/xui/en/panel_facebook_account.xml deleted file mode 100644 index 122cbfb717..0000000000 --- a/indra/newview/skins/default/xui/en/panel_facebook_account.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - Not connected to Facebook. - - - - - - - - [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Learn about posting to Facebook] - - - diff --git a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml index 9d21a3a293..6ec85eb247 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml @@ -1,6 +1,6 @@ @@ -11,15 +11,15 @@ name="facebook_friends_no_connected" value="You're currently not connected to Facebook. Please go to the Account tab to connect and enable this feature." /> + width="272" /> + width="272" /> Not connected to Facebook. diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml index b5b6dee004..22e6598352 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml @@ -1,29 +1,19 @@ - - + width="124"> + width="124"> + top_pad="5" + follows="left|top|rith" + right="-10" + left="10"> - - + width="251"> Refreshing... + + - - + diff --git a/indra/newview/skins/default/xui/en/panel_facebook_place.xml b/indra/newview/skins/default/xui/en/panel_facebook_place.xml index 84c87df523..6a4b5e2b8a 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_place.xml @@ -1,115 +1,96 @@ - - Say something about where you are: - - + - - - - Include overhead view of location - - - + layout="topleft" + height="24" + width="24" + name="map_loading_indicator2" + top_delta="116" + left="126" + visible="true"/> - - diff --git a/indra/newview/skins/default/xui/en/panel_facebook_status.xml b/indra/newview/skins/default/xui/en/panel_facebook_status.xml index 480abec558..fe0f3c9279 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_status.xml @@ -1,50 +1,113 @@ - + + + Not connected to Facebook. + + + + + + + - + length="1" + follows="top|left|right" + left="10" + right="-10" + height="16" + name="account_learn_more_label" + top_pad="5" + type="string"> + [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Learn about posting to Facebook] + + + What's on your mind? - - - - -- cgit v1.2.3 From c885547056e40f80b1f26074782b478b5e10cc93 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 08:09:24 +0200 Subject: Changed: Flickr floater layout. Changed: Flickr floater size. Changed: Aligned all widgets to an unified layout, keep 10 pixels left/right and so on. --- .../skins/default/xui/en/floater_flickr.xml | 23 ++-- .../skins/default/xui/en/panel_flickr_account.xml | 22 ++-- .../skins/default/xui/en/panel_flickr_photo.xml | 145 +++++++++++---------- 3 files changed, 104 insertions(+), 86 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml index 1a9ffd0489..24de3ddd8d 100644 --- a/indra/newview/skins/default/xui/en/floater_flickr.xml +++ b/indra/newview/skins/default/xui/en/floater_flickr.xml @@ -10,11 +10,11 @@ single_instance="true" reuse_instance="true" title="UPLOAD TO FLICKR" - height="622" - width="304"> + height="590" + width="272"> Not connected to Flickr. @@ -28,7 +28,7 @@ follows="top|left" font="SansSerif" height="16" - left="9" + left="10" name="account_name_label" parse_urls="true" type="string"/> @@ -36,12 +36,14 @@ layout="topleft" name="panel_buttons" height="345" - left="9"> + left="0"> - + width="251"> Refreshing... + + - - + -- cgit v1.2.3 From acee1894023aa971aeca92316d01a68553f32904 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 08:09:54 +0200 Subject: Changed: Twitter floater layout. Changed: Twitter floater size. Changed: Aligned all widgets to an unified layout, keep 10 pixels left/right and so on. --- .../skins/default/xui/en/floater_twitter.xml | 34 ++---- .../skins/default/xui/en/panel_twitter_account.xml | 24 ++-- .../skins/default/xui/en/panel_twitter_photo.xml | 124 +++++++++++---------- 3 files changed, 88 insertions(+), 94 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml index aa5bfce2e9..3e1a91e58d 100644 --- a/indra/newview/skins/default/xui/en/floater_twitter.xml +++ b/indra/newview/skins/default/xui/en/floater_twitter.xml @@ -10,21 +10,13 @@ single_instance="true" reuse_instance="true" title="TWITTER" - height="502" - width="304"> - + height="462" + width="272"> - Loading... - - diff --git a/indra/newview/skins/default/xui/en/panel_twitter_account.xml b/indra/newview/skins/default/xui/en/panel_twitter_account.xml index ee4f6396e1..b9049a0bba 100644 --- a/indra/newview/skins/default/xui/en/panel_twitter_account.xml +++ b/indra/newview/skins/default/xui/en/panel_twitter_account.xml @@ -1,6 +1,6 @@ Not connected to Twitter. @@ -28,19 +28,23 @@ follows="top|left" font="SansSerif" height="16" - left="9" + left="10" name="account_name_label" parse_urls="true" type="string"/> + top_pad="3" + left="0"> - + width="251"> Refreshing... + + - - - - -- cgit v1.2.3 From c7de2ac4395e44618094d69e0c5d83482d300838 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 09:06:46 +0200 Subject: Changed: Reflected changes made to the Facebook floater XMLs in code. Fixed: Deprecated llerrs/llwarns/lldebugs/llinfos on the way. --- indra/newview/llfloaterfacebook.cpp | 320 ++++++++++++++++-------------------- indra/newview/llfloaterfacebook.h | 44 ++--- 2 files changed, 160 insertions(+), 204 deletions(-) diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 9e3f917eae..516cf5c15c 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -58,7 +58,6 @@ static LLPanelInjector t_panel_status("llfacebookstatuspa static LLPanelInjector t_panel_photo("llfacebookphotopanel"); static LLPanelInjector t_panel_checkin("llfacebookcheckinpanel"); static LLPanelInjector t_panel_friends("llfacebookfriendspanel"); -static LLPanelInjector t_panel_account("llfacebookaccountpanel"); const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/"; @@ -99,13 +98,29 @@ S32 compute_jpeg_quality(S32 width, S32 height) LLFacebookStatusPanel::LLFacebookStatusPanel() : mMessageTextEditor(NULL), mPostButton(NULL), - mCancelButton(NULL) + mCancelButton(NULL), + mAccountCaptionLabel(NULL), + mAccountNameLabel(NULL), + mPanelButtons(NULL), + mConnectButton(NULL), + mDisconnectButton(NULL) { + mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); + + setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); + mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this)); } BOOL LLFacebookStatusPanel::postBuild() { + mAccountCaptionLabel = getChild("account_caption_label"); + mAccountNameLabel = getChild("account_name_label"); + mPanelButtons = getChild("panel_buttons"); + mConnectButton = getChild("connect_btn"); + mDisconnectButton = getChild("disconnect_btn"); + mMessageTextEditor = getChild("status_message"); mPostButton = getChild("post_status_btn"); mCancelButton = getChild("cancel_status_btn"); @@ -115,6 +130,16 @@ BOOL LLFacebookStatusPanel::postBuild() void LLFacebookStatusPanel::draw() { + LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); + + //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress + bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; + mDisconnectButton->setEnabled(!disconnecting); + + //Disable the 'connect' button when a connection is in progress + bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; + mConnectButton->setEnabled(!connecting); + if (mMessageTextEditor && mPostButton && mCancelButton) { bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); @@ -145,6 +170,19 @@ void LLFacebookStatusPanel::onSend() bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data) { + if(LLFacebookConnect::instance().isConnected()) + { + //In process of disconnecting so leave the layout as is + if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) + { + showConnectedLayout(); + } + } + else + { + showDisconnectedLayout(); + } + switch (data.get("enum").asInteger()) { case LLFacebookConnect::FB_CONNECTED: @@ -169,6 +207,103 @@ void LLFacebookStatusPanel::sendStatus() } } +void LLFacebookStatusPanel::onVisibilityChange(BOOL visible) +{ + if(visible) + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); + + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); + + //Connected + if(LLFacebookConnect::instance().isConnected()) + { + showConnectedLayout(); + } + //Check if connected (show disconnected layout in meantime) + else + { + showDisconnectedLayout(); + } + if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || + (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) + { + LLFacebookConnect::instance().checkConnectionToFacebook(); + } + } + else + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + } +} + +bool LLFacebookStatusPanel::onFacebookConnectInfoChange() +{ + LLSD info = LLFacebookConnect::instance().getInfo(); + std::string clickable_name; + + //Strings of format [http://www.somewebsite.com Click Me] become clickable text + if(info.has("link") && info.has("name")) + { + clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; + } + + mAccountNameLabel->setText(clickable_name); + + return false; +} + +void LLFacebookStatusPanel::showConnectButton() +{ + if(!mConnectButton->getVisible()) + { + mConnectButton->setVisible(TRUE); + mDisconnectButton->setVisible(FALSE); + } +} + +void LLFacebookStatusPanel::hideConnectButton() +{ + if(mConnectButton->getVisible()) + { + mConnectButton->setVisible(FALSE); + mDisconnectButton->setVisible(TRUE); + } +} + +void LLFacebookStatusPanel::showDisconnectedLayout() +{ + mAccountCaptionLabel->setText(getString("facebook_disconnected")); + mAccountNameLabel->setText(std::string("")); + showConnectButton(); +} + +void LLFacebookStatusPanel::showConnectedLayout() +{ + LLFacebookConnect::instance().loadFacebookInfo(); + + mAccountCaptionLabel->setText(getString("facebook_connected")); + hideConnectButton(); +} + +void LLFacebookStatusPanel::onConnect() +{ + LLFacebookConnect::instance().checkConnectionToFacebook(true); + + //Clear only the facebook browser cookies so that the facebook login screen appears + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +} + +void LLFacebookStatusPanel::onDisconnect() +{ + LLFacebookConnect::instance().disconnectFromFacebook(); + + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +} + void LLFacebookStatusPanel::clearAndClose() { mMessageTextEditor->setValue(""); @@ -185,7 +320,6 @@ void LLFacebookStatusPanel::clearAndClose() /////////////////////////// LLFacebookPhotoPanel::LLFacebookPhotoPanel() : -mSnapshotPanel(NULL), mResolutionComboBox(NULL), mRefreshBtn(NULL), mBtnPreview(NULL), @@ -213,7 +347,6 @@ BOOL LLFacebookPhotoPanel::postBuild() { setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2)); - mSnapshotPanel = getChild("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw! mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); @@ -300,16 +433,9 @@ void LLFacebookPhotoPanel::draw() // calc preview offset within the preview rect const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ; const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; + S32 offset_x = thumbnail_rect.mLeft + local_offset_x; + S32 offset_y = thumbnail_rect.mBottom + local_offset_y; - // calc preview offset within the floater rect - // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. - // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. - // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. - S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; - S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; - - mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType()); - gGL.matrixMode(LLRender::MM_MODELVIEW); // Apply floater transparency to the texture unless the floater is focused. F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); @@ -344,7 +470,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(BOOL visible) LLSnapshotLivePreview* preview = getPreviewView(); if(preview) { - lldebugs << "opened, updating snapshot" << llendl; + LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; preview->updateSnapshot(TRUE); } } @@ -477,7 +603,7 @@ void LLFacebookPhotoPanel::updateControls() BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); // *TODO: Separate maximum size for Web images from postcards - lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; + LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; updateResolution(FALSE); } @@ -507,13 +633,13 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update) if (width == 0 || height == 0) { // take resolution from current window size - lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; + LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL; previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); } else { // use the resolution from the selected pre-canned drop-down choice - lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; + LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; previewp->setSize(width, height); } @@ -887,164 +1013,6 @@ bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data) return false; } -/////////////////////////// -//LLFacebookAccountPanel////// -/////////////////////////// - -LLFacebookAccountPanel::LLFacebookAccountPanel() : -mAccountCaptionLabel(NULL), -mAccountNameLabel(NULL), -mPanelButtons(NULL), -mConnectButton(NULL), -mDisconnectButton(NULL) -{ - mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookAccountPanel::onConnect, this)); - mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookAccountPanel::onDisconnect, this)); - - setVisibleCallback(boost::bind(&LLFacebookAccountPanel::onVisibilityChange, this, _2)); -} - -BOOL LLFacebookAccountPanel::postBuild() -{ - mAccountCaptionLabel = getChild("account_caption_label"); - mAccountNameLabel = getChild("account_name_label"); - mPanelButtons = getChild("panel_buttons"); - mConnectButton = getChild("connect_btn"); - mDisconnectButton = getChild("disconnect_btn"); - - return LLPanel::postBuild(); -} - -void LLFacebookAccountPanel::draw() -{ - LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); - - //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress - bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; - mDisconnectButton->setEnabled(!disconnecting); - - //Disable the 'connect' button when a connection is in progress - bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; - mConnectButton->setEnabled(!connecting); - - LLPanel::draw(); -} - -void LLFacebookAccountPanel::onVisibilityChange(BOOL visible) -{ - if(visible) - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookAccountPanel::onFacebookConnectStateChange, this, _1)); - - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookAccountPanel::onFacebookConnectInfoChange, this)); - - //Connected - if(LLFacebookConnect::instance().isConnected()) - { - showConnectedLayout(); - } - //Check if connected (show disconnected layout in meantime) - else - { - showDisconnectedLayout(); - } - if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || - (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) - { - LLFacebookConnect::instance().checkConnectionToFacebook(); - } - } - else - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - } -} - -bool LLFacebookAccountPanel::onFacebookConnectStateChange(const LLSD& data) -{ - if(LLFacebookConnect::instance().isConnected()) - { - //In process of disconnecting so leave the layout as is - if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) - { - showConnectedLayout(); - } - } - else - { - showDisconnectedLayout(); - } - - return false; -} - -bool LLFacebookAccountPanel::onFacebookConnectInfoChange() -{ - LLSD info = LLFacebookConnect::instance().getInfo(); - std::string clickable_name; - - //Strings of format [http://www.somewebsite.com Click Me] become clickable text - if(info.has("link") && info.has("name")) - { - clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; - } - - mAccountNameLabel->setText(clickable_name); - - return false; -} - -void LLFacebookAccountPanel::showConnectButton() -{ - if(!mConnectButton->getVisible()) - { - mConnectButton->setVisible(TRUE); - mDisconnectButton->setVisible(FALSE); - } -} - -void LLFacebookAccountPanel::hideConnectButton() -{ - if(mConnectButton->getVisible()) - { - mConnectButton->setVisible(FALSE); - mDisconnectButton->setVisible(TRUE); - } -} - -void LLFacebookAccountPanel::showDisconnectedLayout() -{ - mAccountCaptionLabel->setText(getString("facebook_disconnected")); - mAccountNameLabel->setText(std::string("")); - showConnectButton(); -} - -void LLFacebookAccountPanel::showConnectedLayout() -{ - LLFacebookConnect::instance().loadFacebookInfo(); - - mAccountCaptionLabel->setText(getString("facebook_connected")); - hideConnectButton(); -} - -void LLFacebookAccountPanel::onConnect() -{ - LLFacebookConnect::instance().checkConnectionToFacebook(true); - - //Clear only the facebook browser cookies so that the facebook login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); -} - -void LLFacebookAccountPanel::onDisconnect() -{ - LLFacebookConnect::instance().disconnectFromFacebook(); - - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); -} - //////////////////////// //LLFloaterFacebook/////// //////////////////////// @@ -1094,7 +1062,7 @@ void LLFloaterFacebook::showPhotoPanel() LLTabContainer* parent = dynamic_cast(mFacebookPhotoPanel->getParent()); if (!parent) { - llwarns << "Cannot find panel container" << llendl; + LL_WARNS() << "Cannot find panel container" << LL_ENDL; return; } diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index 34356412d6..86e3a148b9 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -51,6 +51,22 @@ public: void clearAndClose(); private: + void onVisibilityChange(BOOL new_visibility); + bool onFacebookConnectInfoChange(); + void onConnect(); + void onUseAnotherAccount(); + void onDisconnect(); + + void showConnectButton(); + void hideConnectButton(); + void showDisconnectedLayout(); + void showConnectedLayout(); + + LLTextBox * mAccountCaptionLabel; + LLTextBox * mAccountNameLabel; + LLUICtrl * mPanelButtons; + LLUICtrl * mConnectButton; + LLUICtrl * mDisconnectButton; LLUICtrl* mMessageTextEditor; LLUICtrl* mPostButton; LLUICtrl* mCancelButton; @@ -87,7 +103,6 @@ private: LLHandle mPreviewHandle; - LLUICtrl * mSnapshotPanel; LLUICtrl * mResolutionComboBox; LLUICtrl * mFilterComboBox; LLUICtrl * mRefreshBtn; @@ -147,33 +162,6 @@ private: LLAvatarList* mSuggestedFriends; }; -class LLFacebookAccountPanel : public LLPanel -{ -public: - LLFacebookAccountPanel(); - BOOL postBuild(); - void draw(); - -private: - void onVisibilityChange(BOOL new_visibility); - bool onFacebookConnectStateChange(const LLSD& data); - bool onFacebookConnectInfoChange(); - void onConnect(); - void onUseAnotherAccount(); - void onDisconnect(); - - void showConnectButton(); - void hideConnectButton(); - void showDisconnectedLayout(); - void showConnectedLayout(); - - LLTextBox * mAccountCaptionLabel; - LLTextBox * mAccountNameLabel; - LLUICtrl * mPanelButtons; - LLUICtrl * mConnectButton; - LLUICtrl * mDisconnectButton; -}; - class LLFloaterFacebook : public LLFloater { public: -- cgit v1.2.3 From a34188354d7d54fa3548e8ee0bebcaeaaa2bcbd9 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 09:07:08 +0200 Subject: Changed: Reflected changes made to the Flickr floater XMLs in code. Fixed: Deprecated llerrs/llwarns/lldebugs/llinfos on the way. --- indra/newview/llfloaterflickr.cpp | 23 +++++++---------------- indra/newview/llfloaterflickr.h | 1 - 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 4e6d98ecfa..36afab86b7 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -65,7 +65,6 @@ const std::string FLICKR_MACHINE_TAGS_NAMESPACE = "secondlife"; /////////////////////////// LLFlickrPhotoPanel::LLFlickrPhotoPanel() : -mSnapshotPanel(NULL), mResolutionComboBox(NULL), mRefreshBtn(NULL), mBtnPreview(NULL), @@ -96,7 +95,6 @@ BOOL LLFlickrPhotoPanel::postBuild() { setVisibleCallback(boost::bind(&LLFlickrPhotoPanel::onVisibilityChange, this, _2)); - mSnapshotPanel = getChild("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); mResolutionComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE)); mFilterComboBox = getChild("filters_combobox"); @@ -191,16 +189,9 @@ void LLFlickrPhotoPanel::draw() // calc preview offset within the preview rect const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ; const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; + S32 offset_x = thumbnail_rect.mLeft + local_offset_x; + S32 offset_y = thumbnail_rect.mBottom + local_offset_y; - // calc preview offset within the floater rect - // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. - // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. - // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. - S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; - S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; - - mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType()); - gGL.matrixMode(LLRender::MM_MODELVIEW); // Apply floater transparency to the texture unless the floater is focused. F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); @@ -235,7 +226,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible) LLSnapshotLivePreview* preview = getPreviewView(); if(preview) { - lldebugs << "opened, updating snapshot" << llendl; + LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; preview->updateSnapshot(TRUE); } } @@ -427,7 +418,7 @@ void LLFlickrPhotoPanel::updateControls() BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); // *TODO: Separate maximum size for Web images from postcards - lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; + LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; updateResolution(FALSE); } @@ -457,13 +448,13 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) if (width == 0 || height == 0) { // take resolution from current window size - lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; + LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL; previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); } else { // use the resolution from the selected pre-canned drop-down choice - lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; + LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; previewp->setSize(width, height); } @@ -726,7 +717,7 @@ void LLFloaterFlickr::showPhotoPanel() LLTabContainer* parent = dynamic_cast(mFlickrPhotoPanel->getParent()); if (!parent) { - llwarns << "Cannot find panel container" << llendl; + LL_WARNS() << "Cannot find panel container" << LL_ENDL; return; } diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index ba27c9a3d8..74da3bcea9 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -67,7 +67,6 @@ private: LLHandle mPreviewHandle; - LLUICtrl * mSnapshotPanel; LLUICtrl * mResolutionComboBox; LLUICtrl * mFilterComboBox; LLUICtrl * mRefreshBtn; -- cgit v1.2.3 From 9f9fb34742b80f89d9c8e058d6177947c8f55d06 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 09:10:52 +0200 Subject: Changed: Reflected changes made to the Twitter floater XMLs in code. Fixed: Deprecated llerrs/llwarns/lldebugs/llinfos on the way. --- indra/newview/llfloatertwitter.cpp | 23 +++++++---------------- indra/newview/llfloatertwitter.h | 1 - 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 78e9259919..868d623d57 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -64,7 +64,6 @@ const std::string DEFAULT_STATUS_TEXT = " #SecondLife"; /////////////////////////// LLTwitterPhotoPanel::LLTwitterPhotoPanel() : -mSnapshotPanel(NULL), mResolutionComboBox(NULL), mRefreshBtn(NULL), mBtnPreview(NULL), @@ -94,7 +93,6 @@ BOOL LLTwitterPhotoPanel::postBuild() { setVisibleCallback(boost::bind(&LLTwitterPhotoPanel::onVisibilityChange, this, _2)); - mSnapshotPanel = getChild("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); mResolutionComboBox->setValue("[i800,i600]"); // hardcoded defaults ftw! mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE)); @@ -194,15 +192,8 @@ void LLTwitterPhotoPanel::draw() // calc preview offset within the preview rect const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ; const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; - - // calc preview offset within the floater rect - // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. - // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. - // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. - S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; - S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; - - mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType()); + S32 offset_x = thumbnail_rect.mLeft + local_offset_x; + S32 offset_y = thumbnail_rect.mBottom + local_offset_y; gGL.matrixMode(LLRender::MM_MODELVIEW); // Apply floater transparency to the texture unless the floater is focused. @@ -238,7 +229,7 @@ void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible) LLSnapshotLivePreview* preview = getPreviewView(); if(preview) { - lldebugs << "opened, updating snapshot" << llendl; + LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; preview->updateSnapshot(TRUE); } } @@ -455,7 +446,7 @@ void LLTwitterPhotoPanel::updateControls() BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); // *TODO: Separate maximum size for Web images from postcards - lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; + LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; updateResolution(FALSE); } @@ -485,13 +476,13 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update) if (width == 0 || height == 0) { // take resolution from current window size - lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; + LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL; previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); } else { // use the resolution from the selected pre-canned drop-down choice - lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; + LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; previewp->setSize(width, height); } @@ -755,7 +746,7 @@ void LLFloaterTwitter::showPhotoPanel() LLTabContainer* parent = dynamic_cast(mTwitterPhotoPanel->getParent()); if (!parent) { - llwarns << "Cannot find panel container" << llendl; + LL_WARNS() << "Cannot find panel container" << LL_ENDL; return; } diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index f07ec2ca2f..d586799d18 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -70,7 +70,6 @@ private: LLHandle mPreviewHandle; - LLUICtrl * mSnapshotPanel; LLUICtrl * mResolutionComboBox; LLUICtrl * mFilterComboBox; LLUICtrl * mRefreshBtn; -- cgit v1.2.3 From dca057c6656d98ee05c2fc98dd912d4fd5d35505 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 10:16:38 +0200 Subject: Changed: Snapshot floater layout. Changed: Snapshots to disk default to 'Custom' (Window Resolution) Added: Big Auto-scaling integrated image Preview. Can be toggled. Added: Fixed german translations for the new floater layout. Removed: Need to have SnapshotFiltersEnabled to see the filter dropdown. Removed: SnapshotFiltersEnabled debug. --- indra/newview/app_settings/settings.xml | 11 - indra/newview/llfloatersnapshot.cpp | 136 +++---- .../skins/default/xui/de/floater_snapshot.xml | 13 +- .../default/xui/de/panel_snapshot_inventory.xml | 2 +- .../skins/default/xui/de/panel_snapshot_local.xml | 2 +- .../default/xui/de/panel_snapshot_options.xml | 11 +- .../default/xui/de/panel_snapshot_postcard.xml | 2 - .../default/xui/de/panel_snapshot_profile.xml | 2 +- .../skins/default/xui/en/floater_snapshot.xml | 450 +++++++++++---------- .../default/xui/en/panel_postcard_message.xml | 30 +- .../default/xui/en/panel_postcard_settings.xml | 74 ++-- .../default/xui/en/panel_snapshot_inventory.xml | 77 ++-- .../skins/default/xui/en/panel_snapshot_local.xml | 240 +++++------ .../default/xui/en/panel_snapshot_options.xml | 162 ++++---- .../default/xui/en/panel_snapshot_postcard.xml | 32 +- .../default/xui/en/panel_snapshot_profile.xml | 202 ++++----- 16 files changed, 671 insertions(+), 775 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 03b953b6cc..7ebda3eea6 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11452,17 +11452,6 @@ Value 0 - SnapshotFiltersEnabled - - Comment - Enable filters in the Snapshot Advanced panel (experimental). - Persist - 1 - Type - Boolean - Value - 0 - SnapshotFormat Comment diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 960d3f35dd..c4b00c8342 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llfloatersnapshot.cpp * @brief Snapshot preview window, allowing saving, e-mailing, etc. * @@ -62,7 +62,6 @@ const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512 static LLDefaultChildRegistry::Register r("snapshot_floater_view"); - ///---------------------------------------------------------------------------- /// Class LLFloaterSnapshot::Impl ///---------------------------------------------------------------------------- @@ -96,7 +95,7 @@ public: static void onClickAutoSnap(LLUICtrl *ctrl, void* data); static void onClickFilter(LLUICtrl *ctrl, void* data); //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); - static void onClickMore(void* data) ; + static void onClickPreview(void* data) ; static void onClickUICheck(LLUICtrl *ctrl, void* data); static void onClickHUDCheck(LLUICtrl *ctrl, void* data); static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked); @@ -264,31 +263,33 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot"); - // Show/hide advanced options. - LLPanel* advanced_options_panel = floaterp->getChild("advanced_options_panel"); - floaterp->getChild("advanced_options_btn")->setImageOverlay(advanced ? "TabIcon_Open_Off" : "TabIcon_Close_Off"); - if (advanced != advanced_options_panel->getVisible()) + //BD - Automatically calculate the size of our snapshot window to enlarge + // the snapshot preview to its maximum size, this is especially helpfull + // for pretty much every aspect ratio other than 1:1. + F32 panel_width = 400.f * gViewerWindow->getWorldViewAspectRatio(); + + //BD - Make sure we clamp at 700 here because 700 would be for 16:9 which we + // consider the maximum. Everything bigger will be clamped and will have + // a slightly smaller preview window which most likely won't fill up the + // whole snapshot floater as it should. + if(panel_width > 700.f) { - S32 panel_width = advanced_options_panel->getRect().getWidth(); - floaterp->getChild("advanced_options_panel")->setVisible(advanced); - S32 floater_width = floaterp->getRect().getWidth(); - floater_width += (advanced ? panel_width : -panel_width); - floaterp->reshape(floater_width, floaterp->getRect().getHeight()); + panel_width = 700.f; } - if(!advanced) //set to original window resolution + S32 floater_width = 224.f; + if(advanced) { - previewp->mKeepAspectRatio = TRUE; - - floaterp->getChild("profile_size_combo")->setCurrentByIndex(0); - floaterp->getChild("postcard_size_combo")->setCurrentByIndex(0); - floaterp->getChild("texture_size_combo")->setCurrentByIndex(0); - floaterp->getChild("local_size_combo")->setCurrentByIndex(0); - - LLSnapshotLivePreview* previewp = getPreviewView(floaterp); - previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); + floater_width = floater_width + panel_width; } + LLUICtrl* thumbnail_placeholder = floaterp->getChild("thumbnail_placeholder"); + thumbnail_placeholder->setVisible(advanced); + thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight()); + floaterp->getChild("image_res_text")->setVisible(advanced); + floaterp->getChild("file_size_label")->setVisible(advanced); + floaterp->reshape(floater_width, floaterp->getRect().getHeight()); + bool use_freeze_frame = floaterp->getChild("freeze_frame_check")->getValue().asBoolean(); if (use_freeze_frame) @@ -388,7 +389,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) height_ctrl->setValue(h); } - // Сlamp snapshot resolution to window size when showing UI or HUD in snapshot. + // Clamp snapshot resolution to window size when showing UI or HUD in snapshot. if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) { S32 width = gViewerWindow->getWindowWidthRaw(); @@ -581,20 +582,6 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) } } -void LLFloaterSnapshot::Impl::onClickMore(void* data) -{ - BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot"); - - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) - { - view->impl.setStatus(Impl::STATUS_READY); - gSavedSettings.setBOOL("AdvanceSnapshot", !visible); - updateControls(view) ; - updateLayout(view) ; - } -} - // static void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) { @@ -701,6 +688,20 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde } } +void LLFloaterSnapshot::Impl::onClickPreview(void* data) +{ + BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot"); + + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) + { + view->impl.setStatus(Impl::STATUS_READY); + gSavedSettings.setBOOL("AdvanceSnapshot", !visible); + updateControls(view) ; + updateLayout(view) ; + } +} + // Show/hide upload progress indicators. // static void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working) @@ -1055,7 +1056,7 @@ BOOL LLFloaterSnapshot::postBuild() mSucceessLblPanel = getChild("succeeded_panel"); mFailureLblPanel = getChild("failed_panel"); - childSetAction("advanced_options_btn", Impl::onClickMore, this); + childSetAction("preview_btn", Impl::onClickPreview, this); childSetCommitCallback("ui_check", Impl::onClickUICheck, this); getChild("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); @@ -1075,24 +1076,15 @@ BOOL LLFloaterSnapshot::postBuild() getChild("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); + // Filters LLComboBox* filterbox = getChild("filters_combobox"); - if (gSavedSettings.getBOOL("SnapshotFiltersEnabled")) - { - // Update filter list if setting is on (experimental) - std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); - for (U32 i = 0; i < filter_list.size(); i++) - { - filterbox->add(filter_list[i]); - } - childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); - } - else + std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + for (U32 i = 0; i < filter_list.size(); i++) { - // Hide Filter UI if setting is off (default) - getChild("filter_list_label")->setVisible(FALSE); - filterbox->setVisible(FALSE); + filterbox->add(filter_list[i]); } + childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); @@ -1119,7 +1111,7 @@ BOOL LLFloaterSnapshot::postBuild() getChild("profile_size_combo")->selectNthItem(0); getChild("postcard_size_combo")->selectNthItem(0); getChild("texture_size_combo")->selectNthItem(0); - getChild("local_size_combo")->selectNthItem(0); + getChild("local_size_combo")->selectNthItem(8); getChild("local_format_combo")->selectNthItem(0); impl.mPreviewHandle = previewp->getHandle(); @@ -1145,7 +1137,7 @@ void LLFloaterSnapshot::draw() LLFloater::draw(); - if (previewp && !isMinimized()) + if (previewp && !isMinimized() && sThumbnailPlaceholder->getVisible()) { if(previewp->getThumbnailImage()) { @@ -1172,44 +1164,13 @@ void LLFloaterSnapshot::draw() previewp->drawPreviewRect(offset_x, offset_y) ; - // Draw some controls on top of the preview thumbnail. - static const S32 PADDING = 5; - static const S32 REFRESH_LBL_BG_HEIGHT = 32; - - // Reshape and position the posting result message panels at the top of the thumbnail. - // Do this regardless of current posting status (finished or not) to avoid flicker - // when the result message is displayed for the first time. - // if (impl.getStatus() == Impl::STATUS_FINISHED) - { - LLRect result_lbl_rect = mSucceessLblPanel->getRect(); - const S32 result_lbl_h = result_lbl_rect.getHeight(); - result_lbl_rect.setLeftTopAndSize(local_offset_x, local_offset_y + thumbnail_h, thumbnail_w - 1, result_lbl_h); - mSucceessLblPanel->reshape(result_lbl_rect.getWidth(), result_lbl_h); - mSucceessLblPanel->setRect(result_lbl_rect); - mFailureLblPanel->reshape(result_lbl_rect.getWidth(), result_lbl_h); - mFailureLblPanel->setRect(result_lbl_rect); - } - - // Position the refresh button in the bottom left corner of the thumbnail. - mRefreshBtn->setOrigin(local_offset_x + PADDING, local_offset_y + PADDING); - - if (impl.mNeedRefresh) - { - // Place the refresh hint text to the right of the refresh button. - const LLRect& refresh_btn_rect = mRefreshBtn->getRect(); - mRefreshLabel->setOrigin(refresh_btn_rect.mLeft + refresh_btn_rect.getWidth() + PADDING, refresh_btn_rect.mBottom); - - // Draw the refresh hint background. - LLRect refresh_label_bg_rect(offset_x, offset_y + REFRESH_LBL_BG_HEIGHT, offset_x + thumbnail_w - 1, offset_y); - gl_rect_2d(refresh_label_bg_rect, LLColor4::white % 0.9f, TRUE); - } - gGL.pushUIMatrix(); LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom); sThumbnailPlaceholder->draw(); gGL.popUIMatrix(); } } + impl.updateLayout(this); } void LLFloaterSnapshot::onOpen(const LLSD& key) @@ -1225,6 +1186,9 @@ void LLFloaterSnapshot::onOpen(const LLSD& key) gSnapshotFloaterView->setVisible(TRUE); gSnapshotFloaterView->adjustToFitScreen(this, FALSE); + impl.updateControls(this); + impl.updateLayout(this); + // Initialize default tab. getChild("panel_container")->getCurrentPanel()->onOpen(LLSD()); } diff --git a/indra/newview/skins/default/xui/de/floater_snapshot.xml b/indra/newview/skins/default/xui/de/floater_snapshot.xml index 798461c007..b98ee78685 100755 --- a/indra/newview/skins/default/xui/de/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/de/floater_snapshot.xml @@ -41,23 +41,24 @@ diff --git a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml index 3f67a48b14..22f19ca99a 100755 --- a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml +++ b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml @@ -11,8 +11,8 @@ layout="topleft" left="10" name="postcard_size_combo" - right="-10" - top_pad="10"> + right="-5" + top_pad="5"> + top_pad="0" + right="-1"> + top_pad="3" + width="132" /> + width="54" /> - - ([QLVL]) - + decimal_digits="0" + follows="left|top" + height="15" + increment="1" + initial_value="75" + label="Quality:" + label_width="45" + layout="topleft" + left="10" + max_val="100" + name="image_quality_slider" + top_pad="6" + width="195" /> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml index 71d808fa4b..3a42b9a2f8 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml @@ -12,12 +12,12 @@ left="12" mouse_opaque="true" name="title_icon" - top="5" + top="6" width="18" /> - Save to My Inventory + top_delta="3"> + Inventory - - Saving an image to your inventory costs L$[UPLOAD_COST]. To save your image as a texture select one of the square formats. - + right="-5" + top_pad="5"> + top_pad="7" + width="134" /> + width="54" /> + + Saving an image to your inventory costs L$[UPLOAD_COST]. To save your image as a texture select one of the square formats. + - + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml index 781ab17403..430010f7e4 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml @@ -12,12 +12,12 @@ left="12" mouse_opaque="true" name="title_icon" - top="5" + top="7" width="18" /> - Save to My Computer + top_delta="2"> + Disk + right="-5" + top_pad="5"/> + right="-5" + top_pad="5"> - - - - - - - - - - - - - - - ([QLVL]) - - - + + + + + Format: + + + + + + + + width="95"> - + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml index eff60f8228..0bb2ccba5e 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml @@ -4,117 +4,127 @@ height="240" layout="topleft" name="panel_snapshot_options" - width="490"> + width="198"> + + + - - Send to: [secondlife:/// Facebook] - - - [secondlife:/// Twitter] - - - [secondlife:/// Flickr] - - + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml index ebba292a93..5be93c44c1 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml @@ -24,12 +24,12 @@ left="12" mouse_opaque="true" name="title_icon" - top="5" + top="8" width="18" /> - Email + top_delta="2"> + E-mail @@ -57,12 +58,13 @@ follows="right|top" height="23" is_toggle="true" - label="Settings" + label="" + image_overlay="Command_Preferences_Icon" layout="topleft" name="settings_btn" top_delta="0" - right="-10" - width="70"> + left_pad="5" + width="25"> @@ -73,8 +75,8 @@ left="10" layout="topleft" name="hr" - right="-10" - top_pad="5" + right="-5" + top_pad="2" /> - + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml index 0dd357aa1a..bb63bc5347 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml @@ -17,7 +17,7 @@ - Post to My Profile Feed + Profile + top_pad="5" + width="180"> - + + + + Caption: + + + + - - - - - - - - Caption: - - - - - - + height="18" + name="add_location_cb" + top_pad="3" /> - + \ No newline at end of file -- cgit v1.2.3 From 009a3028efa728dc70769fd773f6619cbf49a2b3 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 10:17:01 +0200 Subject: Added: NiranV Dean to contribution list. --- doc/contributions.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/contributions.txt b/doc/contributions.txt index 7e8ab46b1a..d9d4e6a600 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -990,6 +990,7 @@ Nicky Perian STORM-1090 STORM-1828 Nicoladie Gymnast +NiranV Dean Nounouch Hapmouche VWR-238 Ollie Kubrick -- cgit v1.2.3 From 21aca031d7c6e34249dfb5ba5c19f04ee64f8a03 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Fri, 25 Jul 2014 11:36:57 +0300 Subject: MAINT-4287 FIXED Check that gMenuHolder is not NULL --- indra/newview/lltoolpie.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index eec9760d2d..e4353aafaa 100755 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1315,7 +1315,7 @@ void LLToolPie::handleDeselect() // Menu may be still up during transfer to different tool. // toolfocus and toolgrab should retain menu, they will clear it if needed MASK override_mask = gKeyboard ? gKeyboard->currentMask(TRUE) : 0; - if (!gMenuHolder->getVisible() || (override_mask & (MASK_ALT | MASK_CONTROL)) == 0) + if (gMenuHolder && (!gMenuHolder->getVisible() || (override_mask & (MASK_ALT | MASK_CONTROL)) == 0)) { // in most cases menu is useless without correct selection, so either keep both or discard both gMenuHolder->hideMenus(); -- cgit v1.2.3 From 47241b5d54b84fd2e655f8db0e7841b069f2cbb2 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 25 Jul 2014 10:39:29 +0200 Subject: Changed: Very tiny visual alignment finetunings. Everything has to be perfect. --- indra/newview/skins/default/xui/en/floater_snapshot.xml | 8 ++++---- indra/newview/skins/default/xui/en/panel_snapshot_options.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 410594f1c6..e85a7d81ea 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -106,7 +106,7 @@ bevel_style="in" follows="left|top|right" height="1" - left="6" + left="10" layout="topleft" name="advanced_options_hr" right="-1" @@ -204,11 +204,11 @@ bevel_style="in" follows="left|top|right" height="1" - left="6" + left="10" layout="topleft" name="advanced_options_hr" right="-1" - top_pad="10" + top_pad="7" /> Date: Fri, 25 Jul 2014 10:48:22 +0200 Subject: Changed: More tiny alignment inconsestencies between Black Dragon and Linden Release. --- indra/newview/skins/default/xui/en/floater_snapshot.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index e85a7d81ea..85963756d5 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -260,7 +260,7 @@ left="10" layout="topleft" name="status_hr" - width="192" + width="189" top_pad="-16"/> Date: Sat, 26 Jul 2014 11:46:17 +0200 Subject: STORM-2040: Fixed: German Translation for several snapshot panels. --- .../default/xui/de/panel_postcard_message.xml | 2 +- .../default/xui/de/panel_postcard_settings.xml | 19 +++++--------- .../skins/default/xui/de/panel_snapshot_local.xml | 29 ++++++++-------------- .../default/xui/de/panel_snapshot_profile.xml | 29 ++++++++-------------- 4 files changed, 29 insertions(+), 50 deletions(-) diff --git a/indra/newview/skins/default/xui/de/panel_postcard_message.xml b/indra/newview/skins/default/xui/de/panel_postcard_message.xml index 6eeef8af71..609569bd6f 100755 --- a/indra/newview/skins/default/xui/de/panel_postcard_message.xml +++ b/indra/newview/skins/default/xui/de/panel_postcard_message.xml @@ -9,7 +9,7 @@ Betreff: - + Nachricht: diff --git a/indra/newview/skins/default/xui/de/panel_postcard_settings.xml b/indra/newview/skins/default/xui/de/panel_postcard_settings.xml index c1a1c0cc46..e6d3b7de66 100755 --- a/indra/newview/skins/default/xui/de/panel_postcard_settings.xml +++ b/indra/newview/skins/default/xui/de/panel_postcard_settings.xml @@ -7,17 +7,10 @@ - - - - - - - - - - ([QLVL]) - - - + + + + + ([QLVL]) + diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_local.xml b/indra/newview/skins/default/xui/de/panel_snapshot_local.xml index 935e8d2356..53e78ba290 100755 --- a/indra/newview/skins/default/xui/de/panel_snapshot_local.xml +++ b/indra/newview/skins/default/xui/de/panel_snapshot_local.xml @@ -13,24 +13,17 @@ - - - - - - - - - - - - - - - ([QLVL]) - - - + + + + + + + + + + ([QLVL]) + - diff --git a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml index f6397fe7a2..907751280f 100755 --- a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml +++ b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml @@ -9,9 +9,9 @@ height="23" label="Resolution" layout="topleft" - left="10" + left="5" name="postcard_size_combo" - right="-5" + right="-3" top_pad="5"> + width="190" /> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml index 2622ccb4c4..01265523ea 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml @@ -24,7 +24,7 @@ left="12" mouse_opaque="true" name="title_icon" - top="8" + top="7" width="18" /> E-mail - - - + halign="center" + use_highlighting_on_hover="true"> - + + + \ No newline at end of file -- cgit v1.2.3 From fff5593010aa10eb3921bba475736a5daf1d2968 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 1 Aug 2014 18:50:38 +0200 Subject: STORM-2040: Changed: Slight alignment adjustations. --- indra/newview/skins/default/xui/en/panel_snapshot_local.xml | 2 +- indra/newview/skins/default/xui/en/panel_snapshot_options.xml | 2 +- indra/newview/skins/default/xui/en/panel_snapshot_profile.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml index ab1e1e290e..4cc20a8b5a 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml @@ -32,7 +32,7 @@ bevel_style="in" follows="left|top|right" height="1" - left="10" + left="9" layout="topleft" name="hr" right="-5" diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml index 2f8efd9b13..2b26ee19c1 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml @@ -16,7 +16,7 @@ imgoverlay_label_space="10" label="Save to Disk" layout="topleft" - left="10" + left="9" name="save_to_computer_btn" top_pad="9"> Date: Fri, 1 Aug 2014 19:23:59 +0200 Subject: STORM-2051: Moved: Missing german button translation. --- indra/newview/skins/default/xui/de/panel_postcard_message.xml | 2 -- indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/de/panel_postcard_message.xml b/indra/newview/skins/default/xui/de/panel_postcard_message.xml index 609569bd6f..b34dc776de 100755 --- a/indra/newview/skins/default/xui/de/panel_postcard_message.xml +++ b/indra/newview/skins/default/xui/de/panel_postcard_message.xml @@ -16,6 +16,4 @@ Nachricht hier eingeben. - @@ -140,7 +140,7 @@ left="10" name="save_btn" top_delta="0" - width="95"> + width="97"> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml index 4cc20a8b5a..188c9f8707 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml @@ -86,14 +86,14 @@ height="20" increment="32" label="Width x Height" - label_width="80" + label_width="90" layout="topleft" left="10" max_val="6016" min_val="32" name="local_snapshot_width" top_pad="7" - width="134" /> + width="144" /> + width="203" /> @@ -186,7 +186,7 @@ name="save_btn" tool_tip="Save image to a file" top_delta="0" - width="95"> + width="97"> + width="208"> @@ -96,7 +96,7 @@ left="10" name="send_btn" top_delta="0" - width="95"> + width="97"> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml index 1b718e6826..d86cb92981 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml @@ -76,14 +76,14 @@ height="20" increment="32" label="Width x Height" - label_width="80" + label_width="90" layout="topleft" left="10" max_val="6016" min_val="32" name="profile_snapshot_width" top_pad="7" - width="134" /> + width="144" /> + width="97"> @@ -160,7 +160,7 @@ left="10" name="post_btn" top_delta="0" - width="95"> + width="97"> -- cgit v1.2.3 From b746d4067875cbf4880046fabe9de127b00e8cd3 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 1 Aug 2014 20:17:05 +0200 Subject: Changed: Updated contributions file. --- doc/contributions.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/contributions.txt b/doc/contributions.txt index ed60e48443..faaac602a5 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1002,6 +1002,7 @@ NiranV Dean STORM-2049 STORM-2050 STORM-2051 + STORM-2052 BUG-372 BUG-1179 Nounouch Hapmouche -- cgit v1.2.3 From 45e98414eaeba225a3aa26657789f9d3b80cba22 Mon Sep 17 00:00:00 2001 From: NiranV Date: Sat, 2 Aug 2014 05:25:06 +0200 Subject: STORM-2052: Changed: Swapped button icons. --- indra/newview/skins/default/xui/en/floater_snapshot.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index bc4bf8fd8f..4b8f4c8fed 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -105,7 +105,7 @@ image_hover_unselected="Toolbar_Middle_Over" image_selected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off" - image_overlay="Conv_toolbar_collapse" + image_overlay="Conv_toolbar_expand" name="retract_btn" left_pad="1" top_delta="0" @@ -117,7 +117,7 @@ height="25" is_toggle="true" layout="topleft" - image_overlay="Conv_toolbar_expand" + image_overlay="Conv_toolbar_collapse" image_hover_unselected="Toolbar_Middle_Over" image_selected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off" -- cgit v1.2.3 From 6dc90470275a6d1b1625a05432e63fa54b889ae6 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Mon, 4 Aug 2014 12:39:47 +0300 Subject: MAINT-4293 FIXED [BEAR] Very slow inventory fetch on Bear compared to current release) --- indra/newview/llviewerwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d042bd847e..9dcd0b81e0 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1969,7 +1969,7 @@ void LLViewerWindow::initWorldUI() // Force gFloaterTools to initialize LLFloaterReg::getInstance("build"); - LLFloaterReg::hideInstance("build"); + // Status bar LLPanel* status_bar_container = getRootView()->getChild("status_bar_container"); -- cgit v1.2.3 From e5f6c2faa040c2a7c161d60226854c23ff831eb5 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 4 Aug 2014 14:44:35 -0400 Subject: add some debug logging --- indra/newview/lltexturefetch.cpp | 3 +++ indra/newview/llviewerregion.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 9ea46cab68..62b2f5f976 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1336,17 +1336,20 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_WARNS() << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL; } setUrl(http_url + "/?texture_id=" + mID.asString().c_str()); + LL_DEBUGS("Texture") << "Texture URL " << mUrl << LL_ENDL; mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. } else { mCanUseHTTP = false ; + LL_DEBUGS("Texture") << "Texture not available via HTTP: no URL " << mUrl << LL_ENDL; } } else { // This will happen if not logged in or if a region deoes not have HTTP Texture enabled //LL_WARNS() << "Region not found for host: " << mHost << LL_ENDL; + LL_DEBUGS("Texture") << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; mCanUseHTTP = false; } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 673913c4f2..b22d37b710 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -285,8 +285,8 @@ private: { regionp->setCapability(iter->first, iter->second); - LL_DEBUGS("AppInit", "Capabilities") << "got capability for " - << iter->first << LL_ENDL; + LL_DEBUGS("AppInit", "Capabilities") + << "Capability '" << iter->first << "' is '" << iter->second << "'" << LL_ENDL; /* HACK we're waiting for the ServerReleaseNotes */ if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested()) -- cgit v1.2.3 From c03e22e420a17e47b597c90978eb2f4d206f2ffe Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 6 Aug 2014 17:50:40 +0300 Subject: MAINT-4325 FIXED [BEAR] Fix to "Reset Filters" causes empty folders to appear in Recent tab of Inventory --- indra/newview/llpanelmaininventory.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 2378e09979..ddf1a63c6e 100755 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -151,7 +151,9 @@ BOOL LLPanelMainInventory::postBuild() recent_items_panel->setSinceLogoff(TRUE); recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - recent_items_panel->getFilter().markDefault(); + LLInventoryFilter& recent_filter = recent_items_panel->getFilter(); + recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); + recent_filter.markDefault(); recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2)); } @@ -183,13 +185,6 @@ BOOL LLPanelMainInventory::postBuild() } - if (recent_items_panel) - { - U64 types = recent_items_panel->getFilter().getFilterObjectTypes(); - types &= ~(0x1 << LLInventoryType::IT_CATEGORY); - recent_items_panel->getFilter().setFilterObjectTypes(types); - } - mFilterEditor = getChild("inventory search editor"); if (mFilterEditor) { -- cgit v1.2.3 From 3dbbc49b4f535ee409c3a7c15b617c2997e80d8c Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 6 Aug 2014 15:33:41 -0400 Subject: fix dos line endings --- indra/newview/llfloaterfacebook.cpp | 258 ++++++++++++++++++------------------ indra/newview/llfloaterfacebook.h | 30 ++--- 2 files changed, 144 insertions(+), 144 deletions(-) diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 516cf5c15c..d4f727e1df 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -98,27 +98,27 @@ S32 compute_jpeg_quality(S32 width, S32 height) LLFacebookStatusPanel::LLFacebookStatusPanel() : mMessageTextEditor(NULL), mPostButton(NULL), - mCancelButton(NULL), - mAccountCaptionLabel(NULL), - mAccountNameLabel(NULL), - mPanelButtons(NULL), - mConnectButton(NULL), + mCancelButton(NULL), + mAccountCaptionLabel(NULL), + mAccountNameLabel(NULL), + mPanelButtons(NULL), + mConnectButton(NULL), mDisconnectButton(NULL) { - mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); - mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); - - setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); + mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); + + setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this)); } BOOL LLFacebookStatusPanel::postBuild() { - mAccountCaptionLabel = getChild("account_caption_label"); - mAccountNameLabel = getChild("account_name_label"); - mPanelButtons = getChild("panel_buttons"); - mConnectButton = getChild("connect_btn"); + mAccountCaptionLabel = getChild("account_caption_label"); + mAccountNameLabel = getChild("account_name_label"); + mPanelButtons = getChild("panel_buttons"); + mConnectButton = getChild("connect_btn"); mDisconnectButton = getChild("disconnect_btn"); mMessageTextEditor = getChild("status_message"); @@ -130,15 +130,15 @@ BOOL LLFacebookStatusPanel::postBuild() void LLFacebookStatusPanel::draw() { - LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); - - //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress - bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; - mDisconnectButton->setEnabled(!disconnecting); - - //Disable the 'connect' button when a connection is in progress - bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; - mConnectButton->setEnabled(!connecting); + LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); + + //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress + bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; + mDisconnectButton->setEnabled(!disconnecting); + + //Disable the 'connect' button when a connection is in progress + bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; + mConnectButton->setEnabled(!connecting); if (mMessageTextEditor && mPostButton && mCancelButton) { @@ -170,18 +170,18 @@ void LLFacebookStatusPanel::onSend() bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data) { - if(LLFacebookConnect::instance().isConnected()) - { - //In process of disconnecting so leave the layout as is - if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) - { - showConnectedLayout(); - } - } - else - { - showDisconnectedLayout(); - } + if(LLFacebookConnect::instance().isConnected()) + { + //In process of disconnecting so leave the layout as is + if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) + { + showConnectedLayout(); + } + } + else + { + showDisconnectedLayout(); + } switch (data.get("enum").asInteger()) { @@ -207,101 +207,101 @@ void LLFacebookStatusPanel::sendStatus() } } -void LLFacebookStatusPanel::onVisibilityChange(BOOL visible) -{ - if(visible) - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); - - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); - - //Connected - if(LLFacebookConnect::instance().isConnected()) - { - showConnectedLayout(); - } - //Check if connected (show disconnected layout in meantime) - else - { - showDisconnectedLayout(); - } - if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || - (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) - { - LLFacebookConnect::instance().checkConnectionToFacebook(); - } - } - else - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - } -} - -bool LLFacebookStatusPanel::onFacebookConnectInfoChange() -{ - LLSD info = LLFacebookConnect::instance().getInfo(); - std::string clickable_name; - - //Strings of format [http://www.somewebsite.com Click Me] become clickable text - if(info.has("link") && info.has("name")) - { - clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; - } - - mAccountNameLabel->setText(clickable_name); - - return false; -} - -void LLFacebookStatusPanel::showConnectButton() -{ - if(!mConnectButton->getVisible()) - { - mConnectButton->setVisible(TRUE); - mDisconnectButton->setVisible(FALSE); - } -} - -void LLFacebookStatusPanel::hideConnectButton() -{ - if(mConnectButton->getVisible()) - { - mConnectButton->setVisible(FALSE); - mDisconnectButton->setVisible(TRUE); - } -} - -void LLFacebookStatusPanel::showDisconnectedLayout() -{ - mAccountCaptionLabel->setText(getString("facebook_disconnected")); - mAccountNameLabel->setText(std::string("")); - showConnectButton(); -} - -void LLFacebookStatusPanel::showConnectedLayout() -{ - LLFacebookConnect::instance().loadFacebookInfo(); - - mAccountCaptionLabel->setText(getString("facebook_connected")); - hideConnectButton(); -} - -void LLFacebookStatusPanel::onConnect() -{ - LLFacebookConnect::instance().checkConnectionToFacebook(true); - - //Clear only the facebook browser cookies so that the facebook login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); -} - -void LLFacebookStatusPanel::onDisconnect() -{ - LLFacebookConnect::instance().disconnectFromFacebook(); - - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +void LLFacebookStatusPanel::onVisibilityChange(BOOL visible) +{ + if(visible) + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); + + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); + + //Connected + if(LLFacebookConnect::instance().isConnected()) + { + showConnectedLayout(); + } + //Check if connected (show disconnected layout in meantime) + else + { + showDisconnectedLayout(); + } + if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || + (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) + { + LLFacebookConnect::instance().checkConnectionToFacebook(); + } + } + else + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + } +} + +bool LLFacebookStatusPanel::onFacebookConnectInfoChange() +{ + LLSD info = LLFacebookConnect::instance().getInfo(); + std::string clickable_name; + + //Strings of format [http://www.somewebsite.com Click Me] become clickable text + if(info.has("link") && info.has("name")) + { + clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; + } + + mAccountNameLabel->setText(clickable_name); + + return false; +} + +void LLFacebookStatusPanel::showConnectButton() +{ + if(!mConnectButton->getVisible()) + { + mConnectButton->setVisible(TRUE); + mDisconnectButton->setVisible(FALSE); + } +} + +void LLFacebookStatusPanel::hideConnectButton() +{ + if(mConnectButton->getVisible()) + { + mConnectButton->setVisible(FALSE); + mDisconnectButton->setVisible(TRUE); + } +} + +void LLFacebookStatusPanel::showDisconnectedLayout() +{ + mAccountCaptionLabel->setText(getString("facebook_disconnected")); + mAccountNameLabel->setText(std::string("")); + showConnectButton(); +} + +void LLFacebookStatusPanel::showConnectedLayout() +{ + LLFacebookConnect::instance().loadFacebookInfo(); + + mAccountCaptionLabel->setText(getString("facebook_connected")); + hideConnectButton(); +} + +void LLFacebookStatusPanel::onConnect() +{ + LLFacebookConnect::instance().checkConnectionToFacebook(true); + + //Clear only the facebook browser cookies so that the facebook login screen appears + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +} + +void LLFacebookStatusPanel::onDisconnect() +{ + LLFacebookConnect::instance().disconnectFromFacebook(); + + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } void LLFacebookStatusPanel::clearAndClose() diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index 86e3a148b9..f5a27dd5e7 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -51,21 +51,21 @@ public: void clearAndClose(); private: - void onVisibilityChange(BOOL new_visibility); - bool onFacebookConnectInfoChange(); - void onConnect(); - void onUseAnotherAccount(); - void onDisconnect(); - - void showConnectButton(); - void hideConnectButton(); - void showDisconnectedLayout(); - void showConnectedLayout(); - - LLTextBox * mAccountCaptionLabel; - LLTextBox * mAccountNameLabel; - LLUICtrl * mPanelButtons; - LLUICtrl * mConnectButton; + void onVisibilityChange(BOOL new_visibility); + bool onFacebookConnectInfoChange(); + void onConnect(); + void onUseAnotherAccount(); + void onDisconnect(); + + void showConnectButton(); + void hideConnectButton(); + void showDisconnectedLayout(); + void showConnectedLayout(); + + LLTextBox * mAccountCaptionLabel; + LLTextBox * mAccountNameLabel; + LLUICtrl * mPanelButtons; + LLUICtrl * mConnectButton; LLUICtrl * mDisconnectButton; LLUICtrl* mMessageTextEditor; LLUICtrl* mPostButton; -- cgit v1.2.3 From 210ff45bd62fe6aec299a16daa555ad791370df5 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 6 Aug 2014 17:42:29 -0400 Subject: corrected contributions.txt for OPEN-217 --- doc/contributions.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/contributions.txt b/doc/contributions.txt index 2e9c1da9a6..12bcb87231 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1202,6 +1202,7 @@ Sovereign Engineer OPEN-189 STORM-1972 OPEN-195 + OPEN-217 SpacedOut Frye VWR-34 VWR-45 -- cgit v1.2.3 From cf159e169573c18b259fdab3ace64c946a0620a1 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 7 Aug 2014 17:32:25 +0300 Subject: MAINT-4325 FIXED [BEAR] Fix to "Reset Filters" causes empty folders to appear in Recent tab of Inventory Clean up - reverted fragment from MAINT-1192, it is no longer needed. --- indra/newview/llinventorypanel.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 4491ec8488..32e5675f5e 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1492,8 +1492,6 @@ public: getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); } - /*virtual*/ void onVisibilityChange(BOOL new_visibility); - protected: LLInventoryRecentItemsPanel (const Params&); friend class LLUICtrlFactory; @@ -1506,13 +1504,6 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; } -void LLInventoryRecentItemsPanel::onVisibilityChange(BOOL new_visibility) -{ - if(new_visibility) - { - getFilter().setModified(); - } -} namespace LLInitParam { void TypeValues::declareValues() -- cgit v1.2.3 From c43574dbb731f8a73c37f339c21bcffb1341b9a4 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 8 Aug 2014 19:07:21 +0200 Subject: STORM-2059: Removed: Useless 'Current Window' entry in resolution dropdown. We can go up to 512 only anyway. --- indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml index 5782ba7d04..ea579c6dae 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml @@ -47,10 +47,6 @@ name="texture_size_combo" right="-5" top_pad="5"> - Date: Fri, 8 Aug 2014 19:09:08 +0200 Subject: STORM-2057/2058/2061: Changed: Always update snapshot and thumbnail on every change. Making everything only show up the "need to refresh" message seems impossible with the current onIdle system of the preview other than making incredibly hacky stuff. --- indra/newview/llfloatersnapshot.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 2011afc124..97dcae8591 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -576,7 +576,7 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) LLComboBox* filterbox = static_cast(view->getChild("filters_combobox")); std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); previewp->setFilter(filter_name); - previewp->updateSnapshot(FALSE, TRUE); + previewp->updateSnapshot(TRUE); } } } @@ -825,12 +825,11 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL // hide old preview as the aspect ratio could be wrong checkAutoSnapshot(previewp, FALSE); LL_DEBUGS() << "updating thumbnail" << LL_ENDL; - getPreviewView(view)->updateSnapshot(FALSE, TRUE); + getPreviewView(view)->updateSnapshot(TRUE); if(do_update) { LL_DEBUGS() << "Will update controls" << LL_ENDL; updateControls(view); - setNeedRefresh(view, true); } } } @@ -873,7 +872,6 @@ void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view) LL_DEBUGS() << "image format changed, updating snapshot" << LL_ENDL; getPreviewView(view)->updateSnapshot(TRUE); updateControls(view); - setNeedRefresh(view, false); // we're refreshing } } @@ -951,8 +949,6 @@ void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshot // static void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h) { - bool need_refresh = false; - LL_DEBUGS() << "applyCustomResolution(" << w << ", " << h << ")" << LL_ENDL; if (!view) return; @@ -970,20 +966,15 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 previewp->setSize(w,h); checkAutoSnapshot(previewp, FALSE); LL_DEBUGS() << "applied custom resolution, updating thumbnail" << LL_ENDL; - previewp->updateSnapshot(FALSE, TRUE); + previewp->updateSnapshot(TRUE); comboSetCustom(view, "profile_size_combo"); comboSetCustom(view, "postcard_size_combo"); comboSetCustom(view, "texture_size_combo"); comboSetCustom(view, "local_size_combo"); - need_refresh = true; } } updateControls(view); - if (need_refresh) - { - setNeedRefresh(view, true); // need to do this after updateControls() - } } // static @@ -1238,8 +1229,6 @@ S32 LLFloaterSnapshot::notify(const LLSD& info) { // Disable the send/post/save buttons until snapshot is ready. impl.updateControls(this); - // Force hiding the "Refresh to save" hint because we know we've just started refresh. - impl.setNeedRefresh(this, false); return 1; } -- cgit v1.2.3 From edc1a4efd379d64b2cfda0401800b9ebd0cbb54e Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 8 Aug 2014 20:54:01 +0200 Subject: STORM-2060: Fixed: Width/Height spinners resetting every time type a custom value while 'custom' is not set in the resolution dropdown. --- indra/newview/llfloatersnapshot.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 97dcae8591..beb06c4162 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -965,16 +965,14 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 previewp->setSize(w,h); checkAutoSnapshot(previewp, FALSE); - LL_DEBUGS() << "applied custom resolution, updating thumbnail" << LL_ENDL; - previewp->updateSnapshot(TRUE); comboSetCustom(view, "profile_size_combo"); comboSetCustom(view, "postcard_size_combo"); comboSetCustom(view, "texture_size_combo"); comboSetCustom(view, "local_size_combo"); + LL_DEBUGS() << "applied custom resolution, updating thumbnail" << LL_ENDL; + previewp->updateSnapshot(TRUE); } } - - updateControls(view); } // static -- cgit v1.2.3 From 06b605b8666f2336e77126f8ff47765115c08a27 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 8 Aug 2014 15:20:28 -0400 Subject: MAINT-4257 WIP - already fixed by MAINT-4286, added some warnings --- indra/newview/llaisapi.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 623458cb08..96de15bf75 100755 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -385,6 +385,10 @@ void AISUpdate::parseMeta(const LLSD& update) mCatDescendentDeltas[cat->getParentUUID()]--; mObjectsDeletedIds.insert(*it); } + else + { + LL_WARNS("Inventory") << "removed category not found " << *it << LL_ENDL; + } } // parse _categories_items_removed -> mObjectsDeletedIds @@ -400,6 +404,10 @@ void AISUpdate::parseMeta(const LLSD& update) mCatDescendentDeltas[item->getParentUUID()]--; mObjectsDeletedIds.insert(*it); } + else + { + LL_WARNS("Inventory") << "removed item not found " << *it << LL_ENDL; + } } // parse _broken_links_removed -> mObjectsDeletedIds @@ -414,6 +422,10 @@ void AISUpdate::parseMeta(const LLSD& update) mCatDescendentDeltas[item->getParentUUID()]--; mObjectsDeletedIds.insert(*it); } + else + { + LL_WARNS("Inventory") << "broken link not found " << *it << LL_ENDL; + } } // parse _created_items @@ -804,7 +816,7 @@ void AISUpdate::doUpdate() // Since this is a copy of the category *before* the accounting update, above, // we need to transfer back the updated version/descendent count. LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID()); - if (NULL == curr_cat) + if (!curr_cat) { LL_WARNS("Inventory") << "Failed to update unknown category " << new_category->getUUID() << LL_ENDL; } -- cgit v1.2.3 From aaf4428fad7796417934dbc9c6ccf2b01ab285d3 Mon Sep 17 00:00:00 2001 From: NiranV Date: Sat, 9 Aug 2014 02:14:01 +0200 Subject: STORM-2066: Fixed: Selecting a resolution dropdown bigger than the maximum window resolution with toggled "Show UI in Snapshot" freezes the Viewer. --- indra/newview/llfloatersnapshot.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index beb06c4162..f927b50092 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -758,6 +758,12 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL S32 original_width = 0 , original_height = 0 ; previewp->getSize(original_width, original_height) ; + if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) + { //clamp snapshot resolution to window size when showing UI or HUD in snapshot + width = llmin(width, gViewerWindow->getWindowWidthRaw()); + height = llmin(height, gViewerWindow->getWindowHeightRaw()); + } + if (width == 0 || height == 0) { // take resolution from current window size @@ -803,12 +809,6 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL checkAspectRatio(view, width) ; previewp->getSize(width, height); - - if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) - { //clamp snapshot resolution to window size when showing UI or HUD in snapshot - width = llmin(width, gViewerWindow->getWindowWidthRaw()); - height = llmin(height, gViewerWindow->getWindowHeightRaw()); - } updateSpinners(view, previewp, width, height, TRUE); // may change width and height -- cgit v1.2.3 From beb471287eb0dfad55866209bc294f628b58d658 Mon Sep 17 00:00:00 2001 From: NiranV Date: Sat, 9 Aug 2014 02:21:17 +0200 Subject: STORM-2065: Added: 'Scanlines' filter, we now got a 'Video' one for that poorly recorded bright video style and one that looks like only scanlines were added. --- indra/newview/app_settings/filters/Scanlines.xml | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 indra/newview/app_settings/filters/Scanlines.xml diff --git a/indra/newview/app_settings/filters/Scanlines.xml b/indra/newview/app_settings/filters/Scanlines.xml new file mode 100644 index 0000000000..9f0c3ac318 --- /dev/null +++ b/indra/newview/app_settings/filters/Scanlines.xml @@ -0,0 +1,41 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + saturate + 2.0 + + + stencil + uniform + blend + 0.0 + 0.5 + + + screen + line + 0.02 + 0.02 + + + gamma + 1.75 + 1.0 + 1.0 + 1.0 + + + blur + + + blur + + + -- cgit v1.2.3 From acf278cea1b3f71a2c548798b106e1959b7c485d Mon Sep 17 00:00:00 2001 From: NiranV Date: Sat, 9 Aug 2014 02:29:23 +0200 Subject: STORM-2063: Fixed: Resolution text appearing for a brief moment when updating the controls while the preview is hidden. --- indra/newview/skins/default/xui/en/floater_snapshot.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 4b8f4c8fed..8451814c47 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -420,10 +420,11 @@ type="string" font="SansSerifSmall" length="1" - follows="left|top" + follows="left|top|right" height="14" layout="topleft" - left_delta="5" + left="220" + right="-20" halign="left" name="image_res_text" top_delta="5" -- cgit v1.2.3 From 0762c71bbe006d48de767a119c9b238f552b11b4 Mon Sep 17 00:00:00 2001 From: NiranV Date: Sat, 9 Aug 2014 02:31:47 +0200 Subject: STORM-2064: Changed: Made background of status text invisible. --- indra/newview/skins/default/xui/en/floater_snapshot.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 8451814c47..c0907d6031 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -326,8 +326,7 @@ Date: Sun, 10 Aug 2014 21:14:16 +0200 Subject: STORM-2064: Changed: 'Scanlines' filter to a original picture like look with scanlines. --- indra/newview/app_settings/filters/Scanlines.xml | 25 +++++++----------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/indra/newview/app_settings/filters/Scanlines.xml b/indra/newview/app_settings/filters/Scanlines.xml index 9f0c3ac318..e9ba2889fa 100644 --- a/indra/newview/app_settings/filters/Scanlines.xml +++ b/indra/newview/app_settings/filters/Scanlines.xml @@ -7,26 +7,18 @@ 1.0 1.0 - - saturate - 2.0 - stencil - uniform - blend + scanlines + add-back 0.0 - 0.5 - - - screen - line - 0.02 - 0.02 + 1.0 + 0.015 + 0 gamma - 1.75 + 0.5 1.0 1.0 1.0 @@ -34,8 +26,5 @@ blur - - blur - - + \ No newline at end of file -- cgit v1.2.3 From 8b51aa1f646658669857638eb4050518f95b2fc2 Mon Sep 17 00:00:00 2001 From: NiranV Date: Sun, 10 Aug 2014 21:16:22 +0200 Subject: Changed: 'Black and White' filter to proper b&w only. No corrections, just plain greyscale. --- indra/newview/app_settings/filters/BlackAndWhite.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/indra/newview/app_settings/filters/BlackAndWhite.xml b/indra/newview/app_settings/filters/BlackAndWhite.xml index 101ed8233a..7894628d29 100644 --- a/indra/newview/app_settings/filters/BlackAndWhite.xml +++ b/indra/newview/app_settings/filters/BlackAndWhite.xml @@ -1,19 +1,5 @@ - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - grayscale -- cgit v1.2.3 From 31519b6fed053174a96413c5cfc763e55b059a9b Mon Sep 17 00:00:00 2001 From: NiranV Date: Sun, 10 Aug 2014 21:16:44 +0200 Subject: Changed: 'Sepia' filter to proper sepia only. No corrections, just plain sepia colors. --- indra/newview/app_settings/filters/Sepia.xml | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/indra/newview/app_settings/filters/Sepia.xml b/indra/newview/app_settings/filters/Sepia.xml index 3d577b2998..81d7caf0eb 100644 --- a/indra/newview/app_settings/filters/Sepia.xml +++ b/indra/newview/app_settings/filters/Sepia.xml @@ -1,30 +1,5 @@ - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - stencil - vignette - fade - 0.5 - 1.0 - 0.0 - 0.0 - 1.0 - 4.0 - sepia -- cgit v1.2.3 From 5dffe16aef7c6687a2ed47c5324f4365ff9d84df Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Mon, 11 Aug 2014 14:38:47 -0400 Subject: Add 'HttpRangeRequestsDisable' debug setting to inhibit use of 'Range:' header. Intended for users with bad networking gear or twitchy ISPs, if set to True, forces plain GET requests to asset servers for textures and meshes. This change kicked off a slight refactor in the mesh repository code which made it resilient against unexpected 200's and responses not covering the requested start range. There's still too much data copying in the Mesh code (always has been). Would love to fix that and get rid of the monolithic temp buffer. Cleaned up white space damage caused by unnamed linden who likes to drag his magical editor through code. --- indra/newview/app_settings/settings.xml | 11 + indra/newview/llmeshrepository.cpp | 364 ++++++++++++++++++-------------- indra/newview/lltexturefetch.cpp | 43 ++-- 3 files changed, 243 insertions(+), 175 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 410473c54f..50f56cf6ff 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4467,6 +4467,17 @@ Value 1 + HttpRangeRequestsDisable + + Comment + If true, viewer will not issued range GET requests for meshes and textures. + Persist + 1 + Type + Boolean + Value + 0 + IMShowTimestamps Comment diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index fc69ecfae9..6477389d4c 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1,4 +1,3 @@ - /** * @file llmeshrepository.cpp * @brief Mesh repository implementation. @@ -521,11 +520,13 @@ class LLMeshHandlerBase : public LLCore::HttpHandler { public: LOG_CLASS(LLMeshHandlerBase); - LLMeshHandlerBase() + LLMeshHandlerBase(U32 offset, U32 requested_bytes) : LLCore::HttpHandler(), mMeshParams(), mProcessed(false), - mHttpHandle(LLCORE_HTTP_HANDLE_INVALID) + mHttpHandle(LLCORE_HTTP_HANDLE_INVALID), + mOffset(offset), + mRequestedBytes(requested_bytes) {} virtual ~LLMeshHandlerBase() @@ -537,13 +538,15 @@ protected: public: virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); - virtual void processData(LLCore::BufferArray * body, U8 * data, S32 data_size) = 0; + virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size) = 0; virtual void processFailure(LLCore::HttpStatus status) = 0; public: LLVolumeParams mMeshParams; bool mProcessed; - LLCore::HttpHandle mHttpHandle; + LLCore::HttpHandle mHttpHandle; + U32 mOffset; + U32 mRequestedBytes; }; @@ -554,8 +557,8 @@ class LLMeshHeaderHandler : public LLMeshHandlerBase { public: LOG_CLASS(LLMeshHeaderHandler); - LLMeshHeaderHandler(const LLVolumeParams & mesh_params) - : LLMeshHandlerBase() + LLMeshHeaderHandler(const LLVolumeParams & mesh_params, U32 offset, U32 requested_bytes) + : LLMeshHandlerBase(offset, requested_bytes) { mMeshParams = mesh_params; LLMeshRepoThread::incActiveHeaderRequests(); @@ -567,7 +570,7 @@ protected: void operator=(const LLMeshHeaderHandler &); // Not defined public: - virtual void processData(LLCore::BufferArray * body, U8 * data, S32 data_size); + virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size); virtual void processFailure(LLCore::HttpStatus status); }; @@ -576,17 +579,16 @@ public: // // Thread: repo class LLMeshLODHandler : public LLMeshHandlerBase - { +{ public: + LOG_CLASS(LLMeshLODHandler); LLMeshLODHandler(const LLVolumeParams & mesh_params, S32 lod, U32 offset, U32 requested_bytes) - : LLMeshHandlerBase(), - mLOD(lod), - mRequestedBytes(requested_bytes), - mOffset(offset) + : LLMeshHandlerBase(offset, requested_bytes), + mLOD(lod) { - mMeshParams = mesh_params; - LLMeshRepoThread::incActiveLODRequests(); - } + mMeshParams = mesh_params; + LLMeshRepoThread::incActiveLODRequests(); + } virtual ~LLMeshLODHandler(); protected: @@ -594,13 +596,11 @@ protected: void operator=(const LLMeshLODHandler &); // Not defined public: - virtual void processData(LLCore::BufferArray * body, U8 * data, S32 data_size); + virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size); virtual void processFailure(LLCore::HttpStatus status); public: S32 mLOD; - U32 mRequestedBytes; - U32 mOffset; }; @@ -608,14 +608,12 @@ public: // // Thread: repo class LLMeshSkinInfoHandler : public LLMeshHandlerBase - { +{ public: LOG_CLASS(LLMeshSkinInfoHandler); - LLMeshSkinInfoHandler(const LLUUID& id, U32 offset, U32 size) - : LLMeshHandlerBase(), - mMeshID(id), - mRequestedBytes(size), - mOffset(offset) + LLMeshSkinInfoHandler(const LLUUID& id, U32 offset, U32 requested_bytes) + : LLMeshHandlerBase(offset, requested_bytes), + mMeshID(id) {} virtual ~LLMeshSkinInfoHandler(); @@ -624,13 +622,11 @@ protected: void operator=(const LLMeshSkinInfoHandler &); // Not defined public: - virtual void processData(LLCore::BufferArray * body, U8 * data, S32 data_size); + virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size); virtual void processFailure(LLCore::HttpStatus status); public: LLUUID mMeshID; - U32 mRequestedBytes; - U32 mOffset; }; @@ -638,14 +634,12 @@ public: // // Thread: repo class LLMeshDecompositionHandler : public LLMeshHandlerBase - { +{ public: LOG_CLASS(LLMeshDecompositionHandler); - LLMeshDecompositionHandler(const LLUUID& id, U32 offset, U32 size) - : LLMeshHandlerBase(), - mMeshID(id), - mRequestedBytes(size), - mOffset(offset) + LLMeshDecompositionHandler(const LLUUID& id, U32 offset, U32 requested_bytes) + : LLMeshHandlerBase(offset, requested_bytes), + mMeshID(id) {} virtual ~LLMeshDecompositionHandler(); @@ -654,13 +648,11 @@ protected: void operator=(const LLMeshDecompositionHandler &); // Not defined public: - virtual void processData(LLCore::BufferArray * body, U8 * data, S32 data_size); + virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size); virtual void processFailure(LLCore::HttpStatus status); public: LLUUID mMeshID; - U32 mRequestedBytes; - U32 mOffset; }; @@ -668,14 +660,12 @@ public: // // Thread: repo class LLMeshPhysicsShapeHandler : public LLMeshHandlerBase - { +{ public: LOG_CLASS(LLMeshPhysicsShapeHandler); - LLMeshPhysicsShapeHandler(const LLUUID& id, U32 offset, U32 size) - : LLMeshHandlerBase(), - mMeshID(id), - mRequestedBytes(size), - mOffset(offset) + LLMeshPhysicsShapeHandler(const LLUUID& id, U32 offset, U32 requested_bytes) + : LLMeshHandlerBase(offset, requested_bytes), + mMeshID(id) {} virtual ~LLMeshPhysicsShapeHandler(); @@ -684,13 +674,11 @@ protected: void operator=(const LLMeshPhysicsShapeHandler &); // Not defined public: - virtual void processData(LLCore::BufferArray * body, U8 * data, S32 data_size); + virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size); virtual void processFailure(LLCore::HttpStatus status); public: LLUUID mMeshID; - U32 mRequestedBytes; - U32 mOffset; }; @@ -716,8 +704,8 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content, LL_WARNS(LOG_MESH) << "error: " << err << LL_ENDL; LL_WARNS(LOG_MESH) << " mesh upload failed, stage '" << stage << "', error '" << err["error"].asString() - << "', message '" << err["message"].asString() - << "', id '" << err["identifier"].asString() + << "', message '" << err["message"].asString() + << "', id '" << err["identifier"].asString() << "'" << LL_ENDL; if (err.has("errors")) { @@ -779,7 +767,7 @@ LLMeshRepoThread::LLMeshRepoThread() LLMeshRepoThread::~LLMeshRepoThread() - { +{ LL_INFOS(LOG_MESH) << "Small GETs issued: " << LLMeshRepository::sHTTPRequestCount << ", Large GETs issued: " << LLMeshRepository::sHTTPLargeRequestCount << ", Max Lock Holdoffs: " << LLMeshRepository::sMaxLockHoldoffs @@ -790,23 +778,23 @@ LLMeshRepoThread::~LLMeshRepoThread() ++iter) { delete *iter; - } + } mHttpRequestSet.clear(); if (mHttpHeaders) - { + { mHttpHeaders->release(); mHttpHeaders = NULL; - } + } if (mHttpOptions) - { + { mHttpOptions->release(); mHttpOptions = NULL; - } + } if (mHttpLargeOptions) -{ + { mHttpLargeOptions->release(); mHttpLargeOptions = NULL; -} + } delete mHttpRequest; mHttpRequest = NULL; delete mMutex; @@ -1137,6 +1125,9 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int c size_t offset, size_t len, LLCore::HttpHandler * handler) { + // Also used in lltexturefetch.cpp + static LLCachedControl disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false); + LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); if (len < LARGE_MESH_FETCH_THRESHOLD) @@ -1146,8 +1137,8 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int c : mHttpLegacyPolicyClass), mHttpPriority, url, - offset, - len, + (disable_range_req ? size_t(0) : offset), + (disable_range_req ? size_t(0) : len), mHttpOptions, mHttpHeaders, handler); @@ -1161,8 +1152,8 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int c handle = mHttpRequest->requestGetByteRange(mHttpLargePolicyClass, mHttpPriority, url, - offset, - len, + (disable_range_req ? size_t(0) : offset), + (disable_range_req ? size_t(0) : len), mHttpLargeOptions, mHttpHeaders, handler); @@ -1532,7 +1523,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) //within the first 4KB //NOTE -- this will break of headers ever exceed 4KB - LLMeshHeaderHandler * handler = new LLMeshHeaderHandler(mesh_params); + LLMeshHeaderHandler * handler = new LLMeshHeaderHandler(mesh_params, 0, MESH_HEADER_SIZE); LLCore::HttpHandle handle = getByteRange(http_url, cap_version, 0, MESH_HEADER_SIZE, handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) { @@ -2276,7 +2267,7 @@ void LLMeshUploadThread::doWholeModelUpload() mHttpRequest->update(0); while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) - { + { ms_sleep(sleep_time); sleep_time = llmin(250U, sleep_time + sleep_time); mHttpRequest->update(0); @@ -2292,7 +2283,7 @@ void LLMeshUploadThread::doWholeModelUpload() } } } - } +} void LLMeshUploadThread::requestWholeModelFee() { @@ -2323,7 +2314,7 @@ void LLMeshUploadThread::requestWholeModelFee() LL_WARNS(LOG_MESH) << "Couldn't issue request for model fee. Reason: " << mHttpStatus.toString() << " (" << mHttpStatus.toTerseString() << ")" << LL_ENDL; - } + } else { U32 sleep_time(10); @@ -2340,7 +2331,7 @@ void LLMeshUploadThread::requestWholeModelFee() LL_DEBUGS(LOG_MESH) << "Mesh fee query operation discarded." << LL_ENDL; } } - } +} // Does completion duty for both fee queries and actual uploads. @@ -2393,12 +2384,12 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp { LLCore::BufferArrayStream bas(ba); LLSDSerialize::fromXML(body, bas); -} + } } dump_llsd_to_file(body, make_dump_name("whole_model_upload_response_", dump_num)); if (body["state"].asString() == "complete") -{ + { // requested "mesh" asset type isn't actually the type // of the resultant object, fix it up here. mModelData["asset_type"] = "object"; @@ -2451,18 +2442,18 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp body = llsd_from_file("fake_upload_error.xml"); } else - { + { LLCore::BufferArray * ba(response->getBody()); if (ba && ba->size()) - { + { LLCore::BufferArrayStream bas(ba); LLSDSerialize::fromXML(body, bas); - } - } + } + } dump_llsd_to_file(body, make_dump_name("whole_model_fee_response_", dump_num)); if (body["state"].asString() == "upload") - { + { mWholeModelUploadURL = body["uploader"].asString(); if (observer) @@ -2548,18 +2539,18 @@ void LLMeshRepoThread::notifyLoadedMeshes() skin_info_q.swap(mSkinInfoQ); } if (! mDecompositionQ.empty()) - { + { decomp_q.swap(mDecompositionQ); - } + } mMutex->unlock(); // Process the elements free of the lock while (! skin_info_q.empty()) - { + { gMeshRepo.notifySkinInfoReceived(skin_info_q.front()); skin_info_q.pop_front(); - } + } while (! decomp_q.empty()) { @@ -2681,35 +2672,78 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo // rather than partial) and 416 (request completely unsatisfyable). // Always been exposed to these but are less likely here where // speculative loads aren't done. - static const LLCore::HttpStatus par_status(HTTP_PARTIAL_CONTENT); + LLCore::BufferArray * body(response->getBody()); + S32 body_offset(0); + U8 * data(NULL); + S32 data_size(body ? body->size() : 0); - if (par_status != status) + if (data_size > 0) { - LL_WARNS_ONCE(LOG_MESH) << "Non-206 successful status received for fetch: " - << status.toTerseString() << LL_ENDL; - } + static const LLCore::HttpStatus par_status(HTTP_PARTIAL_CONTENT); + + unsigned int offset(0), length(0), full_length(0); + + if (par_status == status) + { + // 216 case + response->getRange(&offset, &length, &full_length); + if (! offset && ! length) + { + // This is the case where we receive a 206 status but + // there wasn't a useful Content-Range header in the response. + // This could be because it was badly formatted but is more + // likely due to capabilities services which scrub headers + // from responses. Assume we got what we asked for...` + // length = data_size; + offset = mOffset; + } + } + else + { + // 200 case, typically + offset = 0; + } - LLCore::BufferArray * body(response->getBody()); - S32 data_size(body ? body->size() : 0); - U8 * data(NULL); + // *DEBUG: To test validation below + // offset += 1; - if (data_size > 0) - { + // Validate that what we think we received is consistent with + // what we've asked for. I.e. first byte we wanted lies somewhere + // in the response. + if (offset > mOffset + || (offset + data_size) <= mOffset + || (mOffset - offset) >= data_size) + { + // No overlap with requested range. Fail request with + // suitable error. Shouldn't happen unless server/cache/ISP + // is doing something awful. + LL_WARNS(LOG_MESH) << "Mesh response (bytes [" + << offset << ".." << (offset + length - 1) + << "]) didn't overlap with request's origin (bytes [" + << mOffset << ".." << (mOffset + mRequestedBytes - 1) + << "])." << LL_ENDL; + processFailure(LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_INV_CONTENT_RANGE_HDR)); + ++LLMeshRepository::sHTTPErrorCount; + goto common_exit; + } + // *TODO: Try to get rid of data copying and add interfaces // that support BufferArray directly. Introduce a two-phase // handler, optional first that takes a body, fallback second // that requires a temporary allocation and data copy. - data = new U8[data_size]; - body->read(0, (char *) data, data_size); + body_offset = mOffset - offset; + data = new U8[data_size - body_offset]; + body->read(body_offset, (char *) data, data_size - body_offset); LLMeshRepository::sBytesReceived += data_size; } - processData(body, data, data_size); + processData(body, body_offset, data, data_size - body_offset); delete [] data; } // Release handler +common_exit: gMeshRepo.mThread->mHttpRequestSet.erase(this); delete this; // Must be last statement } @@ -2744,9 +2778,10 @@ void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status) { gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); } - } +} -void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size) +void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, + U8 * data, S32 data_size) { LLUUID mesh_id = mMeshParams.getSculptID(); bool success = (! MESH_HEADER_PROCESS_FAILED) && gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size); @@ -2761,12 +2796,12 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32 // Can't get the header so none of the LODs will be available LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) - { + { gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); - } } + } else if (data && data_size > 0) - { + { // header was successfully retrieved from sim, cache in vfs LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id]; @@ -2779,11 +2814,11 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32 S32 lod_bytes = 0; for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i) - { + { // figure out how many bytes we'll need to reserve in the file const std::string & lod_name = header_lod[i]; lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger()); - } + } // just in case skin info or decomposition is at the end of the file (which it shouldn't be) lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); @@ -2799,7 +2834,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32 LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) - { + { LLMeshRepository::sCacheBytesWritten += data_size; ++LLMeshRepository::sCacheWrites; @@ -2810,19 +2845,19 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32 memset(block, 0, sizeof(block)); while (bytes-file.tell() > sizeof(block)) - { + { file.write(block, sizeof(block)); - } + } S32 remaining = bytes-file.tell(); if (remaining > 0) - { + { file.write(block, remaining); } } } } - } +} LLMeshLODHandler::~LLMeshLODHandler() { @@ -2848,8 +2883,9 @@ void LLMeshLODHandler::processFailure(LLCore::HttpStatus status) gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); } -void LLMeshLODHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size) - { +void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, + U8 * data, S32 data_size) +{ if ((! MESH_LOD_PROCESS_FAILED) && gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size)) { //good fetch from sim, write to VFS for caching @@ -2865,7 +2901,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * body, U8 * data, S32 da LLMeshRepository::sCacheBytesWritten += size; ++LLMeshRepository::sCacheWrites; } - } + } else { LL_WARNS(LOG_MESH) << "Error during mesh LOD processing. ID: " << mMeshParams.getSculptID() @@ -2877,12 +2913,12 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * body, U8 * data, S32 da } LLMeshSkinInfoHandler::~LLMeshSkinInfoHandler() - { - llassert(mProcessed); - } +{ + llassert(mProcessed); +} void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status) - { +{ LL_WARNS(LOG_MESH) << "Error during mesh skin info handling. ID: " << mMeshID << ", Reason: " << status.toString() << " (" << status.toTerseString() << "). Not retrying." @@ -2890,10 +2926,11 @@ void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status) // *TODO: Mark mesh unavailable on error. For now, simply leave // request unfulfilled rather than retry forever. - } +} -void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size) - { +void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, + U8 * data, S32 data_size) +{ if ((! MESH_SKIN_INFO_PROCESS_FAILED) && gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size)) { //good fetch from sim, write to VFS for caching @@ -2921,20 +2958,21 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * body, U8 * data, S LLMeshDecompositionHandler::~LLMeshDecompositionHandler() { - llassert(mProcessed); + llassert(mProcessed); } void LLMeshDecompositionHandler::processFailure(LLCore::HttpStatus status) - { +{ LL_WARNS(LOG_MESH) << "Error during mesh decomposition handling. ID: " << mMeshID << ", Reason: " << status.toString() << " (" << status.toTerseString() << "). Not retrying." << LL_ENDL; // *TODO: Mark mesh unavailable on error. For now, simply leave // request unfulfilled rather than retry forever. - } +} -void LLMeshDecompositionHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size) +void LLMeshDecompositionHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, + U8 * data, S32 data_size) { if ((! MESH_DECOMP_PROCESS_FAILED) && gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size)) { @@ -2951,34 +2989,35 @@ void LLMeshDecompositionHandler::processData(LLCore::BufferArray * body, U8 * da file.seek(offset); file.write(data, size); } - } - else - { + } + else + { LL_WARNS(LOG_MESH) << "Error during mesh decomposition processing. ID: " << mMeshID << ", Unknown reason. Not retrying." << LL_ENDL; // *TODO: Mark mesh unavailable on error - } } +} LLMeshPhysicsShapeHandler::~LLMeshPhysicsShapeHandler() - { - llassert(mProcessed); - } +{ + llassert(mProcessed); +} void LLMeshPhysicsShapeHandler::processFailure(LLCore::HttpStatus status) - { +{ LL_WARNS(LOG_MESH) << "Error during mesh physics shape handling. ID: " << mMeshID << ", Reason: " << status.toString() << " (" << status.toTerseString() << "). Not retrying." << LL_ENDL; // *TODO: Mark mesh unavailable on error - } +} -void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size) - { +void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, + U8 * data, S32 data_size) +{ if ((! MESH_PHYS_SHAPE_PROCESS_FAILED) && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size)) - { + { // good fetch from sim, write to VFS for caching LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); @@ -2986,13 +3025,13 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * body, U8 * dat S32 size = mRequestedBytes; if (file.getSize() >= offset+size) - { + { LLMeshRepository::sCacheBytesWritten += size; ++LLMeshRepository::sCacheWrites; file.seek(offset); file.write(data, size); - } } + } else { LL_WARNS(LOG_MESH) << "Error during mesh physics shape processing. ID: " << mMeshID @@ -3192,7 +3231,7 @@ void LLMeshRepository::notifyLoadedMeshes() if (1 == mGetMeshVersion) { // Legacy GetMesh operation with high connection concurrency - LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests"); + LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests"); LLMeshRepoThread::sRequestHighWater = llclamp(2 * S32(LLMeshRepoThread::sMaxConcurrentRequests), REQUEST_HIGH_WATER_MIN, REQUEST_HIGH_WATER_MAX); @@ -3311,18 +3350,18 @@ void LLMeshRepository::notifyLoadedMeshes() // If we can't get the locks, skip and pick this up later. ++hold_offs; sMaxLockHoldoffs = llmax(sMaxLockHoldoffs, hold_offs); - return; - } + return; + } hold_offs = 0; if (gAgent.getRegion()) { // Update capability urls - static std::string region_name("never name a region this"); + static std::string region_name("never name a region this"); - if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived()) - { - region_name = gAgent.getRegion()->getName(); + if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived()) + { + region_name = gAgent.getRegion()->getName(); const bool use_v1(gSavedSettings.getBOOL("MeshUseGetMesh1")); const std::string mesh1(gAgent.getRegion()->getCapability("GetMesh")); const std::string mesh2(gAgent.getRegion()->getCapability("GetMesh2")); @@ -3333,8 +3372,8 @@ void LLMeshRepository::notifyLoadedMeshes() << ", GetMesh: " << mesh1 << ", using version: " << mGetMeshVersion << LL_ENDL; + } } - } //popup queued error messages from background threads while (!mUploadErrorQ.empty()) @@ -3349,46 +3388,46 @@ void LLMeshRepository::notifyLoadedMeshes() S32 push_count = LLMeshRepoThread::sRequestHighWater - active_count; if (mPendingRequests.size() > push_count) - { + { // More requests than the high-water limit allows so // sort and forward the most important. - //calculate "score" for pending requests + //calculate "score" for pending requests - //create score map - std::map score_map; + //create score map + std::map score_map; - for (U32 i = 0; i < 4; ++i) - { - for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) + for (U32 i = 0; i < 4; ++i) { - F32 max_score = 0.f; - for (std::set::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) + for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) { - LLViewerObject* object = gObjectList.findObject(*obj_iter); - - if (object) + F32 max_score = 0.f; + for (std::set::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) { - LLDrawable* drawable = object->mDrawable; - if (drawable) + LLViewerObject* object = gObjectList.findObject(*obj_iter); + + if (object) { - F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f); - max_score = llmax(max_score, cur_score); + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f); + max_score = llmax(max_score, cur_score); + } } } - } - score_map[iter->first.getSculptID()] = max_score; + score_map[iter->first.getSculptID()] = max_score; + } } - } - //set "score" for pending requests - for (std::vector::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter) - { - iter->mScore = score_map[iter->mMeshParams.getSculptID()]; - } + //set "score" for pending requests + for (std::vector::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter) + { + iter->mScore = score_map[iter->mMeshParams.getSculptID()]; + } - //sort by "score" + //sort by "score" std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count, mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); } @@ -3599,7 +3638,6 @@ void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) } } } - } LLModel::Decomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index ab7df02100..4008a6948d 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1327,7 +1327,7 @@ bool LLTextureFetchWorker::doWork(S32 param) } } - static LLCachedControl use_http(gSavedSettings,"ImagePipelineUseHTTP", true); + static LLCachedControl use_http(gSavedSettings, "ImagePipelineUseHTTP", true); // if (mHost != LLHost::invalid) get_url = false; if ( use_http && mCanUseHTTP && mUrl.empty())//get http url. @@ -1472,6 +1472,9 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == SEND_HTTP_REQ) { + // Also used in llmeshrepository + static LLCachedControl disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false); + if (! mCanUseHTTP) { releaseHttpSemaphore(); @@ -1553,16 +1556,32 @@ bool LLTextureFetchWorker::doWork(S32 param) // Will call callbackHttpGet when curl request completes // Only server bake images use the returned headers currently, for getting retry-after field. LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions; - mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, - mWorkPriority, - mUrl, - mRequestedOffset, - (mRequestedOffset + mRequestedSize) > HTTP_REQUESTS_RANGE_END_MAX - ? 0 - : mRequestedSize, - options, - mFetcher->mHttpHeaders, - this); + if (disable_range_req) + { + // 'Range:' requests may be disabled in which case all HTTP + // texture fetches result in full fetches. This can be used + // by people with questionable ISPs or networking gear that + // doesn't handle these well. + mHttpHandle = mFetcher->mHttpRequest->requestGet(mHttpPolicyClass, + mWorkPriority, + mUrl, + options, + mFetcher->mHttpHeaders, + this); + } + else + { + mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, + mWorkPriority, + mUrl, + mRequestedOffset, + (mRequestedOffset + mRequestedSize) > HTTP_REQUESTS_RANGE_END_MAX + ? 0 + : mRequestedSize, + options, + mFetcher->mHttpHeaders, + this); + } if (LLCORE_HTTP_HANDLE_INVALID == mHttpHandle) { LLCore::HttpStatus status(mFetcher->mHttpRequest->getStatus()); @@ -1782,7 +1801,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == DECODE_IMAGE) { - static LLCachedControl textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); + static LLCachedControl textures_decode_disabled(gSavedSettings, "TextureDecodeDisabled", false); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it if (textures_decode_disabled) -- cgit v1.2.3 From e201c9d274539f987ca1d41fd9fb21431838fe4d Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Mon, 11 Aug 2014 17:04:39 -0400 Subject: Doc cleanup. Unicode cruft, copy editing. --- indra/cmake/00-COMPILE-LINK-RUN.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indra/cmake/00-COMPILE-LINK-RUN.txt b/indra/cmake/00-COMPILE-LINK-RUN.txt index d08cc2dc0c..49b899c50d 100644 --- a/indra/cmake/00-COMPILE-LINK-RUN.txt +++ b/indra/cmake/00-COMPILE-LINK-RUN.txt @@ -115,12 +115,12 @@ Compilation ---------------------------------------------------------------------------- Notes: - 1. We’re also building dylibs in a somewhat unusual way. They’re + 1. We're also building dylibs in a somewhat unusual way. They're currently being generated with a link path of - ‘@executable_path/../Resources/’. If we were to follow - the recommendations in dyld’s man page, we’d instead reference - ‘@loader_path/’, use -rpath on the executable link - (pointing to the ‘Resources’ subdir of the main executable), and + '@executable_path/../Resources/'. If we were to follow + the recommendations in dyld's man page, we’d instead reference + '@loader_path/', use -rpath on the executable link + (pointing to the 'Resources' subdir of the main executable), and be able to avoid some symlinking in the .app tree. 2. Use the -headerpad_max_install_names link option on all .dylibs. @@ -184,7 +184,7 @@ Linking second, incompatible version of the library. Switching colladadom to a static library ended the re-export problem. - * Preventing re-export is not sufficient. other libraries will + * Preventing re-export is not sufficient. Other libraries will still be shipped as shared and they can still have Singleton and Fragile Base Class issues. A DLL may be built with a static archive of a library that has global data. That same static -- cgit v1.2.3 From ea96b9cc3286d346108c73498b4ed18e43d50098 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 12 Aug 2014 15:36:17 -0400 Subject: Remove now-unused mac_updater subtree from viewer source. --- indra/mac_updater/mac_updater.cpp | 1266 ------------------------------------- 1 file changed, 1266 deletions(-) delete mode 100644 indra/mac_updater/mac_updater.cpp diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp deleted file mode 100644 index f533d47b18..0000000000 --- a/indra/mac_updater/mac_updater.cpp +++ /dev/null @@ -1,1266 +0,0 @@ -/** - * @file mac_updater.cpp - * @brief - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include - -#include -#include -#include -#include - -#include -#include - -#include "llerror.h" -#include "lltimer.h" -#include "lldir.h" -#include "llfile.h" - -#include "llstring.h" - -#include - -#include "llerrorcontrol.h" - -#if LL_DARWIN -// FSPathMakeRef, FSObjectCopy, deprecations... -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - -enum -{ - kEventClassCustom = 'Cust', - kEventCustomProgress = 'Prog', - kEventParamCustomCurValue = 'Cur ', - kEventParamCustomMaxValue = 'Max ', - kEventParamCustomText = 'Text', - kEventCustomDone = 'Done', -}; - -WindowRef gWindow = NULL; -EventHandlerRef gEventHandler = NULL; -OSStatus gFailure = noErr; -Boolean gCancelled = false; - -const char *gUpdateURL; -const char *gProductName; -const char *gBundleID; -const char *gDmgFile; -const char *gMarkerPath; - -void *updatethreadproc(void*); - -pthread_t updatethread; - -OSStatus setProgress(int cur, int max) -{ - OSStatus err; - ControlRef progressBar = NULL; - ControlID id; - - id.signature = 'prog'; - id.id = 0; - - err = GetControlByID(gWindow, &id, &progressBar); - if(err == noErr) - { - Boolean indeterminate; - - if(max == 0) - { - indeterminate = true; - err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate); - } - else - { - double percentage = (double)cur / (double)max; - SetControlMinimum(progressBar, 0); - SetControlMaximum(progressBar, 100); - SetControlValue(progressBar, (SInt16)(percentage * 100)); - - indeterminate = false; - err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate); - - Draw1Control(progressBar); - } - } - - return(err); -} - -OSStatus setProgressText(CFStringRef text) -{ - OSStatus err; - ControlRef progressText = NULL; - ControlID id; - - id.signature = 'what'; - id.id = 0; - - err = GetControlByID(gWindow, &id, &progressText); - if(err == noErr) - { - err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&text); - Draw1Control(progressText); - } - - return(err); -} - -OSStatus sendProgress(long cur, long max, CFStringRef text = NULL) -{ - OSStatus result; - EventRef evt; - - result = CreateEvent( - NULL, - kEventClassCustom, - kEventCustomProgress, - 0, - kEventAttributeNone, - &evt); - - // This event needs to be targeted at the window so it goes to the window's handler. - if(result == noErr) - { - EventTargetRef target = GetWindowEventTarget(gWindow); - result = SetEventParameter ( - evt, - kEventParamPostTarget, - typeEventTargetRef, - sizeof(target), - &target); - } - - if(result == noErr) - { - result = SetEventParameter ( - evt, - kEventParamCustomCurValue, - typeLongInteger, - sizeof(cur), - &cur); - } - - if(result == noErr) - { - result = SetEventParameter ( - evt, - kEventParamCustomMaxValue, - typeLongInteger, - sizeof(max), - &max); - } - - if(result == noErr) - { - if(text != NULL) - { - result = SetEventParameter ( - evt, - kEventParamCustomText, - typeCFStringRef, - sizeof(text), - &text); - } - } - - if(result == noErr) - { - // Send the event - PostEventToQueue( - GetMainEventQueue(), - evt, - kEventPriorityStandard); - - } - - return(result); -} - -OSStatus sendDone(void) -{ - OSStatus result; - EventRef evt; - - result = CreateEvent( - NULL, - kEventClassCustom, - kEventCustomDone, - 0, - kEventAttributeNone, - &evt); - - // This event needs to be targeted at the window so it goes to the window's handler. - if(result == noErr) - { - EventTargetRef target = GetWindowEventTarget(gWindow); - result = SetEventParameter ( - evt, - kEventParamPostTarget, - typeEventTargetRef, - sizeof(target), - &target); - } - - if(result == noErr) - { - // Send the event - PostEventToQueue( - GetMainEventQueue(), - evt, - kEventPriorityStandard); - - } - - return(result); -} - -OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) -{ - OSStatus result = eventNotHandledErr; - OSStatus err; - UInt32 evtClass = GetEventClass(event); - UInt32 evtKind = GetEventKind(event); - - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand cmd; - err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd); - - if(err == noErr) - { - switch(cmd.commandID) - { - case kHICommandCancel: - gCancelled = true; -// QuitAppModalLoopForWindow(gWindow); - result = noErr; - break; - } - } - } - else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomProgress)) - { - // Request to update the progress dialog - long cur = 0; - long max = 0; - CFStringRef text = NULL; - (void) GetEventParameter(event, kEventParamCustomCurValue, typeLongInteger, NULL, sizeof(cur), NULL, &cur); - (void) GetEventParameter(event, kEventParamCustomMaxValue, typeLongInteger, NULL, sizeof(max), NULL, &max); - (void) GetEventParameter(event, kEventParamCustomText, typeCFStringRef, NULL, sizeof(text), NULL, &text); - - err = setProgress(cur, max); - if(err == noErr) - { - if(text != NULL) - { - setProgressText(text); - } - } - - result = noErr; - } - else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomDone)) - { - // We're done. Exit the modal loop. - QuitAppModalLoopForWindow(gWindow); - result = noErr; - } - - return(result); -} - -#if 0 -size_t curl_download_callback(void *data, size_t size, size_t nmemb, - void *user_data) -{ - S32 bytes = size * nmemb; - char *cdata = (char *) data; - for (int i =0; i < bytes; i += 1) - { - gServerResponse.append(cdata[i]); - } - return bytes; -} -#endif - -int curl_progress_callback_func(void *clientp, - double dltotal, - double dlnow, - double ultotal, - double ulnow) -{ - int max = (int)(dltotal / 1024.0); - int cur = (int)(dlnow / 1024.0); - sendProgress(cur, max); - - if(gCancelled) - return(1); - - return(0); -} - -int parse_args(int argc, char **argv) -{ - int j; - - for (j = 1; j < argc; j++) - { - if ((!strcmp(argv[j], "-url")) && (++j < argc)) - { - gUpdateURL = argv[j]; - } - else if ((!strcmp(argv[j], "-name")) && (++j < argc)) - { - gProductName = argv[j]; - } - else if ((!strcmp(argv[j], "-bundleid")) && (++j < argc)) - { - gBundleID = argv[j]; - } - else if ((!strcmp(argv[j], "-dmg")) && (++j < argc)) - { - gDmgFile = argv[j]; - } - else if ((!strcmp(argv[j], "-marker")) && (++j < argc)) - { - gMarkerPath = argv[j];; - } - } - - return 0; -} - -int main(int argc, char **argv) -{ - // We assume that all the logs we're looking for reside on the current drive - gDirUtilp->initAppDirs("SecondLife"); - - LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - - // Rename current log file to ".old" - std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log.old"); - std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); - LLFile::rename(log_file.c_str(), old_log_file.c_str()); - - // Set the log file to updater.log - LLError::logToFile(log_file); - - ///////////////////////////////////////// - // - // Process command line arguments - // - gUpdateURL = NULL; - gProductName = NULL; - gBundleID = NULL; - gDmgFile = NULL; - gMarkerPath = NULL; - parse_args(argc, argv); - if ((gUpdateURL == NULL) && (gDmgFile == NULL)) - { - llinfos << "Usage: mac_updater -url | -dmg [-name ] [-program ]" << llendl; - exit(1); - } - else - { - llinfos << "Update url is: " << gUpdateURL << llendl; - if (gProductName) - { - llinfos << "Product name is: " << gProductName << llendl; - } - else - { - gProductName = "Second Life"; - } - if (gBundleID) - { - llinfos << "Bundle ID is: " << gBundleID << llendl; - } - else - { - gBundleID = "com.secondlife.indra.viewer"; - } - } - - llinfos << "Starting " << gProductName << " Updater" << llendl; - - // Real UI... - OSStatus err; - IBNibRef nib = NULL; - - err = CreateNibReference(CFSTR("AutoUpdater"), &nib); - - char windowTitle[MAX_PATH]; /* Flawfinder: ignore */ - snprintf(windowTitle, sizeof(windowTitle), "%s Updater", gProductName); - CFStringRef windowTitleRef = NULL; - windowTitleRef = CFStringCreateWithCString(NULL, windowTitle, kCFStringEncodingUTF8); - - if(err == noErr) - { - err = CreateWindowFromNib(nib, CFSTR("Updater"), &gWindow); - } - - if (err == noErr) - { - err = SetWindowTitleWithCFString(gWindow, windowTitleRef); - } - CFRelease(windowTitleRef); - - if(err == noErr) - { - // Set up an event handler for the window. - EventTypeSpec handlerEvents[] = - { - { kEventClassCommand, kEventCommandProcess }, - { kEventClassCustom, kEventCustomProgress }, - { kEventClassCustom, kEventCustomDone } - }; - InstallStandardEventHandler(GetWindowEventTarget(gWindow)); - InstallWindowEventHandler( - gWindow, - NewEventHandlerUPP(dialogHandler), - GetEventTypeCount (handlerEvents), - handlerEvents, - 0, - &gEventHandler); - } - - if(err == noErr) - { - ShowWindow(gWindow); - SelectWindow(gWindow); - } - - if(err == noErr) - { - pthread_create(&updatethread, - NULL, - &updatethreadproc, - NULL); - - } - - if(err == noErr) - { - RunAppModalLoopForWindow(gWindow); - } - - void *threadresult; - - pthread_join(updatethread, &threadresult); - - if(!gCancelled && (gFailure != noErr)) - { - // Something went wrong. Since we always just tell the user to download a new version, we don't really care what. - AlertStdCFStringAlertParamRec params; - SInt16 retval_mac = 1; - DialogRef alert = NULL; - OSStatus err; - - params.version = kStdCFStringAlertVersionOne; - params.movable = false; - params.helpButton = false; - params.defaultText = (CFStringRef)kAlertDefaultOKText; - params.cancelText = 0; - params.otherText = 0; - params.defaultButton = 1; - params.cancelButton = 0; - params.position = kWindowDefaultPosition; - params.flags = 0; - - err = CreateStandardAlert( - kAlertStopAlert, - CFSTR("Error"), - CFSTR("An error occurred while updating Second Life. Please download the latest version from www.secondlife.com."), - ¶ms, - &alert); - - if(err == noErr) - { - err = RunStandardAlert( - alert, - NULL, - &retval_mac); - } - - if(gMarkerPath != 0) - { - // Create a install fail marker that can be used by the viewer to - // detect install problems. - std::ofstream stream(gMarkerPath); - if(stream) stream << -1; - } - exit(-1); - } else { - exit(0); - } - - if(gWindow != NULL) - { - DisposeWindow(gWindow); - } - - if(nib != NULL) - { - DisposeNibReference(nib); - } - - return 0; -} - -bool isDirWritable(FSRef &dir) -{ - bool result = false; - - // Test for a writable directory by creating a directory, then deleting it again. - // This is kinda lame, but will pretty much always give the right answer. - - OSStatus err = noErr; - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - - err = FSRefMakePath(&dir, (UInt8*)temp, sizeof(temp)); - - if(err == noErr) - { - strncat(temp, "/.test_XXXXXX", (sizeof(temp) - strlen(temp)) - 1); - - if(mkdtemp(temp) != NULL) - { - // We were able to make the directory. This means the directory is writable. - result = true; - - // Clean up. - rmdir(temp); - } - } - -#if 0 - // This seemed like a good idea, but won't tell us if we're on a volume mounted read-only. - UInt8 perm; - err = FSGetUserPrivilegesPermissions(&targetParentRef, &perm, NULL); - if(err == noErr) - { - if(perm & kioACUserNoMakeChangesMask) - { - // Parent directory isn't writable. - llinfos << "Target parent directory not writable." << llendl; - err = -1; - replacingTarget = false; - } - } -#endif - - return result; -} - -static std::string HFSUniStr255_to_utf8str(const HFSUniStr255* src) -{ - llutf16string string16((U16*)&(src->unicode), src->length); - std::string result = utf16str_to_utf8str(string16); - return result; -} - -int restoreObject(const char* aside, const char* target, const char* path, const char* object) -{ - char source[PATH_MAX] = ""; /* Flawfinder: ignore */ - char dest[PATH_MAX] = ""; /* Flawfinder: ignore */ - snprintf(source, sizeof(source), "%s/%s/%s", aside, path, object); - snprintf(dest, sizeof(dest), "%s/%s", target, path); - FSRef sourceRef; - FSRef destRef; - OSStatus err; - err = FSPathMakeRef((UInt8 *)source, &sourceRef, NULL); - if(err != noErr) return false; - err = FSPathMakeRef((UInt8 *)dest, &destRef, NULL); - if(err != noErr) return false; - - llinfos << "Copying " << source << " to " << dest << llendl; - - err = FSCopyObjectSync( - &sourceRef, - &destRef, - NULL, - NULL, - kFSFileOperationOverwrite); - - if(err != noErr) return false; - return true; -} - -// Replace any mention of "Second Life" with the product name. -void filterFile(const char* filename) -{ - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - // First copy the target's version, so we can run it through sed. - snprintf(temp, sizeof(temp), "cp '%s' '%s.tmp'", filename, filename); - system(temp); /* Flawfinder: ignore */ - - // Now run it through sed. - snprintf(temp, sizeof(temp), - "sed 's/Second Life/%s/g' '%s.tmp' > '%s'", gProductName, filename, filename); - system(temp); /* Flawfinder: ignore */ -} - -static bool isFSRefViewerBundle(FSRef *targetRef) -{ - bool result = false; - CFURLRef targetURL = NULL; - CFBundleRef targetBundle = NULL; - CFStringRef targetBundleID = NULL; - CFStringRef sourceBundleID = NULL; - - targetURL = CFURLCreateFromFSRef(NULL, targetRef); - - if(targetURL == NULL) - { - llinfos << "Error creating target URL." << llendl; - } - else - { - targetBundle = CFBundleCreate(NULL, targetURL); - } - - if(targetBundle == NULL) - { - llinfos << "Failed to create target bundle." << llendl; - } - else - { - targetBundleID = CFBundleGetIdentifier(targetBundle); - } - - if(targetBundleID == NULL) - { - llinfos << "Couldn't retrieve target bundle ID." << llendl; - } - else - { - sourceBundleID = CFStringCreateWithCString(NULL, gBundleID, kCFStringEncodingUTF8); - if(CFStringCompare(sourceBundleID, targetBundleID, 0) == kCFCompareEqualTo) - { - // This is the bundle we're looking for. - result = true; - } - else - { - llinfos << "Target bundle ID mismatch." << llendl; - } - } - - // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released. - if(targetURL != NULL) - CFRelease(targetURL); - if(targetBundle != NULL) - CFRelease(targetBundle); - - return result; -} - -// Search through the directory specified by 'parent' for an item that appears to be a Second Life viewer. -static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app) -{ - FSIterator iterator; - bool found = false; - - OSErr err = FSOpenIterator( parent, kFSIterateFlat, &iterator ); - if(!err) - { - do - { - ItemCount actualObjects = 0; - Boolean containerChanged = false; - FSCatalogInfo info; - FSRef ref; - HFSUniStr255 unicodeName; - err = FSGetCatalogInfoBulk( - iterator, - 1, - &actualObjects, - &containerChanged, - kFSCatInfoNodeFlags, - &info, - &ref, - NULL, - &unicodeName ); - - if(actualObjects == 0) - break; - - if(!err) - { - // Call succeeded and not done with the iteration. - std::string name = HFSUniStr255_to_utf8str(&unicodeName); - - llinfos << "Considering \"" << name << "\"" << llendl; - - if(info.nodeFlags & kFSNodeIsDirectoryMask) - { - // This is a directory. See if it's a .app - if(name.find(".app") != std::string::npos) - { - // Looks promising. Check to see if it has the right bundle identifier. - if(isFSRefViewerBundle(&ref)) - { - llinfos << name << " is the one" << llendl; - // This is the one. Return it. - *app = ref; - found = true; - break; - } else { - llinfos << name << " is not the bundle we are looking for; move along" << llendl; - } - - } - } - } - } - while(!err); - - llinfos << "closing the iterator" << llendl; - - FSCloseIterator(iterator); - - llinfos << "closed" << llendl; - } - - if(!err && !found) - err = fnfErr; - - return err; -} - -void *updatethreadproc(void*) -{ - char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ - FSRef tempDirRef; - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - // *NOTE: This buffer length is used in a scanf() below. - char deviceNode[1024] = ""; /* Flawfinder: ignore */ - LLFILE *downloadFile = NULL; - OSStatus err; - ProcessSerialNumber psn; - char target[PATH_MAX] = ""; /* Flawfinder: ignore */ - FSRef targetRef; - FSRef targetParentRef; - FSVolumeRefNum targetVol; - FSRef trashFolderRef; - Boolean replacingTarget = false; - - memset(&tempDirRef, 0, sizeof(tempDirRef)); - memset(&targetRef, 0, sizeof(targetRef)); - memset(&targetParentRef, 0, sizeof(targetParentRef)); - - try - { - // Attempt to get a reference to the Second Life application bundle containing this updater. - // Any failures during this process will cause us to default to updating /Applications/Second Life.app - { - FSRef myBundle; - - err = GetCurrentProcess(&psn); - if(err == noErr) - { - err = GetProcessBundleLocation(&psn, &myBundle); - } - - if(err == noErr) - { - // Sanity check: Make sure the name of the item referenced by targetRef is "Second Life.app". - FSRefMakePath(&myBundle, (UInt8*)target, sizeof(target)); - - llinfos << "Updater bundle location: " << target << llendl; - } - - // Our bundle should be in Second Life.app/Contents/Resources/AutoUpdater.app - // so we need to go up 3 levels to get the path to the main application bundle. - if(err == noErr) - { - err = FSGetCatalogInfo(&myBundle, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); - } - if(err == noErr) - { - err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); - } - if(err == noErr) - { - err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); - } - - // And once more to get the parent of the target - if(err == noErr) - { - err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetParentRef); - } - - if(err == noErr) - { - FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); - llinfos << "Path to target: " << target << llendl; - } - - // Sanity check: make sure the target is a bundle with the right identifier - if(err == noErr) - { - // Assume the worst... - err = -1; - - if(isFSRefViewerBundle(&targetRef)) - { - // This is the bundle we're looking for. - err = noErr; - replacingTarget = true; - } - } - - // Make sure the target's parent directory is writable. - if(err == noErr) - { - if(!isDirWritable(targetParentRef)) - { - // Parent directory isn't writable. - llinfos << "Target parent directory not writable." << llendl; - err = -1; - replacingTarget = false; - } - } - - if(err != noErr) - { - Boolean isDirectory; - llinfos << "Target search failed, defaulting to /Applications/" << gProductName << ".app." << llendl; - - // Set up the parent directory - err = FSPathMakeRef((UInt8*)"/Applications", &targetParentRef, &isDirectory); - if((err != noErr) || (!isDirectory)) - { - // We're so hosed. - llinfos << "Applications directory not found, giving up." << llendl; - throw 0; - } - - snprintf(target, sizeof(target), "/Applications/%s.app", gProductName); - - memset(&targetRef, 0, sizeof(targetRef)); - err = FSPathMakeRef((UInt8*)target, &targetRef, NULL); - if(err == fnfErr) - { - // This is fine, just means we're not replacing anything. - err = noErr; - replacingTarget = false; - } - else - { - replacingTarget = true; - } - - // Make sure the target's parent directory is writable. - if(err == noErr) - { - if(!isDirWritable(targetParentRef)) - { - // Parent directory isn't writable. - llinfos << "Target parent directory not writable." << llendl; - err = -1; - replacingTarget = false; - } - } - - } - - // If we haven't fixed all problems by this point, just bail. - if(err != noErr) - { - llinfos << "Unable to pick a target, giving up." << llendl; - throw 0; - } - } - - // Find the volID of the volume the target resides on - { - FSCatalogInfo info; - err = FSGetCatalogInfo( - &targetParentRef, - kFSCatInfoVolume, - &info, - NULL, - NULL, - NULL); - - if(err != noErr) - throw 0; - - targetVol = info.volume; - } - - // Find the temporary items and trash folders on that volume. - err = FSFindFolder( - targetVol, - kTrashFolderType, - true, - &trashFolderRef); - - if(err != noErr) - throw 0; - -#if 0 // *HACK for DEV-11935 see below for details. - - FSRef tempFolderRef; - - err = FSFindFolder( - targetVol, - kTemporaryFolderType, - true, - &tempFolderRef); - - if(err != noErr) - throw 0; - - err = FSRefMakePath(&tempFolderRef, (UInt8*)temp, sizeof(temp)); - - if(err != noErr) - throw 0; - -#else - - // *HACK for DEV-11935 the above kTemporaryFolderType query was giving - // back results with path names that seem to be too long to be used as - // mount points. I suspect this incompatibility was introduced in the - // Leopard 10.5.2 update, but I have not verified this. - char const HARDCODED_TMP[] = "/tmp"; - strncpy(temp, HARDCODED_TMP, sizeof(HARDCODED_TMP)); - -#endif // 0 *HACK for DEV-11935 - - // Skip downloading the file if the dmg was passed on the command line. - std::string dmgName; - if(gDmgFile != NULL) { - dmgName = basename((char *)gDmgFile); - char * dmgDir = dirname((char *)gDmgFile); - strncpy(tempDir, dmgDir, sizeof(tempDir)); - err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); - if(err != noErr) throw 0; - chdir(tempDir); - goto begin_install; - } else { - // Continue on to download file. - dmgName = "SecondLife.dmg"; - } - - - strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1); - if(mkdtemp(temp) == NULL) - { - throw 0; - } - - strncpy(tempDir, temp, sizeof(tempDir)); - temp[sizeof(tempDir) - 1] = '\0'; - - llinfos << "tempDir is " << tempDir << llendl; - - err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); - - if(err != noErr) - throw 0; - - chdir(tempDir); - - snprintf(temp, sizeof(temp), "SecondLife.dmg"); - - downloadFile = LLFile::fopen(temp, "wb"); /* Flawfinder: ignore */ - if(downloadFile == NULL) - { - throw 0; - } - - { - CURL *curl = curl_easy_init(); - - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback); - curl_easy_setopt(curl, CURLOPT_FILE, downloadFile); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func); - curl_easy_setopt(curl, CURLOPT_URL, gUpdateURL); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - - sendProgress(0, 1, CFSTR("Downloading...")); - - CURLcode result = curl_easy_perform(curl); - - curl_easy_cleanup(curl); - - if(gCancelled) - { - llinfos << "User cancel, bailing out."<< llendl; - throw 0; - } - - if(result != CURLE_OK) - { - llinfos << "Error " << result << " while downloading disk image."<< llendl; - throw 0; - } - - fclose(downloadFile); - downloadFile = NULL; - } - - begin_install: - sendProgress(0, 0, CFSTR("Mounting image...")); - LLFile::mkdir("mnt", 0700); - - // NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder, - // but if our cleanup fails, this makes it much harder for the user to unmount the image. - std::string mountOutput; - boost::format cmdFormat("hdiutil attach %s -mountpoint mnt"); - cmdFormat % dmgName; - FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */ - - if(mounter == NULL) - { - llinfos << "Failed to mount disk image, exiting."<< llendl; - throw 0; - } - - // We need to scan the output from hdiutil to find the device node it uses to attach the disk image. - // If we don't have this information, we can't detach it later. - while(mounter != NULL) - { - size_t len = fread(temp, 1, sizeof(temp)-1, mounter); - temp[len] = 0; - mountOutput.append(temp); - if(len < sizeof(temp)-1) - { - // End of file or error. - int result = pclose(mounter); - if(result != 0) - { - // NOTE: We used to abort here, but pclose() started returning - // -1, possibly when the size of the DMG passed a certain point - llinfos << "Unexpected result closing pipe: " << result << llendl; - } - mounter = NULL; - } - } - - if(!mountOutput.empty()) - { - const char *s = mountOutput.c_str(); - const char *prefix = "/dev/"; - char *sub = strstr(s, prefix); - - if(sub != NULL) - { - sub += strlen(prefix); /* Flawfinder: ignore */ - sscanf(sub, "%1023s", deviceNode); /* Flawfinder: ignore */ - } - } - - if(deviceNode[0] != 0) - { - llinfos << "Disk image attached on /dev/" << deviceNode << llendl; - } - else - { - llinfos << "Disk image device node not found!" << llendl; - throw 0; - } - - // Get an FSRef to the new application on the disk image - FSRef sourceRef; - FSRef mountRef; - snprintf(temp, sizeof(temp), "%s/mnt", tempDir); - - llinfos << "Disk image mount point is: " << temp << llendl; - - err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL); - if(err != noErr) - { - llinfos << "Couldn't make FSRef to disk image mount point." << llendl; - throw 0; - } - - sendProgress(0, 0, CFSTR("Searching for the app bundle...")); - err = findAppBundleOnDiskImage(&mountRef, &sourceRef); - if(err != noErr) - { - llinfos << "Couldn't find application bundle on mounted disk image." << llendl; - throw 0; - } - else - { - llinfos << "found the bundle." << llendl; - } - - sendProgress(0, 0, CFSTR("Preparing to copy files...")); - - FSRef asideRef; - char aside[MAX_PATH]; /* Flawfinder: ignore */ - - // this will hold the name of the destination target - CFStringRef appNameRef; - - if(replacingTarget) - { - // Get the name of the target we're replacing - HFSUniStr255 appNameUniStr; - err = FSGetCatalogInfo(&targetRef, 0, NULL, &appNameUniStr, NULL, NULL); - if(err != noErr) - throw 0; - appNameRef = FSCreateStringFromHFSUniStr(NULL, &appNameUniStr); - - // Move aside old version (into work directory) - err = FSMoveObject(&targetRef, &tempDirRef, &asideRef); - if(err != noErr) - { - llwarns << "failed to move aside old version (error code " << - err << ")" << llendl; - throw 0; - } - - // Grab the path for later use. - err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside)); - } - else - { - // Construct the name of the target based on the product name - char appName[MAX_PATH]; /* Flawfinder: ignore */ - snprintf(appName, sizeof(appName), "%s.app", gProductName); - appNameRef = CFStringCreateWithCString(NULL, appName, kCFStringEncodingUTF8); - } - - sendProgress(0, 0, CFSTR("Copying files...")); - - llinfos << "Starting copy..." << llendl; - - // Copy the new version from the disk image to the target location. - err = FSCopyObjectSync( - &sourceRef, - &targetParentRef, - appNameRef, - &targetRef, - kFSFileOperationDefaultOptions); - - // Grab the path for later use. - err = FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); - if(err != noErr) - throw 0; - - llinfos << "Copy complete. Target = " << target << llendl; - - if(err != noErr) - { - // Something went wrong during the copy. Attempt to put the old version back and bail. - (void)FSDeleteObject(&targetRef); - if(replacingTarget) - { - (void)FSMoveObject(&asideRef, &targetParentRef, NULL); - } - throw 0; - } - else - { - // The update has succeeded. Clear the cache directory. - - sendProgress(0, 0, CFSTR("Clearing cache...")); - - llinfos << "Clearing cache..." << llendl; - - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); - - llinfos << "Clear complete." << llendl; - - } - } - catch(...) - { - if(!gCancelled) - if(gFailure == noErr) - gFailure = -1; - } - - // Failures from here on out are all non-fatal and not reported. - sendProgress(0, 3, CFSTR("Cleaning up...")); - - // Close disk image file if necessary - if(downloadFile != NULL) - { - llinfos << "Closing download file." << llendl; - - fclose(downloadFile); - downloadFile = NULL; - } - - sendProgress(1, 3); - // Unmount image - if(deviceNode[0] != 0) - { - llinfos << "Detaching disk image." << llendl; - - snprintf(temp, sizeof(temp), "hdiutil detach '%s'", deviceNode); - system(temp); /* Flawfinder: ignore */ - } - - sendProgress(2, 3); - - // Move work directory to the trash - if(tempDir[0] != 0) - { - llinfos << "Moving work directory to the trash." << llendl; - - FSRef trashRef; - OSStatus err = FSMoveObjectToTrashSync(&tempDirRef, &trashRef, 0); - if(err != noErr) { - llwarns << "failed to move files to trash, (error code " << - err << ")" << llendl; - } - } - - if(!gCancelled && !gFailure && (target[0] != 0)) - { - llinfos << "Touching application bundle." << llendl; - - snprintf(temp, sizeof(temp), "touch '%s'", target); - system(temp); /* Flawfinder: ignore */ - - llinfos << "Launching updated application." << llendl; - - snprintf(temp, sizeof(temp), "open '%s'", target); - system(temp); /* Flawfinder: ignore */ - } - - sendDone(); - - return(NULL); -} - -#if LL_DARWIN -#pragma GCC diagnostic warning "-Wdeprecated-declarations" -#endif -- cgit v1.2.3 From 2d316dff3dda88e12ee64b33e22682f24c7ef4fa Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 12 Aug 2014 15:41:24 -0400 Subject: Remove old Windows updater executable from source tree and CMake. --- indra/CMakeLists.txt | 5 +- indra/newview/CMakeLists.txt | 2 - indra/win_updater/CMakeLists.txt | 45 ---- indra/win_updater/updater.cpp | 516 --------------------------------------- 4 files changed, 2 insertions(+), 566 deletions(-) delete mode 100755 indra/win_updater/CMakeLists.txt delete mode 100755 indra/win_updater/updater.cpp diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 410d25ad97..5c3f3713e3 100755 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -86,9 +86,8 @@ elseif (WINDOWS) if (EXISTS ${VIEWER_DIR}win_setup) add_subdirectory(${VIEWER_DIR}win_setup) endif (EXISTS ${VIEWER_DIR}win_setup) - add_subdirectory(${VIEWER_PREFIX}win_updater) - # add_dependencies(viewer windows-updater windows-setup windows-crash-logger) - add_dependencies(viewer windows-updater windows-crash-logger) + # add_dependencies(viewer windows-setup windows-crash-logger) + add_dependencies(viewer windows-crash-logger) elseif (SOLARIS) add_subdirectory(solaris_crash_logger) add_dependencies(viewer solaris-crash-logger) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3e296c8d9f..b1625ca1d7 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1765,7 +1765,6 @@ if (WINDOWS) media_plugin_webkit winmm_shim windows-crash-logger - windows-updater ) if (FMODEX) @@ -1811,7 +1810,6 @@ if (WINDOWS) add_dependencies(${VIEWER_BINARY_NAME} SLPlugin - windows-updater windows-crash-logger ) diff --git a/indra/win_updater/CMakeLists.txt b/indra/win_updater/CMakeLists.txt deleted file mode 100755 index 210486c668..0000000000 --- a/indra/win_updater/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# -*- cmake -*- - -project(win_updater) - -include(00-Common) -include(LLCommon) -include(Linking) - -# *HACK - override msvcrt implementation (intialized on 00-Common) to be -# statically linked for the installer this relies on vc taking the last flag on -# the command line -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ) - -set(win_updater_SOURCE_FILES updater.cpp) - -set(win_updater_HEADER_FILES CMakeLists.txt) - -set_source_files_properties(${win_updater_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND win_updater_SOURCE_FILES ${win_updater_HEADER_FILES}) - -add_executable(windows-updater WIN32 ${win_updater_SOURCE_FILES}) - -target_link_libraries(windows-updater - wininet - user32 - gdi32 - shell32 - ) - -set_target_properties(windows-updater - PROPERTIES - LINK_FLAGS "/NODEFAULTLIB:MSVCRT" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;MSVCRT\"" - ) - -# The windows-updater doesn't link against anything non-system, apparently -#ll_deploy_sharedlibs_command(windows-updater) diff --git a/indra/win_updater/updater.cpp b/indra/win_updater/updater.cpp deleted file mode 100755 index aeab5a3b13..0000000000 --- a/indra/win_updater/updater.cpp +++ /dev/null @@ -1,516 +0,0 @@ -/** - * @file updater.cpp - * @brief Windows auto-updater - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// -// Usage: updater -url -// - -// We use dangerous fopen, strtok, mbstowcs, sprintf -// which generates warnings on VC2005. -// *TODO: Switch to fopen_s, strtok_s, etc. -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include -#include -#include -#include -#include -#include -#include - -#define BUFSIZE 8192 - -int gTotalBytesRead = 0; -DWORD gTotalBytes = -1; -HWND gWindow = NULL; -WCHAR gProgress[256]; -char* gUpdateURL = NULL; - -#if _DEBUG -std::ofstream logfile; -#define DEBUG(expr) logfile << expr << std::endl -#else -#define DEBUG(expr) /**/ -#endif - -char* wchars_to_utf8chars(const WCHAR* in_chars) -{ - int tlen = 0; - const WCHAR* twc = in_chars; - while (*twc++ != 0) - { - tlen++; - } - char* outchars = new char[tlen]; - char* res = outchars; - for (int i=0; i - static RESULT check(const std::string& desc, RESULT result) - { - if (result) - { - // success, show caller - return result; - } - DWORD err = GetLastError(); - std::ostringstream out; - out << desc << " Failed: " << err; - DEBUG(out.str()); - throw InetError(out.str()); - } - - HINTERNET openUrl(const std::wstring& uri) const; - HINTERNET openInet() const; - - HINTERNET mInet, mDownload; -}; - -HINTERNET Fetcher::openInet() const -{ - DEBUG("Calling InternetOpen"); - // Init wininet subsystem - return check("InternetOpen", - InternetOpen(L"LindenUpdater", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0)); -} - -HINTERNET Fetcher::openUrl(const std::wstring& uri) const -{ - DEBUG("Calling InternetOpenUrl: " << wchars_to_utf8chars(uri.c_str())); - return check("InternetOpenUrl", - InternetOpenUrl(mInet, uri.c_str(), NULL, 0, INTERNET_FLAG_NEED_FILE, NULL)); -} - -unsigned long Fetcher::read(char* buffer, size_t bufflen) const -{ - unsigned long bytes_read = 0; - DEBUG("Calling InternetReadFile"); - check("InternetReadFile", - InternetReadFile(mDownload, buffer, bufflen, &bytes_read)); - return bytes_read; -} - -int WINAPI get_url_into_file(const std::wstring& uri, const std::string& path, int *cancelled) -{ - int success = FALSE; - *cancelled = FALSE; - - DEBUG("Opening '" << path << "'"); - - FILE* fp = fopen(path.c_str(), "wb"); /* Flawfinder: ignore */ - - if (!fp) - { - DEBUG("Failed to open '" << path << "'"); - return success; - } - - // Note, ctor can throw, since it uses check() function. - Fetcher fetcher(uri); - gTotalBytes = fetcher.getTotalBytes(); - -/*==========================================================================*| - // nobody uses total_bytes?!? What's this doing here? - DWORD total_bytes = 0; - success = check("InternetQueryDataAvailable", - InternetQueryDataAvailable(hdownload, &total_bytes, 0, 0)); -|*==========================================================================*/ - - success = FALSE; - while(!success && !(*cancelled)) - { - char data[BUFSIZE]; /* Flawfinder: ignore */ - unsigned long bytes_read = fetcher.read(data, sizeof(data)); - - if (!bytes_read) - { - DEBUG("InternetReadFile Read " << bytes_read << " bytes."); - } - - DEBUG("Reading Data, bytes_read = " << bytes_read); - - if (bytes_read == 0) - { - // If InternetFileRead returns TRUE AND bytes_read == 0 - // we've successfully downloaded the entire file - wsprintf(gProgress, L"Download complete."); - success = TRUE; - } - else - { - // write what we've got, then continue - fwrite(data, sizeof(char), bytes_read, fp); - - gTotalBytesRead += int(bytes_read); - - if (gTotalBytes != -1) - wsprintf(gProgress, L"Downloaded: %d%%", 100 * gTotalBytesRead / gTotalBytes); - else - wsprintf(gProgress, L"Downloaded: %dK", gTotalBytesRead / 1024); - - } - - DEBUG("Calling InvalidateRect"); - - // Mark the window as needing redraw (of the whole thing) - InvalidateRect(gWindow, NULL, TRUE); - - // Do the redraw - DEBUG("Calling UpdateWindow"); - UpdateWindow(gWindow); - - DEBUG("Calling PeekMessage"); - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - - if (msg.message == WM_QUIT) - { - // bail out, user cancelled - *cancelled = TRUE; - } - } - } - - fclose(fp); - return success; -} - -LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) -{ - HDC hdc; // Drawing context - PAINTSTRUCT ps; - - switch(message) - { - case WM_PAINT: - { - hdc = BeginPaint(hwnd, &ps); - - RECT rect; - GetClientRect(hwnd, &rect); - DrawText(hdc, gProgress, -1, &rect, - DT_SINGLELINE | DT_CENTER | DT_VCENTER); - - EndPaint(hwnd, &ps); - return 0; - } - case WM_CLOSE: - case WM_DESTROY: - // Get out of full screen - // full_screen_mode(false); - PostQuitMessage(0); - return 0; - } - return DefWindowProc(hwnd, message, wparam, lparam); -} - -#define win_class_name L"FullScreen" - -int parse_args(int argc, char **argv) -{ - int j; - - for (j = 1; j < argc; j++) - { - if ((!strcmp(argv[j], "-url")) && (++j < argc)) - { - gUpdateURL = argv[j]; - } - } - - // If nothing was set, let the caller know. - if (!gUpdateURL) - { - return 1; - } - return 0; -} - -int WINAPI -WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) -{ - // Parse the command line. - LPSTR cmd_line_including_exe_name = GetCommandLineA(); - - const int MAX_ARGS = 100; - int argc = 0; - char* argv[MAX_ARGS]; /* Flawfinder: ignore */ - -#if _DEBUG - logfile.open("updater.log", std::ios_base::out); - DEBUG("Parsing command arguments"); -#endif - - char *token = NULL; - if( cmd_line_including_exe_name[0] == '\"' ) - { - // Exe name is enclosed in quotes - token = strtok( cmd_line_including_exe_name, "\"" ); - argv[argc++] = token; - token = strtok( NULL, " \t," ); - } - else - { - // Exe name is not enclosed in quotes - token = strtok( cmd_line_including_exe_name, " \t," ); - } - - while( (token != NULL) && (argc < MAX_ARGS) ) - { - argv[argc++] = token; - /* Get next token: */ - if (*(token + strlen(token) + 1) == '\"') /* Flawfinder: ignore */ - { - token = strtok( NULL, "\""); - } - else - { - token = strtok( NULL, " \t," ); - } - } - - gUpdateURL = NULL; - - ///////////////////////////////////////// - // - // Process command line arguments - // - - DEBUG("Processing command arguments"); - - // - // Parse the command line arguments - // - int parse_args_result = parse_args(argc, argv); - - WNDCLASSEX wndclassex = { 0 }; - //DEVMODE dev_mode = { 0 }; - - const int WINDOW_WIDTH = 250; - const int WINDOW_HEIGHT = 100; - - wsprintf(gProgress, L"Connecting..."); - - /* Init the WNDCLASSEX */ - wndclassex.cbSize = sizeof(WNDCLASSEX); - wndclassex.style = CS_HREDRAW | CS_VREDRAW; - wndclassex.hInstance = hInstance; - wndclassex.lpfnWndProc = WinProc; - wndclassex.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); - wndclassex.lpszClassName = win_class_name; - - RegisterClassEx(&wndclassex); - - // Get the size of the screen - //EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); - - gWindow = CreateWindowEx(NULL, win_class_name, - L"Second Life Updater", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - WINDOW_WIDTH, - WINDOW_HEIGHT, - NULL, NULL, hInstance, NULL); - - ShowWindow(gWindow, nShowCmd); - UpdateWindow(gWindow); - - if (parse_args_result) - { - MessageBox(gWindow, - L"Usage: updater -url [-name ] [-program ] [-silent]", - L"Usage", MB_OK); - return parse_args_result; - } - - // Did we get a userserver to work with? - if (!gUpdateURL) - { - MessageBox(gWindow, L"Please specify the download url from the command line", - L"Error", MB_OK); - return 1; - } - - // Can't feed GetTempPath into GetTempFile directly - char temp_path[MAX_PATH]; /* Flawfinder: ignore */ - if (0 == GetTempPathA(sizeof(temp_path), temp_path)) - { - MessageBox(gWindow, L"Problem with GetTempPath()", - L"Error", MB_OK); - return 1; - } - std::string update_exec_path(temp_path); - update_exec_path.append("Second_Life_Updater.exe"); - - WCHAR update_uri[4096]; - mbstowcs(update_uri, gUpdateURL, sizeof(update_uri)); - - int success = 0; - int cancelled = 0; - - // Actually do the download - try - { - DEBUG("Calling get_url_into_file"); - success = get_url_into_file(update_uri, update_exec_path, &cancelled); - } - catch (const Fetcher::InetError& e) - { - (void)e; - success = FALSE; - DEBUG("Caught: " << e.what()); - } - - // WinInet can't tell us if we got a 404 or not. Therefor, we check - // for the size of the downloaded file, and assume that our installer - // will always be greater than 1MB. - if (gTotalBytesRead < (1024 * 1024) && ! cancelled) - { - MessageBox(gWindow, - L"The Second Life auto-update has failed.\n" - L"The problem may be caused by other software installed \n" - L"on your computer, such as a firewall.\n" - L"Please visit http://secondlife.com/download/ \n" - L"to download the latest version of Second Life.\n", - NULL, MB_OK); - return 1; - } - - if (cancelled) - { - // silently exit - return 0; - } - - if (!success) - { - MessageBox(gWindow, - L"Second Life download failed.\n" - L"Please try again later.", - NULL, MB_OK); - return 1; - } - - // TODO: Make updates silent (with /S to NSIS) - //char params[256]; /* Flawfinder: ignore */ - //sprintf(params, "/S"); /* Flawfinder: ignore */ - //MessageBox(gWindow, - // L"Updating Second Life.\n\nSecond Life will automatically start once the update is complete. This may take a minute...", - // L"Download Complete", - // MB_OK); - -/*==========================================================================*| - // DEV-31680: ShellExecuteA() causes McAfee-GW-Edition and AntiVir - // scanners to flag this executable as a probable virus vector. - // Less than or equal to 32 means failure - if (32 >= (int) ShellExecuteA(gWindow, "open", update_exec_path.c_str(), NULL, - "C:\\", SW_SHOWDEFAULT)) -|*==========================================================================*/ - // from http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx - STARTUPINFOA si; - PROCESS_INFORMATION pi; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - - if (! CreateProcessA(update_exec_path.c_str(), // executable file - NULL, // command line - NULL, // process cannot be inherited - NULL, // thread cannot be inherited - FALSE, // do not inherit existing handles - 0, // process creation flags - NULL, // inherit parent's environment - NULL, // inherit parent's current dir - &si, // STARTUPINFO - &pi)) // PROCESS_INFORMATION - { - MessageBox(gWindow, L"Update failed. Please try again later.", NULL, MB_OK); - return 1; - } - - // Give installer some time to open a window - Sleep(1000); - - return 0; -} -- cgit v1.2.3 From b603812fac01591951092c0ceba30277f2fb013d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 12 Aug 2014 15:44:09 -0400 Subject: Remove old linux_updater executable from source tree and CMake. --- indra/CMakeLists.txt | 1 - indra/linux_updater/CMakeLists.txt | 57 --- indra/linux_updater/linux_updater.cpp | 926 ---------------------------------- 3 files changed, 984 deletions(-) delete mode 100644 indra/linux_updater/CMakeLists.txt delete mode 100644 indra/linux_updater/linux_updater.cpp diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 5c3f3713e3..24ea59ca49 100755 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -71,7 +71,6 @@ add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) if (LINUX) add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) - add_subdirectory(${VIEWER_PREFIX}linux_updater) if (INSTALL_PROPRIETARY) include(LLAppearanceUtility) add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR}) diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt deleted file mode 100644 index 4a9e82f9b6..0000000000 --- a/indra/linux_updater/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# -*- cmake -*- - -project(linux_updater) - -include(00-Common) -include(CURL) -include(CARes) -include(OpenSSL) -include(UI) -include(LLCommon) -include(LLMessage) -include(LLVFS) -include(LLXML) -include(LLUI) -include(Linking) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ${LLVFS_INCLUDE_DIRS} - ${LLXML_INCLUDE_DIRS} - ${LLUI_INCLUDE_DIRS} - ${CURL_INCLUDE_DIRS} - ${CARES_INCLUDE_DIRS} - ${OPENSSL_INCLUDE_DIRS} - ${UI_INCLUDE_DIRS} - ) -include_directories(SYSTEM - ${LLCOMMON_SYSTEM_INCLUDE_DIRS} - ${LLXML_SYSTEM_INCLUDE_DIRS} - ) - -set(linux_updater_SOURCE_FILES linux_updater.cpp) - -set(linux_updater_HEADER_FILES CMakeLists.txt) - -set_source_files_properties(${linux_updater_HEADER_FILES} - PROPERTIES HEADER_FILES_ONLY TRUE) - -list(APPEND linux_updater_SOURCE_FILES ${linux_updater_HEADER_FILES}) - -add_executable(linux-updater ${linux_updater_SOURCE_FILES}) - -target_link_libraries(linux-updater - ${CURL_LIBRARIES} - ${CARES_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${CRYPTO_LIBRARIES} - ${LLMESSAGE_LIBRARIES} - ${UI_LIBRARIES} - ${LLXML_LIBRARIES} - ${LLUI_LIBRARIES} - ${LLVFS_LIBRARIES} - ${LLCOMMON_LIBRARIES} - ) - -add_custom_target(linux-updater-target ALL - DEPENDS linux-updater) diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp deleted file mode 100644 index 5c94deba02..0000000000 --- a/indra/linux_updater/linux_updater.cpp +++ /dev/null @@ -1,926 +0,0 @@ -/** - * @file linux_updater.cpp - * @author Kyle Ambroff , Tofu Linden - * @brief Viewer update program for unix platforms that support GTK+ - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include -#include -#include -#include -#include - -#include "linden_common.h" -#include "llerrorcontrol.h" -#include "llfile.h" -#include "lldir.h" -#include "lldiriterator.h" - -/*==========================================================================*| -// IQA-490: Use of LLTrans -- by this program at least -- appears to be buggy. -// With it, the 3.3.2 beta 1 linux-updater.bin crashes; without it seems stable. -#include "llxmlnode.h" -#include "lltrans.h" -|*==========================================================================*/ - -static class LLTrans -{ -public: - LLTrans(); - static std::string getString(const std::string& key); - -private: - std::string _getString(const std::string& key) const; - - typedef std::map MessageMap; - MessageMap mMessages; -} sLLTransInstance; - -#include -#include -#include - -extern "C" { -#include -} - -const guint UPDATE_PROGRESS_TIMEOUT = 100; -const guint UPDATE_PROGRESS_TEXT_TIMEOUT = 1000; -const guint ROTATE_IMAGE_TIMEOUT = 8000; - -typedef struct _updater_app_state { - std::string app_name; - std::string url; - std::string file; - std::string image_dir; - std::string dest_dir; - std::string strings_dirs; - std::string strings_file; - - LLDirIterator *image_dir_iter; - - GtkWidget *window; - GtkWidget *progress_bar; - GtkWidget *image; - - double progress_value; - bool activity_mode; - - guint image_rotation_timeout_id; - guint progress_update_timeout_id; - guint update_progress_text_timeout_id; - - bool failure; -} UpdaterAppState; - -// List of entries from strings.xml to always replace -static std::set default_trans_args; -void init_default_trans_args() -{ - default_trans_args.insert("SECOND_LIFE"); // World - default_trans_args.insert("APP_NAME"); - default_trans_args.insert("SECOND_LIFE_GRID"); - default_trans_args.insert("SUPPORT_SITE"); -} - -bool translate_init(std::string comma_delim_path_list, - std::string base_xml_name) -{ - return true; -/*==========================================================================*| - init_default_trans_args(); - - // extract paths string vector from comma-delimited flat string - std::vector paths; - LLStringUtil::getTokens(comma_delim_path_list, paths, ","); // split over ',' - - for(std::vector::iterator it = paths.begin(), end_it = paths.end(); - it != end_it; - ++it) - { - (*it) = gDirUtilp->findSkinnedFilename(*it, base_xml_name); - } - - // suck the translation xml files into memory - LLXMLNodePtr root; - bool success = LLXMLNode::getLayeredXMLNode(root, paths); - if (!success) - { - // couldn't load string table XML - return false; - } - else - { - // get those strings out of the XML - LLTrans::parseStrings(root, default_trans_args); - return true; - } -|*==========================================================================*/ -} - - -void updater_app_ui_init(void); -void updater_app_quit(UpdaterAppState *app_state); -void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state); -std::string next_image_filename(std::string& image_path, LLDirIterator& iter); -void display_error(GtkWidget *parent, std::string title, std::string message); -BOOL install_package(std::string package_file, std::string destination); -BOOL spawn_viewer(UpdaterAppState *app_state); - -extern "C" { - void on_window_closed(GtkWidget *sender, GdkEvent *event, gpointer state); - gpointer worker_thread_cb(gpointer *data); - int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow); - gboolean rotate_image_cb(gpointer data); - gboolean progress_update_timeout(gpointer data); - gboolean update_progress_text_timeout(gpointer data); -} - -void updater_app_ui_init(UpdaterAppState *app_state) -{ - GtkWidget *vbox; - GtkWidget *summary_label; - GtkWidget *description_label; - GtkWidget *frame; - - llassert(app_state != NULL); - - // set up window and main container - std::string window_title = LLTrans::getString("UpdaterWindowTitle"); - app_state->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(app_state->window), - window_title.c_str()); - gtk_window_set_resizable(GTK_WINDOW(app_state->window), FALSE); - gtk_window_set_position(GTK_WINDOW(app_state->window), - GTK_WIN_POS_CENTER_ALWAYS); - - gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12); - g_signal_connect(G_OBJECT(app_state->window), "delete-event", - G_CALLBACK(on_window_closed), app_state); - - vbox = gtk_vbox_new(FALSE, 6); - gtk_container_add(GTK_CONTAINER(app_state->window), vbox); - - // set top label - std::ostringstream label_ostr; - label_ostr << "" - << LLTrans::getString("UpdaterNowUpdating") - << ""; - - summary_label = gtk_label_new(NULL); - gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE); - gtk_label_set_markup(GTK_LABEL(summary_label), - label_ostr.str().c_str()); - gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0); - - // create the description label - description_label = gtk_label_new(LLTrans::getString("UpdaterUpdatingDescriptive").c_str()); - gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE); - gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbox), description_label, FALSE, FALSE, 0); - - // If an image path has been set, load the background images - if (!app_state->image_dir.empty()) { - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - - // load the first image - app_state->image = gtk_image_new_from_file - (next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str()); - gtk_widget_set_size_request(app_state->image, 340, 310); - gtk_container_add(GTK_CONTAINER(frame), app_state->image); - - // rotate the images every 5 seconds - app_state->image_rotation_timeout_id = g_timeout_add - (ROTATE_IMAGE_TIMEOUT, rotate_image_cb, app_state); - } - - // set up progress bar, and update it roughly every 1/10 of a second - app_state->progress_bar = gtk_progress_bar_new(); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), - LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str()); - gtk_box_pack_start(GTK_BOX(vbox), - app_state->progress_bar, FALSE, TRUE, 0); - app_state->progress_update_timeout_id = g_timeout_add - (UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state); - app_state->update_progress_text_timeout_id = g_timeout_add - (UPDATE_PROGRESS_TEXT_TIMEOUT, update_progress_text_timeout, app_state); - - gtk_widget_show_all(app_state->window); -} - -gboolean rotate_image_cb(gpointer data) -{ - UpdaterAppState *app_state; - std::string filename; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter); - - gdk_threads_enter(); - gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str()); - gdk_threads_leave(); - - return TRUE; -} - -std::string next_image_filename(std::string& image_path, LLDirIterator& iter) -{ - std::string image_filename; - iter.next(image_filename); - return gDirUtilp->add(image_path, image_filename); -} - -void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - updater_app_quit(app_state); -} - -void updater_app_quit(UpdaterAppState *app_state) -{ - if (app_state != NULL) - { - g_source_remove(app_state->progress_update_timeout_id); - - if (!app_state->image_dir.empty()) - { - g_source_remove(app_state->image_rotation_timeout_id); - } - } - - gtk_main_quit(); -} - -void display_error(GtkWidget *parent, std::string title, std::string message) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new(GTK_WINDOW(parent), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", message.c_str()); - gtk_window_set_title(GTK_WINDOW(dialog), title.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); -} - -gpointer worker_thread_cb(gpointer data) -{ - UpdaterAppState *app_state; - CURL *curl; - CURLcode result; - FILE *package_file; - GError *error = NULL; - int fd; - - //g_return_val_if_fail (data != NULL, NULL); - app_state = (UpdaterAppState *) data; - - try { - - if(!app_state->url.empty()) - { - char* tmp_local_filename = NULL; - // create temporary file to store the package. - fd = g_file_open_tmp - ("secondlife-update-XXXXXX", &tmp_local_filename, &error); - if (error != NULL) - { - LL_ERRS() << "Unable to create temporary file: " - << error->message - << LL_ENDL; - - g_error_free(error); - throw 0; - } - - if(tmp_local_filename != NULL) - { - app_state->file = tmp_local_filename; - g_free(tmp_local_filename); - } - - package_file = fdopen(fd, "wb"); - if (package_file == NULL) - { - LL_ERRS() << "Failed to create temporary file: " - << app_state->file.c_str() - << LL_ENDL; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - - // initialize curl and start downloading the package - LL_INFOS() << "Downloading package: " << app_state->url << LL_ENDL; - - curl = curl_easy_init(); - if (curl == NULL) - { - LL_ERRS() << "Failed to initialize libcurl" << LL_ENDL; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - - curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str()); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, - &download_progress_cb); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state); - - result = curl_easy_perform(curl); - fclose(package_file); - curl_easy_cleanup(curl); - - if (result) - { - LL_ERRS() << "Failed to download update: " - << app_state->url - << LL_ENDL; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - - throw 0; - } - } - - // now pulse the progres bar back and forth while the package is - // being unpacked - gdk_threads_enter(); - std::string installing_msg = LLTrans::getString("UpdaterNowInstalling"); - gtk_progress_bar_set_text( - GTK_PROGRESS_BAR(app_state->progress_bar), - installing_msg.c_str()); - app_state->activity_mode = TRUE; - gdk_threads_leave(); - - // *TODO: if the destination is not writable, terminate this - // thread and show file chooser? - if (!install_package(app_state->file.c_str(), app_state->dest_dir)) - { - LL_WARNS() << "Failed to install package to destination: " - << app_state->dest_dir - << LL_ENDL; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailInstallTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - //"Failed to update " + app_state->app_name, - gdk_threads_leave(); - throw 0; - } - - // try to spawn the new viewer - if (!spawn_viewer(app_state)) - { - LL_WARNS() << "Viewer was not installed properly in : " - << app_state->dest_dir - << LL_ENDL; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailStartTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - } - catch (...) - { - app_state->failure = TRUE; - } - - gdk_threads_enter(); - updater_app_quit(app_state); - gdk_threads_leave(); - - return NULL; -} - - -gboolean less_anal_gspawnsync(gchar **argv, - gchar **stderr_output, - gint *child_exit_status, - GError **spawn_error) -{ - // store current SIGCHLD handler if there is one, replace with default - // handler to make glib happy - struct sigaction sigchld_backup; - struct sigaction sigchld_appease_glib; - sigchld_appease_glib.sa_handler = SIG_DFL; - sigemptyset(&sigchld_appease_glib.sa_mask); - sigchld_appease_glib.sa_flags = 0; - sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); - - gboolean rtn = g_spawn_sync(NULL, - argv, - NULL, - (GSpawnFlags) (G_SPAWN_STDOUT_TO_DEV_NULL), - NULL, - NULL, - NULL, - stderr_output, - child_exit_status, - spawn_error); - - // restore SIGCHLD handler - sigaction(SIGCHLD, &sigchld_backup, NULL); - - return rtn; -} - - -// perform a rename, or perform a (prompted) root rename if that fails -int -rename_with_sudo_fallback(const std::string& filename, const std::string& newname) -{ - int rtncode = ::rename(filename.c_str(), newname.c_str()); - LL_DEBUGS() << "rename result is: " << rtncode << " / " << errno << LL_ENDL; - if (rtncode && (EACCES == errno || EPERM == errno || EXDEV == errno)) - { - LL_INFOS() << "Permission problem in rename, or moving between different mount points. Retrying as a mv under a sudo." << LL_ENDL; - // failed due to permissions, try again as a gksudo or kdesu mv wrapper hack - char *sudo_cmd = NULL; - sudo_cmd = g_find_program_in_path("gksudo"); - if (!sudo_cmd) - { - sudo_cmd = g_find_program_in_path("kdesu"); - } - if (sudo_cmd) - { - char *mv_cmd = NULL; - mv_cmd = g_find_program_in_path("mv"); - if (mv_cmd) - { - char *src_string_copy = g_strdup(filename.c_str()); - char *dst_string_copy = g_strdup(newname.c_str()); - char* argv[] = - { - sudo_cmd, - mv_cmd, - src_string_copy, - dst_string_copy, - NULL - }; - - gchar *stderr_output = NULL; - gint child_exit_status = 0; - GError *spawn_error = NULL; - if (!less_anal_gspawnsync(argv, &stderr_output, - &child_exit_status, &spawn_error)) - { - LL_WARNS() << "Failed to spawn child process: " - << spawn_error->message - << LL_ENDL; - } - else if (child_exit_status) - { - LL_WARNS() << "mv command failed: " - << (stderr_output ? stderr_output : "(no reason given)") - << LL_ENDL; - } - else - { - // everything looks good, clear the error code - rtncode = 0; - } - - g_free(src_string_copy); - g_free(dst_string_copy); - if (spawn_error) g_error_free(spawn_error); - } - } - } - return rtncode; -} - -gboolean install_package(std::string package_file, std::string destination) -{ - char *tar_cmd = NULL; - std::ostringstream command; - - // Find the absolute path to the 'tar' command. - tar_cmd = g_find_program_in_path("tar"); - if (!tar_cmd) - { - LL_ERRS() << "`tar' was not found in $PATH" << LL_ENDL; - return FALSE; - } - LL_INFOS() << "Found tar command: " << tar_cmd << LL_ENDL; - - // Unpack the tarball in a temporary place first, then move it to - // its final destination - std::string tmp_dest_dir = gDirUtilp->getTempFilename(); - if (LLFile::mkdir(tmp_dest_dir, 0744)) - { - LL_ERRS() << "Failed to create directory: " - << destination - << LL_ENDL; - - return FALSE; - } - - char *package_file_string_copy = g_strdup(package_file.c_str()); - char *tmp_dest_dir_string_copy = g_strdup(tmp_dest_dir.c_str()); - gchar *argv[8] = { - tar_cmd, - const_cast("--strip"), const_cast("1"), - const_cast("-xjf"), - package_file_string_copy, - const_cast("-C"), tmp_dest_dir_string_copy, - NULL, - }; - - LL_INFOS() << "Untarring package: " << package_file << LL_ENDL; - - // store current SIGCHLD handler if there is one, replace with default - // handler to make glib happy - struct sigaction sigchld_backup; - struct sigaction sigchld_appease_glib; - sigchld_appease_glib.sa_handler = SIG_DFL; - sigemptyset(&sigchld_appease_glib.sa_mask); - sigchld_appease_glib.sa_flags = 0; - sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); - - gchar *stderr_output = NULL; - gint child_exit_status = 0; - GError *untar_error = NULL; - if (!less_anal_gspawnsync(argv, &stderr_output, - &child_exit_status, &untar_error)) - { - LL_WARNS() << "Failed to spawn child process: " - << untar_error->message - << LL_ENDL; - return FALSE; - } - - if (child_exit_status) - { - LL_WARNS() << "Untar command failed: " - << (stderr_output ? stderr_output : "(no reason given)") - << LL_ENDL; - return FALSE; - } - - g_free(tar_cmd); - g_free(package_file_string_copy); - g_free(tmp_dest_dir_string_copy); - g_free(stderr_output); - if (untar_error) g_error_free(untar_error); - - // move the existing package out of the way if it exists - if (gDirUtilp->fileExists(destination)) - { - std::string backup_dir = destination + ".backup"; - int oldcounter = 1; - while (gDirUtilp->fileExists(backup_dir)) - { - // find a foo.backup.N folder name that isn't taken yet - backup_dir = destination + ".backup." + llformat("%d", oldcounter); - ++oldcounter; - } - - if (rename_with_sudo_fallback(destination, backup_dir)) - { - LL_WARNS() << "Failed to move directory: '" - << destination << "' -> '" << backup_dir - << LL_ENDL; - return FALSE; - } - } - - // The package has been unpacked in a staging directory, now we just - // need to move it to its destination. - if (rename_with_sudo_fallback(tmp_dest_dir, destination)) - { - LL_WARNS() << "Failed to move installation to the destination: " - << destination - << LL_ENDL; - return FALSE; - } - - // \0/ Success! - return TRUE; -} - -gboolean progress_update_timeout(gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - - app_state = (UpdaterAppState *) data; - - gdk_threads_enter(); - if (app_state->activity_mode) - { - gtk_progress_bar_pulse - (GTK_PROGRESS_BAR(app_state->progress_bar)); - } - else - { - gtk_progress_set_value(GTK_PROGRESS(app_state->progress_bar), - app_state->progress_value); - } - gdk_threads_leave(); - - return TRUE; -} - -gboolean update_progress_text_timeout(gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - if (app_state->activity_mode == TRUE) - { - // We no longer need this timeout, it will be removed. - return FALSE; - } - - if (!app_state->progress_value) - { - return TRUE; - } - - std::string progress_text = llformat((LLTrans::getString("UpdaterProgressBarText")+" (%.0f%%)").c_str(), app_state->progress_value); - - gdk_threads_enter(); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), - progress_text.c_str()); - gdk_threads_leave(); - - return TRUE; -} - -int download_progress_cb(gpointer data, - double t, - double d, - double utotal, - double ulnow) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - if (t <= 0.0) - { - app_state->progress_value = 0; - } - else - { - app_state->progress_value = d * 100.0 / t; - } - return 0; -} - -BOOL spawn_viewer(UpdaterAppState *app_state) -{ - llassert(app_state != NULL); - - std::string cmd = app_state->dest_dir + "/secondlife"; - GError *error = NULL; - - // We want to spawn the Viewer on the same display as the updater app - gboolean success = gdk_spawn_command_line_on_screen - (gtk_widget_get_screen(app_state->window), cmd.c_str(), &error); - - if (!success) - { - LL_WARNS() << "Failed to launch viewer: " << error->message - << LL_ENDL; - } - - if (error) g_error_free(error); - - return success; -} - -void show_usage_and_exit() -{ - std::cout << "Usage: linux-updater <--url URL | --file FILE> --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE" - << "[--image-dir PATH]" - << std::endl; - exit(1); -} - -void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state) -{ - int i; - - for (i = 1; i < argc; i++) - { - if ((!strcmp(argv[i], "--url")) && (++i < argc)) - { - app_state->url = argv[i]; - } - else if ((!strcmp(argv[i], "--file")) && (++i < argc)) - { - app_state->file = argv[i]; - } - else if ((!strcmp(argv[i], "--name")) && (++i < argc)) - { - app_state->app_name = argv[i]; - } - else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc)) - { - app_state->image_dir = argv[i]; - app_state->image_dir_iter = new LLDirIterator(argv[i], "*.jpg"); - } - else if ((!strcmp(argv[i], "--dest")) && (++i < argc)) - { - app_state->dest_dir = argv[i]; - } - else if ((!strcmp(argv[i], "--stringsdir")) && (++i < argc)) - { - app_state->strings_dirs = argv[i]; - } - else if ((!strcmp(argv[i], "--stringsfile")) && (++i < argc)) - { - app_state->strings_file = argv[i]; - } - else - { - // show usage, an invalid option was given. - show_usage_and_exit(); - } - } - - if (app_state->app_name.empty() - || (app_state->url.empty() && app_state->file.empty()) - || app_state->dest_dir.empty()) - { - show_usage_and_exit(); - } - - app_state->progress_value = 0.0; - app_state->activity_mode = FALSE; - app_state->failure = FALSE; - - translate_init(app_state->strings_dirs, app_state->strings_file); -} - -int main(int argc, char **argv) -{ - UpdaterAppState* app_state = new UpdaterAppState; - - parse_args_and_init(argc, argv, app_state); - - // Initialize logger, and rename old log file - gDirUtilp->initAppDirs("SecondLife"); - LLError::initForApplication - (gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - std::string old_log_file = gDirUtilp->getExpandedFilename - (LL_PATH_LOGS, "updater.log.old"); - std::string log_file = - gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); - LLFile::rename(log_file, old_log_file); - LLError::logToFile(log_file); - - // initialize gthreads and gtk+ - if (!g_thread_supported()) - { - g_thread_init(NULL); - gdk_threads_init(); - } - - gtk_init(&argc, &argv); - - // create UI - updater_app_ui_init(app_state); - - //LL_INFOS() << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << LL_ENDL; - - // create download thread - g_thread_create(GThreadFunc(worker_thread_cb), app_state, FALSE, NULL); - - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - // Delete the file only if created from url download. - if(!app_state->url.empty() && !app_state->file.empty()) - { - if (gDirUtilp->fileExists(app_state->file)) - { - LLFile::remove(app_state->file); - } - } - - bool success = !app_state->failure; - delete app_state->image_dir_iter; - delete app_state; - return success ? 0 : 1; -} - -/***************************************************************************** -* Dummy LLTrans implementation (IQA-490) -*****************************************************************************/ -static LLTrans sStaticStrings; - -// lookup -std::string LLTrans::_getString(const std::string& key) const -{ - MessageMap::const_iterator found = mMessages.find(key); - if (found != mMessages.end()) - { - return found->second; - } - LL_WARNS("linux_updater") << "No message for key '" << key - << "' -- add to LLTrans::LLTrans() in linux_updater.cpp" - << LL_ENDL; - return key; -} - -// static lookup -std::string LLTrans::getString(const std::string& key) -{ - return sLLTransInstance._getString(key); -} - -// initialization -LLTrans::LLTrans() -{ - typedef std::pair Pair; - static const Pair data[] = - { - Pair("UpdaterFailDownloadTitle", - "Failed to download update"), - Pair("UpdaterFailInstallTitle", - "Failed to install update"), - Pair("UpdaterFailStartTitle", - "Failed to start viewer"), - Pair("UpdaterFailUpdateDescriptive", - "An error occurred while updating Second Life. " - "Please download the latest version from www.secondlife.com."), - Pair("UpdaterNowInstalling", - "Installing Second Life..."), - Pair("UpdaterNowUpdating", - "Now updating Second Life..."), - Pair("UpdaterProgressBarText", - "Downloading update"), - Pair("UpdaterProgressBarTextWithEllipses", - "Downloading update..."), - Pair("UpdaterUpdatingDescriptive", - "Your Second Life Viewer is being updated to the latest release. " - "This may take some time, so please be patient."), - Pair("UpdaterWindowTitle", - "Second Life Update") - }; - - BOOST_FOREACH(Pair pair, data) - { - mMessages[pair.first] = pair.second; - } -} -- cgit v1.2.3 From e79a88c8ccfadcd260892000d4dec2ae921b26de Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Tue, 12 Aug 2014 18:21:26 -0400 Subject: Better support for dynamic option changes in llcorehttp. Libcurl has some problems disabling pipelining on a multi handle with outstanding requests so build a more conservative system that allows requests to drain before setting curl multi options. Would rather not have this but it is significantly safer. "HttpPipelining" debug setting is now fully dynamic. Connection limits can also be made dynamic in the near future. Upped the default connection count back to 8 for now but will revisit this in the tuning phase. It might be time to combine mesh and textures into a single asset class. For normal server operations that would be a clear path, but for server under load, the current scheme may be better. Minor cleanup in logging to elminate some redundant strings. Might add some more tracing to the stall logic 'just in case'. --- indra/llcorehttp/_httplibcurl.cpp | 198 ++++++++++++++++++++++---------- indra/llcorehttp/_httplibcurl.h | 12 +- indra/llcorehttp/_httpoperation.cpp | 28 +++-- indra/llcorehttp/_httpoprequest.cpp | 46 ++++---- indra/llcorehttp/_httppolicy.cpp | 83 ++++++++----- indra/llcorehttp/_httppolicy.h | 8 ++ indra/llcorehttp/_httpservice.cpp | 30 +++-- indra/newview/app_settings/settings.xml | 4 +- indra/newview/llappcorehttp.cpp | 174 ++++++++++++++++------------ indra/newview/llappcorehttp.h | 1 + indra/newview/lltexturefetch.cpp | 55 +++++---- indra/newview/lltexturefetch.h | 10 +- 12 files changed, 421 insertions(+), 228 deletions(-) diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index fb907f6318..b46833a1f3 100755 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -40,6 +40,8 @@ namespace void check_curl_multi_code(CURLMcode code); void check_curl_multi_code(CURLMcode code, int curl_setopt_option); +static const char * const LOG_CORE("CoreHttp"); + } // end anonymous namespace @@ -51,7 +53,8 @@ HttpLibcurl::HttpLibcurl(HttpService * service) : mService(service), mPolicyCount(0), mMultiHandles(NULL), - mActiveHandles(NULL) + mActiveHandles(NULL), + mDirtyPolicy(NULL) {} @@ -90,6 +93,9 @@ void HttpLibcurl::shutdown() delete [] mActiveHandles; mActiveHandles = NULL; + + delete [] mDirtyPolicy; + mDirtyPolicy = NULL; } mPolicyCount = 0; @@ -101,44 +107,21 @@ void HttpLibcurl::start(int policy_count) llassert_always(policy_count <= HTTP_POLICY_CLASS_LIMIT); llassert_always(! mMultiHandles); // One-time call only - HttpPolicy & policy(mService->getPolicy()); mPolicyCount = policy_count; mMultiHandles = new CURLM * [mPolicyCount]; mActiveHandles = new int [mPolicyCount]; + mDirtyPolicy = new bool [mPolicyCount]; for (int policy_class(0); policy_class < mPolicyCount; ++policy_class) { - HttpPolicyClass & options(policy.getClassOptions(policy_class)); - - mActiveHandles[policy_class] = 0; if (NULL == (mMultiHandles[policy_class] = curl_multi_init())) { - LL_ERRS("CoreHttp") << "Failed to allocate multi handle in libcurl." - << LL_ENDL; - } - - if (options.mPipelining > 1) - { - CURLMcode code; - - // We'll try to do pipelining on this multihandle - code = curl_multi_setopt(mMultiHandles[policy_class], - CURLMOPT_PIPELINING, - 1L); - check_curl_multi_code(code, CURLMOPT_PIPELINING); - code = curl_multi_setopt(mMultiHandles[policy_class], - CURLMOPT_MAX_PIPELINE_LENGTH, - long(options.mPipelining)); - check_curl_multi_code(code, CURLMOPT_MAX_PIPELINE_LENGTH); - code = curl_multi_setopt(mMultiHandles[policy_class], - CURLMOPT_MAX_HOST_CONNECTIONS, - long(options.mPerHostConnectionLimit)); - check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS); - code = curl_multi_setopt(mMultiHandles[policy_class], - CURLMOPT_MAX_TOTAL_CONNECTIONS, - long(options.mConnectionLimit)); - check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS); + LL_ERRS(LOG_CORE) << "Failed to allocate multi handle in libcurl." + << LL_ENDL; } + mActiveHandles[policy_class] = 0; + mDirtyPolicy[policy_class] = false; + policyUpdated(policy_class); } } @@ -156,8 +139,19 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport() // Give libcurl some cycles to do I/O & callbacks for (int policy_class(0); policy_class < mPolicyCount; ++policy_class) { - if (! mActiveHandles[policy_class] || ! mMultiHandles[policy_class]) + if (! mMultiHandles[policy_class]) { + // No handle, nothing to do. + continue; + } + if (! mActiveHandles[policy_class]) + { + // If we've gone quiet and there's a dirty update, apply it, + // otherwise we're done. + if (mDirtyPolicy[policy_class]) + { + policyUpdated(policy_class); + } continue; } @@ -192,9 +186,9 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport() } else { - LL_WARNS_ONCE("CoreHttp") << "Unexpected message from libcurl. Msg code: " - << msg->msg - << LL_ENDL; + LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl. Msg code: " + << msg->msg + << LL_ENDL; } msgs_in_queue = 0; } @@ -230,11 +224,11 @@ void HttpLibcurl::addOp(HttpOpRequest * op) { HttpPolicy & policy(mService->getPolicy()); - LL_INFOS("CoreHttp") << "TRACE, ToActiveQueue, Handle: " - << static_cast(op) - << ", Actives: " << mActiveOps.size() - << ", Readies: " << policy.getReadyCount(op->mReqPolicy) - << LL_ENDL; + LL_INFOS(LOG_CORE) << "TRACE, ToActiveQueue, Handle: " + << static_cast(op) + << ", Actives: " << mActiveOps.size() + << ", Readies: " << policy.getReadyCount(op->mReqPolicy) + << LL_ENDL; } // On success, make operation active @@ -286,10 +280,10 @@ void HttpLibcurl::cancelRequest(HttpOpRequest * op) // Tracing if (op->mTracing > HTTP_TRACE_OFF) { - LL_INFOS("CoreHttp") << "TRACE, RequestCanceled, Handle: " - << static_cast(op) - << ", Status: " << op->mStatus.toTerseString() - << LL_ENDL; + LL_INFOS(LOG_CORE) << "TRACE, RequestCanceled, Handle: " + << static_cast(op) + << ", Status: " << op->mStatus.toTerseString() + << LL_ENDL; } // Cancel op and deliver for notification @@ -306,18 +300,18 @@ bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode if (handle != op->mCurlHandle || ! op->mCurlActive) { - LL_WARNS("CoreHttp") << "libcurl handle and HttpOpRequest handle in disagreement or inactive request." - << " Handle: " << static_cast(handle) - << LL_ENDL; + LL_WARNS(LOG_CORE) << "libcurl handle and HttpOpRequest handle in disagreement or inactive request." + << " Handle: " << static_cast(handle) + << LL_ENDL; return false; } active_set_t::iterator it(mActiveOps.find(op)); if (mActiveOps.end() == it) { - LL_WARNS("CoreHttp") << "libcurl completion for request not on active list. Continuing." - << " Handle: " << static_cast(handle) - << LL_ENDL; + LL_WARNS(LOG_CORE) << "libcurl completion for request not on active list. Continuing." + << " Handle: " << static_cast(handle) + << LL_ENDL; return false; } @@ -348,9 +342,9 @@ bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode } else { - LL_WARNS("CoreHttp") << "Invalid HTTP response code (" - << http_status << ") received from server." - << LL_ENDL; + LL_WARNS(LOG_CORE) << "Invalid HTTP response code (" + << http_status << ") received from server." + << LL_ENDL; op->mStatus = HttpStatus(HttpStatus::LLCORE, HE_INVALID_HTTP_STATUS); } } @@ -363,10 +357,10 @@ bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode // Tracing if (op->mTracing > HTTP_TRACE_OFF) { - LL_INFOS("CoreHttp") << "TRACE, RequestComplete, Handle: " - << static_cast(op) - << ", Status: " << op->mStatus.toTerseString() - << LL_ENDL; + LL_INFOS(LOG_CORE) << "TRACE, RequestComplete, Handle: " + << static_cast(op) + << ", Status: " << op->mStatus.toTerseString() + << LL_ENDL; } // Dispatch to next stage @@ -390,6 +384,88 @@ int HttpLibcurl::getActiveCountInClass(int policy_class) const return mActiveHandles ? mActiveHandles[policy_class] : 0; } +void HttpLibcurl::policyUpdated(int policy_class) +{ + if (policy_class < 0 || policy_class >= mPolicyCount || ! mMultiHandles) + { + return; + } + + HttpPolicy & policy(mService->getPolicy()); + + if (! mActiveHandles[policy_class]) + { + // Clear to set options. As of libcurl 7.37.0, if a pipelining + // multi handle has active requests and you try to set the + // multi handle to non-pipelining, the library gets very angry + // and goes off the rails corrupting memory. A clue that you're + // about to crash is that you'll get a missing server response + // error (curl code 9). So, if options are to be set, we let + // the multi handle run out of requests, then set options, and + // re-enable request processing. + // + // All of this stall mechanism exists for this reason. If + // libcurl becomes more resilient later, it should be possible + // to remove all of this. The connection limit settings are fine, + // it's just that pipelined-to-non-pipelined transition that + // is fatal at the moment. + + HttpPolicyClass & options(policy.getClassOptions(policy_class)); + CURLM * multi_handle(mMultiHandles[policy_class]); + CURLMcode code; + + // Enable policy if stalled + policy.stallPolicy(policy_class, false); + mDirtyPolicy[policy_class] = false; + + if (options.mPipelining > 1) + { + // We'll try to do pipelining on this multihandle + code = curl_multi_setopt(multi_handle, + CURLMOPT_PIPELINING, + 1L); + check_curl_multi_code(code, CURLMOPT_PIPELINING); + code = curl_multi_setopt(multi_handle, + CURLMOPT_MAX_PIPELINE_LENGTH, + long(options.mPipelining)); + check_curl_multi_code(code, CURLMOPT_MAX_PIPELINE_LENGTH); + code = curl_multi_setopt(multi_handle, + CURLMOPT_MAX_HOST_CONNECTIONS, + long(options.mPerHostConnectionLimit)); + check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS); + code = curl_multi_setopt(multi_handle, + CURLMOPT_MAX_TOTAL_CONNECTIONS, + long(options.mConnectionLimit)); + check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS); + } + else + { + code = curl_multi_setopt(multi_handle, + CURLMOPT_PIPELINING, + 0L); + check_curl_multi_code(code, CURLMOPT_PIPELINING); + code = curl_multi_setopt(multi_handle, + CURLMOPT_MAX_HOST_CONNECTIONS, + 0L); + check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS); + code = curl_multi_setopt(multi_handle, + CURLMOPT_MAX_TOTAL_CONNECTIONS, + long(options.mConnectionLimit)); + check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS); + } + } + else if (! mDirtyPolicy[policy_class]) + { + // Mark policy dirty and request a stall in the policy. + // When policy goes idle, we'll re-invoke this method + // and perform the change. Don't allow this thread to + // sleep while we're waiting for quiescence, we'll just + // stop processing. + mDirtyPolicy[policy_class] = true; + policy.stallPolicy(policy_class, true); + } +} + // --------------------------------------- // Free functions @@ -424,9 +500,9 @@ void check_curl_multi_code(CURLMcode code, int curl_setopt_option) { if (CURLM_OK != code) { - LL_WARNS("CoreHttp") << "libcurl multi error detected: " << curl_multi_strerror(code) - << ", curl_multi_setopt option: " << curl_setopt_option - << LL_ENDL; + LL_WARNS(LOG_CORE) << "libcurl multi error detected: " << curl_multi_strerror(code) + << ", curl_multi_setopt option: " << curl_setopt_option + << LL_ENDL; } } @@ -435,8 +511,8 @@ void check_curl_multi_code(CURLMcode code) { if (CURLM_OK != code) { - LL_WARNS("CoreHttp") << "libcurl multi error detected: " << curl_multi_strerror(code) - << LL_ENDL; + LL_WARNS(LOG_CORE) << "libcurl multi error detected: " << curl_multi_strerror(code) + << LL_ENDL; } } diff --git a/indra/llcorehttp/_httplibcurl.h b/indra/llcorehttp/_httplibcurl.h index 67f98dd4f0..2c7ad1fa8e 100755 --- a/indra/llcorehttp/_httplibcurl.h +++ b/indra/llcorehttp/_httplibcurl.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012-2013, Linden Research, Inc. + * Copyright (C) 2012-2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -116,6 +116,14 @@ public: /// Threading: called by worker thread. bool cancel(HttpHandle handle); + /// Informs transport that a particular policy class has had + /// options changed and so should effect any transport state + /// change necessary to effect those changes. Used mainly for + /// initialization and dynamic option setting. + /// + /// Threading: called by worker thread. + void policyUpdated(int policy_class); + protected: /// Invoked when libcurl has indicated a request has been processed /// to completion and we need to move the request to a new state. @@ -134,6 +142,8 @@ protected: int mPolicyCount; CURLM ** mMultiHandles; // One handle per policy class int * mActiveHandles; // Active count per policy class + bool * mDirtyPolicy; // Dirty policy update waiting for stall (per pc) + }; // end class HttpLibcurl } // end namespace LLCore diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp index 5bb0654652..fefe561f80 100755 --- a/indra/llcorehttp/_httpoperation.cpp +++ b/indra/llcorehttp/_httpoperation.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012-2013, Linden Research, Inc. + * Copyright (C) 2012-2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,6 +38,14 @@ #include "lltimer.h" +namespace +{ + +static const char * const LOG_CORE("CoreHttp"); + +} // end anonymous namespace + + namespace LLCore { @@ -94,8 +102,8 @@ void HttpOperation::stageFromRequest(HttpService *) // Default implementation should never be called. This // indicates an operation making a transition that isn't // defined. - LL_ERRS("CoreHttp") << "Default stageFromRequest method may not be called." - << LL_ENDL; + LL_ERRS(LOG_CORE) << "Default stageFromRequest method may not be called." + << LL_ENDL; } @@ -104,8 +112,8 @@ void HttpOperation::stageFromReady(HttpService *) // Default implementation should never be called. This // indicates an operation making a transition that isn't // defined. - LL_ERRS("CoreHttp") << "Default stageFromReady method may not be called." - << LL_ENDL; + LL_ERRS(LOG_CORE) << "Default stageFromReady method may not be called." + << LL_ENDL; } @@ -114,8 +122,8 @@ void HttpOperation::stageFromActive(HttpService *) // Default implementation should never be called. This // indicates an operation making a transition that isn't // defined. - LL_ERRS("CoreHttp") << "Default stageFromActive method may not be called." - << LL_ENDL; + LL_ERRS(LOG_CORE) << "Default stageFromActive method may not be called." + << LL_ENDL; } @@ -145,9 +153,9 @@ void HttpOperation::addAsReply() { if (mTracing > HTTP_TRACE_OFF) { - LL_INFOS("CoreHttp") << "TRACE, ToReplyQueue, Handle: " - << static_cast(this) - << LL_ENDL; + LL_INFOS(LOG_CORE) << "TRACE, ToReplyQueue, Handle: " + << static_cast(this) + << LL_ENDL; } if (mReplyQueue) diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 43dd069bc6..eb664fdced 100755 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012-2013, Linden Research, Inc. + * Copyright (C) 2012-2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -94,6 +94,8 @@ void os_strlower(char * str); void check_curl_easy_code(CURLcode code); void check_curl_easy_code(CURLcode code, int curl_setopt_option); +static const char * const LOG_CORE("CoreHttp"); + } // end anonymous namespace @@ -416,8 +418,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) if (! mCurlHandle) { // We're in trouble. We'll continue but it won't go well. - LL_WARNS("CoreHttp") << "Failed to allocate libcurl easy handle. Continuing." - << LL_ENDL; + LL_WARNS(LOG_CORE) << "Failed to allocate libcurl easy handle. Continuing." + << LL_ENDL; return HttpStatus(HttpStatus::LLCORE, HE_BAD_ALLOC); } code = curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); @@ -538,9 +540,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) break; default: - LL_ERRS("CoreHttp") << "Invalid HTTP method in request: " - << int(mReqMethod) << ". Can't recover." - << LL_ENDL; + LL_ERRS(LOG_CORE) << "Invalid HTTP method in request: " + << int(mReqMethod) << ". Can't recover." + << LL_ENDL; break; } @@ -652,8 +654,8 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void { // Warn but continue if the read position moves beyond end-of-body // for some reason. - LL_WARNS("CoreHttp") << "Request body position beyond body size. Truncating request body." - << LL_ENDL; + LL_WARNS(LOG_CORE) << "Request body position beyond body size. Truncating request body." + << LL_ENDL; } return 0; } @@ -790,10 +792,10 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi else { // Ignore the unparsable. - LL_INFOS_ONCE("CoreHttp") << "Problem parsing odd Content-Range header: '" - << std::string(hdr_data, wanted_hdr_size) - << "'. Ignoring." - << LL_ENDL; + LL_INFOS_ONCE(LOG_CORE) << "Problem parsing odd Content-Range header: '" + << std::string(hdr_data, wanted_hdr_size) + << "'. Ignoring." + << LL_ENDL; } } @@ -895,11 +897,11 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe if (logit) { - LL_INFOS("CoreHttp") << "TRACE, LibcurlDebug, Handle: " - << static_cast(op) - << ", Type: " << tag - << ", Data: " << safe_line - << LL_ENDL; + LL_INFOS(LOG_CORE) << "TRACE, LibcurlDebug, Handle: " + << static_cast(op) + << ", Type: " << tag + << ", Data: " << safe_line + << LL_ENDL; } return 0; @@ -1094,9 +1096,9 @@ void check_curl_easy_code(CURLcode code, int curl_setopt_option) // // linux appears to throw a curl error once per session for a bad initialization // at a pretty random time (when enabling cookies). - LL_WARNS("CoreHttp") << "libcurl error detected: " << curl_easy_strerror(code) - << ", curl_easy_setopt option: " << curl_setopt_option - << LL_ENDL; + LL_WARNS(LOG_CORE) << "libcurl error detected: " << curl_easy_strerror(code) + << ", curl_easy_setopt option: " << curl_setopt_option + << LL_ENDL; } } @@ -1109,8 +1111,8 @@ void check_curl_easy_code(CURLcode code) // // linux appears to throw a curl error once per session for a bad initialization // at a pretty random time (when enabling cookies). - LL_WARNS("CoreHttp") << "libcurl error detected: " << curl_easy_strerror(code) - << LL_ENDL; + LL_WARNS(LOG_CORE) << "libcurl error detected: " << curl_easy_strerror(code) + << LL_ENDL; } } diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index bb7959b578..09b9206f63 100755 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -35,6 +35,13 @@ #include "lltimer.h" +namespace +{ + +static const char * const LOG_CORE("CoreHttp"); + +} // end anonymous namespace + namespace LLCore { @@ -51,7 +58,8 @@ public: ClassState() : mThrottleEnd(0), mThrottleLeft(0L), - mRequestCount(0L) + mRequestCount(0L), + mStallStaging(false) {} HttpReadyQueue mReadyQueue; @@ -61,6 +69,7 @@ public: HttpTime mThrottleEnd; long mThrottleLeft; long mRequestCount; + bool mStallStaging; }; @@ -171,19 +180,19 @@ void HttpPolicy::retryOp(HttpOpRequest * op) { ++op->mPolicy503Retries; } - LL_DEBUGS("CoreHttp") << "HTTP request " << static_cast(op) - << " retry " << op->mPolicyRetries - << " scheduled in " << (delta / HttpTime(1000)) - << " mS (" << (external_delta ? "external" : "internal") - << "). Status: " << op->mStatus.toTerseString() - << LL_ENDL; + LL_DEBUGS(LOG_CORE) << "HTTP request " << static_cast(op) + << " retry " << op->mPolicyRetries + << " scheduled in " << (delta / HttpTime(1000)) + << " mS (" << (external_delta ? "external" : "internal") + << "). Status: " << op->mStatus.toTerseString() + << LL_ENDL; if (op->mTracing > HTTP_TRACE_OFF) { - LL_INFOS("CoreHttp") << "TRACE, ToRetryQueue, Handle: " - << static_cast(op) - << ", Delta: " << (delta / HttpTime(1000)) - << ", Retries: " << op->mPolicyRetries - << LL_ENDL; + LL_INFOS(LOG_CORE) << "TRACE, ToRetryQueue, Handle: " + << static_cast(op) + << ", Delta: " << (delta / HttpTime(1000)) + << ", Retries: " << op->mPolicyRetries + << LL_ENDL; } mClasses[policy_class]->mRetryQueue.push(op); } @@ -219,6 +228,15 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue() HttpRetryQueue & retryq(state.mRetryQueue); HttpReadyQueue & readyq(state.mReadyQueue); + if (state.mStallStaging) + { + // Stalling but don't sleep. Need to complete operations + // and get back to servicing queues. Do this test before + // the retryq/readyq test or you'll get stalls until you + // click a setting or an asset request comes in. + result = HttpService::NORMAL; + continue; + } if (retryq.empty() && readyq.empty()) { continue; @@ -262,9 +280,9 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue() if (now >= state.mThrottleEnd) { // Throttle expired, move to next window - LL_DEBUGS("CoreHttp") << "Throttle expired with " << state.mThrottleLeft - << " requests to go and " << state.mRequestCount - << " requests issued." << LL_ENDL; + LL_DEBUGS(LOG_CORE) << "Throttle expired with " << state.mThrottleLeft + << " requests to go and " << state.mRequestCount + << " requests issued." << LL_ENDL; state.mThrottleLeft = state.mOptions.mThrottleRate; state.mThrottleEnd = now + HttpTime(1000000); } @@ -291,9 +309,9 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue() if (now >= state.mThrottleEnd) { // Throttle expired, move to next window - LL_DEBUGS("CoreHttp") << "Throttle expired with " << state.mThrottleLeft - << " requests to go and " << state.mRequestCount - << " requests issued." << LL_ENDL; + LL_DEBUGS(LOG_CORE) << "Throttle expired with " << state.mThrottleLeft + << " requests to go and " << state.mRequestCount + << " requests issued." << LL_ENDL; state.mThrottleLeft = state.mOptions.mThrottleRate; state.mThrottleEnd = now + HttpTime(1000000); } @@ -408,17 +426,17 @@ bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op) // This op is done, finalize it delivering it to the reply queue... if (! op->mStatus) { - LL_WARNS("CoreHttp") << "HTTP request " << static_cast(op) - << " failed after " << op->mPolicyRetries - << " retries. Reason: " << op->mStatus.toString() - << " (" << op->mStatus.toTerseString() << ")" - << LL_ENDL; + LL_WARNS(LOG_CORE) << "HTTP request " << static_cast(op) + << " failed after " << op->mPolicyRetries + << " retries. Reason: " << op->mStatus.toString() + << " (" << op->mStatus.toTerseString() << ")" + << LL_ENDL; } else if (op->mPolicyRetries) { - LL_DEBUGS("CoreHttp") << "HTTP request " << static_cast(op) - << " succeeded on retry " << op->mPolicyRetries << "." - << LL_ENDL; + LL_DEBUGS(LOG_CORE) << "HTTP request " << static_cast(op) + << " succeeded on retry " << op->mPolicyRetries << "." + << LL_ENDL; } op->stageFromActive(mService); @@ -446,4 +464,17 @@ int HttpPolicy::getReadyCount(HttpRequest::policy_t policy_class) const } +bool HttpPolicy::stallPolicy(HttpRequest::policy_t policy_class, bool stall) +{ + bool ret(false); + + if (policy_class < mClasses.size()) + { + ret = mClasses[policy_class]->mStallStaging; + mClasses[policy_class]->mStallStaging = stall; + } + return ret; +} + + } // end namespace LLCore diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h index bf1aa74267..11cd89bbd1 100755 --- a/indra/llcorehttp/_httppolicy.h +++ b/indra/llcorehttp/_httppolicy.h @@ -158,6 +158,14 @@ public: /// Threading: called by worker thread int getReadyCount(HttpRequest::policy_t policy_class) const; + /// Stall (or unstall) a policy class preventing requests from + /// transitioning to an active state. Used to allow an HTTP + /// request policy to empty prior to changing settings or state + /// that isn't tolerant of changes when work is outstanding. + /// + /// Threading: called by worker thread + bool stallPolicy(HttpRequest::policy_t policy_class, bool stall); + protected: struct ClassState; typedef std::vector class_list_t; diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index c94249dc2d..c673e1be1d 100755 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012-2013, Linden Research, Inc. + * Copyright (C) 2012-2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,6 +40,14 @@ #include "llthread.h" +namespace +{ + +static const char * const LOG_CORE("CoreHttp"); + +} // end anonymous namespace + + namespace LLCore { @@ -87,8 +95,8 @@ HttpService::~HttpService() // Failed to join, expect problems ahead so do a hard termination. mThread->cancel(); - LL_WARNS("CoreHttp") << "Destroying HttpService with running thread. Expect problems." - << LL_ENDL; + LL_WARNS(LOG_CORE) << "Destroying HttpService with running thread. Expect problems." + << LL_ENDL; } } } @@ -328,9 +336,9 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop) if (op->mTracing > HTTP_TRACE_OFF) { - LL_INFOS("CoreHttp") << "TRACE, FromRequestQueue, Handle: " - << static_cast(op) - << LL_ENDL; + LL_INFOS(LOG_CORE) << "TRACE, FromRequestQueue, Handle: " + << static_cast(op) + << LL_ENDL; } // Stage @@ -437,9 +445,13 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ HttpPolicyClass & opts(mPolicy->getClassOptions(pclass)); status = opts.set(opt, value); - if (status && ret_value) + if (status) { - status = opts.get(opt, ret_value); + mTransport->policyUpdated(pclass); + if (ret_value) + { + status = opts.get(opt, ret_value); + } } } @@ -463,7 +475,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ return status; } - // Only string values are global at this time + // String values are always global (at this time). if (pclass == HttpRequest::GLOBAL_POLICY_ID) { HttpPolicyGlobal & opts(mPolicy->getGlobalOptions()); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 50f56cf6ff..0607579a08 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4459,7 +4459,7 @@ HttpPipelining Comment - If true, viewer will pipeline HTTP requests to servers. Static. + If true, viewer will pipeline HTTP requests to servers. Persist 1 Type @@ -4470,7 +4470,7 @@ HttpRangeRequestsDisable Comment - If true, viewer will not issued range GET requests for meshes and textures. + If true, viewer will not issued range GET requests for meshes and textures. May resolve problems with certain ISPs and networking gear. Persist 1 Type diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index d097f18d61..464e60948a 100755 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -60,7 +60,7 @@ static const struct "other" }, { // AP_TEXTURE - 4, 1, 12, 0, true, + 8, 1, 12, 0, true, "TextureFetchConcurrency", "texture fetch" }, @@ -70,7 +70,7 @@ static const struct "mesh fetch" }, { // AP_MESH2 - 4, 1, 32, 100, true, + 8, 1, 32, 100, true, "Mesh2MaxConcurrentRequests", "mesh2 fetch" }, @@ -126,14 +126,6 @@ void LLAppCoreHttp::init() << LL_ENDL; } - // Global pipelining preference from settings - static const std::string http_pipelining("HttpPipelining"); - if (gSavedSettings.controlExists(http_pipelining)) - { - // Default to true if absent. - mPipelined = gSavedSettings.getBOOL(http_pipelining); - } - // Point to our certs or SSH/https: will fail on connect status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE, LLCore::HttpRequest::GLOBAL_POLICY_ID, @@ -210,12 +202,27 @@ void LLAppCoreHttp::init() << LL_ENDL; } - // *NOTE: Pipelining isn't dynamic yet. When it is, add a global - // signal for the setting here. - + // Signal for global pipelining preference from settings + static const std::string http_pipelining("HttpPipelining"); + if (gSavedSettings.controlExists(http_pipelining)) + { + LLPointer cntrl_ptr = gSavedSettings.getControl(http_pipelining); + if (cntrl_ptr.isNull()) + { + LL_WARNS("Init") << "Unable to set signal on global setting '" << http_pipelining + << "'" << LL_ENDL; + } + else + { + mPipelinedSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&setting_changed)); + } + } + // Register signals for settings and state changes for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i) { + const EAppPolicy app_policy(static_cast(i)); + if (! init_data[i].mKey.empty() && gSavedSettings.controlExists(init_data[i].mKey)) { LLPointer cntrl_ptr = gSavedSettings.getControl(init_data[i].mKey); @@ -226,7 +233,7 @@ void LLAppCoreHttp::init() } else { - mHttpClasses[i].mSettingsSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&setting_changed)); + mHttpClasses[app_policy].mSettingsSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&setting_changed)); } } } @@ -282,6 +289,7 @@ void LLAppCoreHttp::cleanup() { mHttpClasses[i].mSettingsSignal.disconnect(); } + mPipelinedSignal.disconnect(); delete mRequest; mRequest = NULL; @@ -299,6 +307,20 @@ void LLAppCoreHttp::cleanup() void LLAppCoreHttp::refreshSettings(bool initial) { LLCore::HttpStatus status; + + // Global pipelining setting + bool pipeline_changed(false); + static const std::string http_pipelining("HttpPipelining"); + if (gSavedSettings.controlExists(http_pipelining)) + { + // Default to true (in ctor) if absent. + bool pipelined(gSavedSettings.getBOOL(http_pipelining)); + if (pipelined != mPipelined) + { + mPipelined = pipelined; + pipeline_changed = true; + } + } for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i) { @@ -323,33 +345,42 @@ void LLAppCoreHttp::refreshSettings(bool initial) } } - mHttpClasses[app_policy].mPipelined = false; - if (mPipelined && init_data[i].mPipelined) + } + + // Init- or run-time settings. Must use the queued request API. + + // Pipelining changes + if (initial || pipeline_changed) + { + const bool to_pipeline(mPipelined && init_data[i].mPipelined); + if (to_pipeline != mHttpClasses[app_policy].mPipelined) { - // Pipelining election is currently static (init-time). - // Making it dynamic isn't too hard in the SL code but verifying - // that libcurl handles the on-to-off transition while holding - // outstanding requests is something that should be tested. + // Pipeline election changing, set dynamic option via request + + LLCore::HttpHandle handle; + const long new_depth(to_pipeline ? PIPELINING_DEPTH : 0); - status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_PIPELINING_DEPTH, - mHttpClasses[app_policy].mPolicy, - PIPELINING_DEPTH, - NULL); - if (! status) + handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_PIPELINING_DEPTH, + mHttpClasses[app_policy].mPolicy, + new_depth, + NULL); + if (LLCORE_HTTP_HANDLE_INVALID == handle) { + status = mRequest->getStatus(); LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage - << " to pipelined mode. Reason: " << status.toString() + << " pipelining. Reason: " << status.toString() << LL_ENDL; } else { - mHttpClasses[app_policy].mPipelined = true; + LL_DEBUGS("Init") << "Changed " << init_data[i].mUsage + << " pipelining. New value: " << new_depth + << LL_ENDL; + mHttpClasses[app_policy].mPipelined = to_pipeline; } } } - - // Init- or run-time settings - + // Get target connection concurrency value U32 setting(init_data[i].mDefault); if (! init_data[i].mKey.empty() && gSavedSettings.controlExists(init_data[i].mKey)) @@ -362,63 +393,60 @@ void LLAppCoreHttp::refreshSettings(bool initial) } } - if (! initial && setting == mHttpClasses[app_policy].mConnLimit) + if (initial || setting != mHttpClasses[app_policy].mConnLimit || pipeline_changed) { - // Unchanged, try next setting - continue; - } - - // Set it and report. Strategies depend on pipelining: - // - // No Pipelining. Llcorehttp manages connections itself based - // on the PO_CONNECTION_LIMIT setting. Set both limits to the - // same value for logical consistency. In the future, may - // hand over connection management to libcurl after the - // connection cache has been better vetted. - // - // Pipelining. Libcurl is allowed to manage connections to a - // great degree. Steady state will connection limit based on - // the per-host setting. Transitions (region crossings, new - // avatars, etc.) can request additional outbound connections - // to other servers via 2X total connection limit. - // - LLCore::HttpHandle handle; - handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_CONNECTION_LIMIT, - mHttpClasses[app_policy].mPolicy, - (mHttpClasses[app_policy].mPipelined ? 2 * setting : setting), - NULL); - if (LLCORE_HTTP_HANDLE_INVALID == handle) - { - status = mRequest->getStatus(); - LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage - << " concurrency. Reason: " << status.toString() - << LL_ENDL; - } - else - { - handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_PER_HOST_CONNECTION_LIMIT, + // Set it and report. Strategies depend on pipelining: + // + // No Pipelining. Llcorehttp manages connections itself based + // on the PO_CONNECTION_LIMIT setting. Set both limits to the + // same value for logical consistency. In the future, may + // hand over connection management to libcurl after the + // connection cache has been better vetted. + // + // Pipelining. Libcurl is allowed to manage connections to a + // great degree. Steady state will connection limit based on + // the per-host setting. Transitions (region crossings, new + // avatars, etc.) can request additional outbound connections + // to other servers via 2X total connection limit. + // + LLCore::HttpHandle handle; + handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_CONNECTION_LIMIT, mHttpClasses[app_policy].mPolicy, - setting, + (mHttpClasses[app_policy].mPipelined ? 2 * setting : setting), NULL); if (LLCORE_HTTP_HANDLE_INVALID == handle) { status = mRequest->getStatus(); LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage - << " per-host concurrency. Reason: " << status.toString() + << " concurrency. Reason: " << status.toString() << LL_ENDL; } else { - LL_DEBUGS("Init") << "Changed " << init_data[i].mUsage - << " concurrency. New value: " << setting - << LL_ENDL; - mHttpClasses[app_policy].mConnLimit = setting; - if (initial && setting != init_data[i].mDefault) + handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_PER_HOST_CONNECTION_LIMIT, + mHttpClasses[app_policy].mPolicy, + setting, + NULL); + if (LLCORE_HTTP_HANDLE_INVALID == handle) { - LL_INFOS("Init") << "Application settings overriding default " << init_data[i].mUsage - << " concurrency. New value: " << setting + status = mRequest->getStatus(); + LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage + << " per-host concurrency. Reason: " << status.toString() << LL_ENDL; } + else + { + LL_DEBUGS("Init") << "Changed " << init_data[i].mUsage + << " concurrency. New value: " << setting + << LL_ENDL; + mHttpClasses[app_policy].mConnLimit = setting; + if (initial && setting != init_data[i].mDefault) + { + LL_INFOS("Init") << "Application settings overriding default " << init_data[i].mUsage + << " concurrency. New value: " << setting + << LL_ENDL; + } + } } } } diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h index 63c8a11180..9ad4eb4b30 100755 --- a/indra/newview/llappcorehttp.h +++ b/indra/newview/llappcorehttp.h @@ -218,6 +218,7 @@ private: bool mStopped; HttpClass mHttpClasses[AP_COUNT]; bool mPipelined; // Global setting + boost::signals2::connection mPipelinedSignal; // Signal for 'HttpPipelining' setting }; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 4008a6948d..097a7b374f 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -483,12 +483,12 @@ private: bool acquireHttpSemaphore() { llassert(! mHttpHasResource); - if (mFetcher->mHttpSemaphore <= 0) + if (mFetcher->mHttpSemaphore >= mFetcher->mHttpHighWater) { return false; } mHttpHasResource = true; - mFetcher->mHttpSemaphore--; + mFetcher->mHttpSemaphore++; return true; } @@ -498,7 +498,8 @@ private: { llassert(mHttpHasResource); mHttpHasResource = false; - mFetcher->mHttpSemaphore++; + mFetcher->mHttpSemaphore--; + llassert_always(mFetcher->mHttpSemaphore >= 0); } private: @@ -2523,6 +2524,8 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), U32Bytes(gSavedSettings.getU32("TextureLoggingThreshold"))); + LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); + mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_TEXTURE); mHttpRequest = new LLCore::HttpRequest; mHttpOptions = new LLCore::HttpOptions; mHttpOptionsWithHeaders = new LLCore::HttpOptions; @@ -2531,21 +2534,9 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpHeaders->append("Accept", "image/x-j2c"); mHttpMetricsHeaders = new LLCore::HttpHeaders; mHttpMetricsHeaders->append("Content-Type", "application/llsd+xml"); - LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); - mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_TEXTURE); - if (app_core_http.isPipelined(LLAppCoreHttp::AP_TEXTURE)) - { - // Init-time election that will have to change for - // support of dynamic changes to the pipelining enable flag. - mHttpHighWater = HTTP_PIPE_REQUESTS_HIGH_WATER; - mHttpLowWater = HTTP_PIPE_REQUESTS_LOW_WATER; - } - else - { - mHttpHighWater = HTTP_NONPIPE_REQUESTS_HIGH_WATER; - mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER; - } - mHttpSemaphore = mHttpHighWater; + mHttpHighWater = HTTP_NONPIPE_REQUESTS_HIGH_WATER; + mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER; + mHttpSemaphore = 0; // Conditionally construct debugger object after 'this' is // fully initialized. @@ -3032,6 +3023,20 @@ bool LLTextureFetch::runCondition() // Threads: Ttf void LLTextureFetch::commonUpdate() { + // Update low/high water levels based on pipelining. We pick + // up setting eventually, so the semaphore/request level can + // fall outside the [0..HIGH_WATER] range. Expect that. + if (LLAppViewer::instance()->getAppCoreHttp().isPipelined(LLAppCoreHttp::AP_TEXTURE)) + { + mHttpHighWater = HTTP_PIPE_REQUESTS_HIGH_WATER; + mHttpLowWater = HTTP_PIPE_REQUESTS_LOW_WATER; + } + else + { + mHttpHighWater = HTTP_NONPIPE_REQUESTS_HIGH_WATER; + mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER; + } + // Release waiters releaseHttpWaiters(); @@ -3693,8 +3698,16 @@ void LLTextureFetch::releaseHttpWaiters() { // Use mHttpSemaphore rather than mHTTPTextureQueue.size() // to avoid a lock. - if (mHttpSemaphore < (mHttpHighWater - mHttpLowWater)) + if (mHttpSemaphore >= mHttpLowWater) return; + S32 needed(mHttpHighWater - mHttpSemaphore); + if (needed <= 0) + { + // Would only happen if High/LowWater were changed behind + // our back. In that case, defer fill until usage falls within + // limits. + return; + } // Quickly make a copy of all the LLUIDs. Get off the // mutex as early as possible. @@ -3743,10 +3756,10 @@ void LLTextureFetch::releaseHttpWaiters() tids.clear(); // Sort into priority order, if necessary and only as much as needed - if (tids2.size() > mHttpSemaphore) + if (tids2.size() > needed) { LLTextureFetchWorker::Compare compare; - std::partial_sort(tids2.begin(), tids2.begin() + mHttpSemaphore, tids2.end(), compare); + std::partial_sort(tids2.begin(), tids2.begin() + needed, tids2.end(), compare); } // Release workers up to the high water mark. Since we aren't diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index d13736997f..89d18e2c67 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -356,8 +356,8 @@ private: LLCore::HttpHeaders * mHttpHeaders; // Ttf LLCore::HttpHeaders * mHttpMetricsHeaders; // Ttf LLCore::HttpRequest::policy_t mHttpPolicyClass; // T* - S32 mHttpHighWater; // T* (ro) - S32 mHttpLowWater; // T* (ro) + S32 mHttpHighWater; // Ttf + S32 mHttpLowWater; // Ttf // We use a resource semaphore to keep HTTP requests in // WAIT_HTTP_RESOURCE2 if there aren't sufficient slots in the @@ -366,7 +366,11 @@ private: // where it's more expensive to get at them. Requests in either // SEND_HTTP_REQ or WAIT_HTTP_REQ charge against the semaphore // and tracking state transitions is critical to liveness. - LLAtomicS32 mHttpSemaphore; // Ttf + Tmain + // + // Originally implemented as a traditional semaphore (heading towards + // zero), it now is an outstanding request count that is allowed to + // exceed the high water level (but not go below zero). + LLAtomicS32 mHttpSemaphore; // Ttf typedef std::set wait_http_res_queue_t; wait_http_res_queue_t mHttpWaitResource; // Mfnq -- cgit v1.2.3 From d56958e68934e673195ec2966e0a3c20dac7fb41 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 13 Aug 2014 17:57:09 -0400 Subject: MAINT-4356 adjust abuse report category label for gaming --- indra/newview/skins/default/xui/en/floater_report_abuse.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index c50c8c02fe..af62c7a9bc 100755 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -253,7 +253,7 @@ name="Land__Encroachment__Objects_textures" value="63" /> -- cgit v1.2.3 From c8e90833207674515a545a4cf539bc9d78236ad2 Mon Sep 17 00:00:00 2001 From: NiranV Date: Thu, 14 Aug 2014 03:21:58 +0200 Subject: BUG-6958: Fixed: Snapshot position is always <0,0,0>. onIdle isn't called as much as they thought it is, it's only called when "Auto refresh" is on but not on normal manual snapshot refreshes. --- indra/newview/llsnapshotlivepreview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 8ad9ca000c..1aa7041175 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -195,6 +195,8 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail mSnapshotDelayTimer.start(); mSnapshotDelayTimer.setTimerExpirySec(delay); + mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); + // Tell the floater container that the snapshot is in the process of updating itself if (mViewContainer) { @@ -760,7 +762,6 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame } } -- cgit v1.2.3 From 9d406f69cc648e70fba0d9cdd3de3baf348fdbdd Mon Sep 17 00:00:00 2001 From: NiranV Date: Thu, 14 Aug 2014 03:27:13 +0200 Subject: Changed: Updated contributions file. --- doc/contributions.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/contributions.txt b/doc/contributions.txt index faaac602a5..46f3e70996 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1003,8 +1003,22 @@ NiranV Dean STORM-2050 STORM-2051 STORM-2052 + STORM-2057 + STORM-2058 + STORM-2059 + STORM-2060 + STORM-2061 + STORM-2063 + STORM-2064 + STORM-2065 + STORM-2066 BUG-372 BUG-1179 + BUG-6835 + BUG-6837 + BUG-6839 + BUG-6840 + BUG-6958 Nounouch Hapmouche VWR-238 Ollie Kubrick -- cgit v1.2.3 From ea79b23e85a4e526b222582a585a55d490724e87 Mon Sep 17 00:00:00 2001 From: NiranV Date: Thu, 14 Aug 2014 03:36:28 +0200 Subject: STORM-2064: Changed: Made background of status text invisible. #2 --- indra/newview/skins/default/xui/en/floater_snapshot.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index c0907d6031..f0a175902b 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -294,8 +294,7 @@ width="199" top_pad="-16"/> Date: Fri, 15 Aug 2014 18:35:00 +0200 Subject: BUG-7020: Fixed: Snapshot floater being resized while it's minimized. --- indra/newview/llfloatersnapshot.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index f927b50092..55dfad37d8 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -287,7 +287,10 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight()); floaterp->getChild("image_res_text")->setVisible(advanced); floaterp->getChild("file_size_label")->setVisible(advanced); - floaterp->reshape(floater_width, floaterp->getRect().getHeight()); + if(!floaterp->isMinimized()) + { + floaterp->reshape(floater_width, floaterp->getRect().getHeight()); + } bool use_freeze_frame = floaterp->getChild("freeze_frame_check")->getValue().asBoolean(); -- cgit v1.2.3 From e11451fc1d543759d397ecaa4cac7b720cc26506 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 15 Aug 2014 18:36:30 +0200 Subject: STORM-2060: Fixed: Height spinner not being detected as first changed. --- indra/newview/llfloatersnapshot.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 55dfad37d8..3f9243381c 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -813,7 +813,16 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL previewp->getSize(width, height); - updateSpinners(view, previewp, width, height, TRUE); // may change width and height + bool width_changed; + if(original_width != width) + { + width_changed = TRUE; + } + else + { + width_changed = FALSE; + } + updateSpinners(view, previewp, width, height, width_changed); // may change width and height if(getWidthSpinner(view)->getValue().asInteger() != width || getHeightSpinner(view)->getValue().asInteger() != height) { -- cgit v1.2.3 From b740891b1f19c3d0e9ee494ef3bdb8adc3dcb151 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Fri, 15 Aug 2014 19:40:21 +0300 Subject: MAINT-4293 [BEAR] Very slow inventory fetch on Bear compared to current release: this change-set will does this issue not [BEAR] and reverts most part of fix for MAINT-1192. --- indra/newview/llinventorypanel.cpp | 6 ------ indra/newview/llpanelmaininventory.cpp | 4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 32e5675f5e..ce7d4f50ad 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -337,12 +337,6 @@ void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType { if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT) { - //Don't show folder without recent item in it - if ("Recent Items" == getName()) - { - types &= ~(0x1 << LLInventoryType::IT_CATEGORY); - } - getFilter().setFilterObjectTypes(types); } if (filter_type == LLInventoryFilter::FILTERTYPE_CATEGORY) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index ddf1a63c6e..90dfb24377 100755 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -151,9 +151,7 @@ BOOL LLPanelMainInventory::postBuild() recent_items_panel->setSinceLogoff(TRUE); recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - LLInventoryFilter& recent_filter = recent_items_panel->getFilter(); - recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); - recent_filter.markDefault(); + recent_items_panel->getFilter().markDefault(); recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2)); } -- cgit v1.2.3 From 0d46af3d38eeeb295c0b12393668755871042661 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 15 Aug 2014 18:42:17 +0200 Subject: STORM-2064: Changed: Renamed 'Scanlines' filter to 'Video' and removed the old 'Video' one. --- indra/newview/app_settings/filters/Scanlines.xml | 30 ------------------------ indra/newview/app_settings/filters/Video.xml | 23 +++++++----------- 2 files changed, 8 insertions(+), 45 deletions(-) delete mode 100644 indra/newview/app_settings/filters/Scanlines.xml diff --git a/indra/newview/app_settings/filters/Scanlines.xml b/indra/newview/app_settings/filters/Scanlines.xml deleted file mode 100644 index e9ba2889fa..0000000000 --- a/indra/newview/app_settings/filters/Scanlines.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - stencil - scanlines - add-back - 0.0 - 1.0 - 0.015 - 0 - - - gamma - 0.5 - 1.0 - 1.0 - 1.0 - - - blur - - - \ No newline at end of file diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml index fe17f3950a..441a506d40 100755 --- a/indra/newview/app_settings/filters/Video.xml +++ b/indra/newview/app_settings/filters/Video.xml @@ -9,27 +9,23 @@ darken - 0.15 + 0.05 1.0 1.0 1.0 stencil - uniform - add - 0.0 - 0.5 - - - screen - line - 0.02 + scanlines + add-back 0.0 + 0.25 + 0.025 + 0 gamma - 0.25 + 0.0 1.0 1.0 1.0 @@ -37,8 +33,5 @@ blur - - blur - - + \ No newline at end of file -- cgit v1.2.3 From 2605ad9c01355ffc2b45b3d0ec74c4da451423f6 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 15 Aug 2014 21:25:31 +0200 Subject: STORM-2064: Changed: Reverted previous changes since Merov has clarified that it is intended behavior. --- indra/newview/app_settings/filters/Video.xml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml index 441a506d40..fe17f3950a 100755 --- a/indra/newview/app_settings/filters/Video.xml +++ b/indra/newview/app_settings/filters/Video.xml @@ -9,23 +9,27 @@ darken - 0.05 + 0.15 1.0 1.0 1.0 stencil - scanlines - add-back + uniform + add 0.0 - 0.25 - 0.025 - 0 + 0.5 - gamma + screen + line + 0.02 0.0 + + + gamma + 0.25 1.0 1.0 1.0 @@ -33,5 +37,8 @@ blur + + blur + - \ No newline at end of file + -- cgit v1.2.3 From bca5c1ed7956d2b32f1ba1609edd2f00566adc81 Mon Sep 17 00:00:00 2001 From: NiranV Date: Fri, 15 Aug 2014 22:41:10 +0200 Subject: Changed: Updated contributions file. --- doc/contributions.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/contributions.txt b/doc/contributions.txt index 46f3e70996..3b995bcb31 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1012,6 +1012,7 @@ NiranV Dean STORM-2064 STORM-2065 STORM-2066 + STORM-2068 BUG-372 BUG-1179 BUG-6835 -- cgit v1.2.3 From 2b66eeb4a61235fae4c29ecd98890b8b47badafe Mon Sep 17 00:00:00 2001 From: NiranV Date: Wed, 20 Aug 2014 01:38:50 +0200 Subject: STORM-2073: Fixed: Do not post our status if we press the "Connect" button otherwise we end up double posting. --- indra/newview/llfloaterfacebook.cpp | 7 +++++-- indra/newview/llfloaterfacebook.h | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 516cf5c15c..d8cc070fd0 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -156,7 +156,8 @@ void LLFacebookStatusPanel::onSend() { LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); - + + pressedConnect = FALSE; // Connect to Facebook if necessary and then post if (LLFacebookConnect::instance().isConnected()) { @@ -186,7 +187,8 @@ bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data) switch (data.get("enum").asInteger()) { case LLFacebookConnect::FB_CONNECTED: - sendStatus(); + if(!pressedConnect) + sendStatus(); break; case LLFacebookConnect::FB_POSTED: @@ -293,6 +295,7 @@ void LLFacebookStatusPanel::onConnect() { LLFacebookConnect::instance().checkConnectionToFacebook(true); + pressedConnect = TRUE; //Clear only the facebook browser cookies so that the facebook login screen appears LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index 86e3a148b9..e1526db18d 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -62,6 +62,8 @@ private: void showDisconnectedLayout(); void showConnectedLayout(); + bool pressedConnect; + LLTextBox * mAccountCaptionLabel; LLTextBox * mAccountNameLabel; LLUICtrl * mPanelButtons; -- cgit v1.2.3 From 5bdf2a0cda79e7cf67818489e8d3a86232863758 Mon Sep 17 00:00:00 2001 From: NiranV Date: Wed, 20 Aug 2014 04:06:15 +0200 Subject: STORM-2060/STORM-2076: Fixed: Whole detection logic not working because of reasons i cannot seem to understand in this hypercube like snapshot floater. --- indra/newview/llfloatersnapshot.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 3f9243381c..31b743b7e8 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -814,13 +814,13 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL previewp->getSize(width, height); bool width_changed; - if(original_width != width) + if(getHeightSpinner(view)->isDirty()) { - width_changed = TRUE; + width_changed = FALSE; } else { - width_changed = FALSE; + width_changed = TRUE; } updateSpinners(view, previewp, width, height, width_changed); // may change width and height @@ -952,6 +952,8 @@ void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshot *view // static void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed) { + getWidthSpinner(view)->resetDirty(); + getHeightSpinner(view)->resetDirty(); if (checkImageSize(previewp, width, height, is_width_changed, previewp->getMaxImageSize())) { setImageSizeSpinnersValues(view, width, height); -- cgit v1.2.3 From 417362e9d8555b77c8510430e2a4b3e8901be2b3 Mon Sep 17 00:00:00 2001 From: NiranV Date: Wed, 20 Aug 2014 16:04:50 +0200 Subject: STORM-2060/STORM-2076: Changed: Code to a more appropiate, shorter version. Thanks Oz. --- indra/newview/llfloatersnapshot.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 31b743b7e8..8037c22173 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -813,16 +813,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL previewp->getSize(width, height); - bool width_changed; - if(getHeightSpinner(view)->isDirty()) - { - width_changed = FALSE; - } - else - { - width_changed = TRUE; - } - updateSpinners(view, previewp, width, height, width_changed); // may change width and height + updateSpinners(view, previewp, width, height, !getHeightSpinner(view)->isDirty()); // may change width and height if(getWidthSpinner(view)->getValue().asInteger() != width || getHeightSpinner(view)->getValue().asInteger() != height) { -- cgit v1.2.3 From 887510c335ebd83dc7f61753443f2e35dc2a69e2 Mon Sep 17 00:00:00 2001 From: NiranV Date: Wed, 20 Aug 2014 16:07:01 +0200 Subject: Changed: Updated contributions file. --- doc/contributions.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/contributions.txt b/doc/contributions.txt index 3b995bcb31..4035dc7da2 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1009,10 +1009,11 @@ NiranV Dean STORM-2060 STORM-2061 STORM-2063 - STORM-2064 STORM-2065 STORM-2066 STORM-2068 + STORM-2073 + STORM-2076 BUG-372 BUG-1179 BUG-6835 @@ -1020,6 +1021,7 @@ NiranV Dean BUG-6839 BUG-6840 BUG-6958 + BUG-7020 Nounouch Hapmouche VWR-238 Ollie Kubrick -- cgit v1.2.3 From 7e5ede1678ef6b167602b3d8d0660c5e89e319f5 Mon Sep 17 00:00:00 2001 From: NiranV Date: Wed, 20 Aug 2014 16:56:18 +0200 Subject: STORM-2060/STORM-2076: Added: Commenting to explain why we use the height spinner instead of the width one. --- indra/newview/llfloatersnapshot.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 8037c22173..8677028942 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llfloatersnapshot.cpp * @brief Snapshot preview window, allowing saving, e-mailing, etc. * @@ -813,6 +813,10 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL previewp->getSize(width, height); + // We use the height spinner here because we come here via the aspect ratio + // checkbox as well and we want height always changing to width by default. + // If we use the width spinner we would change width according to height by + // default, that is not what we want. updateSpinners(view, previewp, width, height, !getHeightSpinner(view)->isDirty()); // may change width and height if(getWidthSpinner(view)->getValue().asInteger() != width || getHeightSpinner(view)->getValue().asInteger() != height) -- cgit v1.2.3 From 0a134e749d01b711ca38a91044efb787cd815701 Mon Sep 17 00:00:00 2001 From: NiranV Date: Wed, 20 Aug 2014 16:57:30 +0200 Subject: Fixed: Line endings. --- indra/newview/llfloaterfacebook.cpp | 260 ++++++++++++++++++------------------ indra/newview/llfloaterfacebook.h | 34 ++--- 2 files changed, 147 insertions(+), 147 deletions(-) diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index d8cc070fd0..33422fb5fd 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -98,27 +98,27 @@ S32 compute_jpeg_quality(S32 width, S32 height) LLFacebookStatusPanel::LLFacebookStatusPanel() : mMessageTextEditor(NULL), mPostButton(NULL), - mCancelButton(NULL), - mAccountCaptionLabel(NULL), - mAccountNameLabel(NULL), - mPanelButtons(NULL), - mConnectButton(NULL), + mCancelButton(NULL), + mAccountCaptionLabel(NULL), + mAccountNameLabel(NULL), + mPanelButtons(NULL), + mConnectButton(NULL), mDisconnectButton(NULL) { - mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); - mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); - - setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); + mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); + + setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this)); } BOOL LLFacebookStatusPanel::postBuild() { - mAccountCaptionLabel = getChild("account_caption_label"); - mAccountNameLabel = getChild("account_name_label"); - mPanelButtons = getChild("panel_buttons"); - mConnectButton = getChild("connect_btn"); + mAccountCaptionLabel = getChild("account_caption_label"); + mAccountNameLabel = getChild("account_name_label"); + mPanelButtons = getChild("panel_buttons"); + mConnectButton = getChild("connect_btn"); mDisconnectButton = getChild("disconnect_btn"); mMessageTextEditor = getChild("status_message"); @@ -130,15 +130,15 @@ BOOL LLFacebookStatusPanel::postBuild() void LLFacebookStatusPanel::draw() { - LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); - - //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress - bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; - mDisconnectButton->setEnabled(!disconnecting); - - //Disable the 'connect' button when a connection is in progress - bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; - mConnectButton->setEnabled(!connecting); + LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); + + //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress + bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; + mDisconnectButton->setEnabled(!disconnecting); + + //Disable the 'connect' button when a connection is in progress + bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; + mConnectButton->setEnabled(!connecting); if (mMessageTextEditor && mPostButton && mCancelButton) { @@ -171,18 +171,18 @@ void LLFacebookStatusPanel::onSend() bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data) { - if(LLFacebookConnect::instance().isConnected()) - { - //In process of disconnecting so leave the layout as is - if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) - { - showConnectedLayout(); - } - } - else - { - showDisconnectedLayout(); - } + if(LLFacebookConnect::instance().isConnected()) + { + //In process of disconnecting so leave the layout as is + if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) + { + showConnectedLayout(); + } + } + else + { + showDisconnectedLayout(); + } switch (data.get("enum").asInteger()) { @@ -209,102 +209,102 @@ void LLFacebookStatusPanel::sendStatus() } } -void LLFacebookStatusPanel::onVisibilityChange(BOOL visible) -{ - if(visible) - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); - - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); - - //Connected - if(LLFacebookConnect::instance().isConnected()) - { - showConnectedLayout(); - } - //Check if connected (show disconnected layout in meantime) - else - { - showDisconnectedLayout(); - } - if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || - (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) - { - LLFacebookConnect::instance().checkConnectionToFacebook(); - } - } - else - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - } -} - -bool LLFacebookStatusPanel::onFacebookConnectInfoChange() -{ - LLSD info = LLFacebookConnect::instance().getInfo(); - std::string clickable_name; - - //Strings of format [http://www.somewebsite.com Click Me] become clickable text - if(info.has("link") && info.has("name")) - { - clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; - } - - mAccountNameLabel->setText(clickable_name); - - return false; -} - -void LLFacebookStatusPanel::showConnectButton() -{ - if(!mConnectButton->getVisible()) - { - mConnectButton->setVisible(TRUE); - mDisconnectButton->setVisible(FALSE); - } -} - -void LLFacebookStatusPanel::hideConnectButton() -{ - if(mConnectButton->getVisible()) - { - mConnectButton->setVisible(FALSE); - mDisconnectButton->setVisible(TRUE); - } -} - -void LLFacebookStatusPanel::showDisconnectedLayout() -{ - mAccountCaptionLabel->setText(getString("facebook_disconnected")); - mAccountNameLabel->setText(std::string("")); - showConnectButton(); -} - -void LLFacebookStatusPanel::showConnectedLayout() -{ - LLFacebookConnect::instance().loadFacebookInfo(); - - mAccountCaptionLabel->setText(getString("facebook_connected")); - hideConnectButton(); -} - -void LLFacebookStatusPanel::onConnect() -{ - LLFacebookConnect::instance().checkConnectionToFacebook(true); - - pressedConnect = TRUE; - //Clear only the facebook browser cookies so that the facebook login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); -} - -void LLFacebookStatusPanel::onDisconnect() -{ - LLFacebookConnect::instance().disconnectFromFacebook(); - - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +void LLFacebookStatusPanel::onVisibilityChange(BOOL visible) +{ + if(visible) + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); + + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); + + //Connected + if(LLFacebookConnect::instance().isConnected()) + { + showConnectedLayout(); + } + //Check if connected (show disconnected layout in meantime) + else + { + showDisconnectedLayout(); + } + if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || + (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) + { + LLFacebookConnect::instance().checkConnectionToFacebook(); + } + } + else + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + } +} + +bool LLFacebookStatusPanel::onFacebookConnectInfoChange() +{ + LLSD info = LLFacebookConnect::instance().getInfo(); + std::string clickable_name; + + //Strings of format [http://www.somewebsite.com Click Me] become clickable text + if(info.has("link") && info.has("name")) + { + clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; + } + + mAccountNameLabel->setText(clickable_name); + + return false; +} + +void LLFacebookStatusPanel::showConnectButton() +{ + if(!mConnectButton->getVisible()) + { + mConnectButton->setVisible(TRUE); + mDisconnectButton->setVisible(FALSE); + } +} + +void LLFacebookStatusPanel::hideConnectButton() +{ + if(mConnectButton->getVisible()) + { + mConnectButton->setVisible(FALSE); + mDisconnectButton->setVisible(TRUE); + } +} + +void LLFacebookStatusPanel::showDisconnectedLayout() +{ + mAccountCaptionLabel->setText(getString("facebook_disconnected")); + mAccountNameLabel->setText(std::string("")); + showConnectButton(); +} + +void LLFacebookStatusPanel::showConnectedLayout() +{ + LLFacebookConnect::instance().loadFacebookInfo(); + + mAccountCaptionLabel->setText(getString("facebook_connected")); + hideConnectButton(); +} + +void LLFacebookStatusPanel::onConnect() +{ + LLFacebookConnect::instance().checkConnectionToFacebook(true); + + pressedConnect = TRUE; + //Clear only the facebook browser cookies so that the facebook login screen appears + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +} + +void LLFacebookStatusPanel::onDisconnect() +{ + LLFacebookConnect::instance().disconnectFromFacebook(); + + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } void LLFacebookStatusPanel::clearAndClose() diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index e1526db18d..6fe7a6541b 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -51,23 +51,23 @@ public: void clearAndClose(); private: - void onVisibilityChange(BOOL new_visibility); - bool onFacebookConnectInfoChange(); - void onConnect(); - void onUseAnotherAccount(); - void onDisconnect(); - - void showConnectButton(); - void hideConnectButton(); - void showDisconnectedLayout(); - void showConnectedLayout(); - - bool pressedConnect; - - LLTextBox * mAccountCaptionLabel; - LLTextBox * mAccountNameLabel; - LLUICtrl * mPanelButtons; - LLUICtrl * mConnectButton; + void onVisibilityChange(BOOL new_visibility); + bool onFacebookConnectInfoChange(); + void onConnect(); + void onUseAnotherAccount(); + void onDisconnect(); + + void showConnectButton(); + void hideConnectButton(); + void showDisconnectedLayout(); + void showConnectedLayout(); + + bool pressedConnect; + + LLTextBox * mAccountCaptionLabel; + LLTextBox * mAccountNameLabel; + LLUICtrl * mPanelButtons; + LLUICtrl * mConnectButton; LLUICtrl * mDisconnectButton; LLUICtrl* mMessageTextEditor; LLUICtrl* mPostButton; -- cgit v1.2.3 From 7fa382937679a9937fd7b09e33b6c2f39ec680ff Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Thu, 21 Aug 2014 15:20:31 -0400 Subject: Remove viewer-side throttles on mesh requests. --- indra/newview/llappcorehttp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 464e60948a..e9274c5c1e 100755 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -65,12 +65,12 @@ static const struct "texture fetch" }, { // AP_MESH1 - 32, 1, 128, 100, false, + 32, 1, 128, 0, false, "MeshMaxConcurrentRequests", "mesh fetch" }, { // AP_MESH2 - 8, 1, 32, 100, true, + 8, 1, 32, 0, true, "Mesh2MaxConcurrentRequests", "mesh2 fetch" }, -- cgit v1.2.3 From d632f91d942404f15d24fce741f12904f024798a Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 21 Aug 2014 16:12:40 -0700 Subject: GAMING-19 : Unknown content message on attempting to enter an SLSG restricted region with an ineligible account. --- indra/newview/llviewermessage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 703c6d87c6..9554f06342 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5828,11 +5828,11 @@ bool handle_teleport_access_blocked(LLSD& llsdBlock) maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); returnValue = true; } - } + } - if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) + // If we have a notification but it is normally ignored, give a simple one instead of an in-your-face dialog + if (returnValue && (maturityLevelNotification != NULL) && maturityLevelNotification->isIgnored()) { - // Given a simple notification if no maturityLevelNotification is set or it is ignore LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); } -- cgit v1.2.3 From 123f8e77cd643dcb8f701fafdaf1233e3ef03892 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Fri, 22 Aug 2014 16:38:37 +0300 Subject: MAINT-4288 FIXED Backed out changeset for MAINT-4018 (c92d43623c2c) --- indra/newview/llavatariconctrl.cpp | 5 ++--- indra/newview/llviewertexture.cpp | 11 ----------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b89b0d9900..746b541f9d 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -247,7 +247,7 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) { LLAvatarPropertiesProcessor* app = LLAvatarPropertiesProcessor::getInstance(); - if (mAvatarId.notNull() && mAvatarId != value.asUUID()) + if (mAvatarId.notNull()) { app->removeObserver(mAvatarId, this); } @@ -255,7 +255,6 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) if (mAvatarId != value.asUUID()) { mAvatarId = value.asUUID(); - app->addObserver(mAvatarId, this); // *BUG: This will return stale icons if a user changes their // profile picture. However, otherwise we send too many upstream @@ -271,7 +270,7 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) // People API, rather than sending AvatarPropertyRequest // messages. People API already hits the user table. LLIconCtrl::setValue(mDefaultIconName); - // duplicated requests are filtered later if there are any + app->addObserver(mAvatarId, this); app->sendAvatarPropertiesRequest(mAvatarId); } } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 3f6d244af1..4e2eef39d6 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1480,17 +1480,6 @@ void LLViewerFetchedTexture::processTextureStats() { mDesiredDiscardLevel = 0; } - else if (mDontDiscard && (mBoostLevel == LLGLTexture::BOOST_UI || mBoostLevel == LLGLTexture::BOOST_ICON)) - { - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) - { - mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 - } - else - { - mDesiredDiscardLevel = 0; - } - } else if(!mFullWidth || !mFullHeight) { mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel); -- cgit v1.2.3 From 85cba58ad473ed28efda7f645af20d56229e8637 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 22 Aug 2014 18:04:27 -0400 Subject: Add an HTTP policy class for inventory operations using four (4) connections. Convert background and foreground fetches, both items and folders/inventory and library, to use new HTTP. Non-fetch inventory operations continue to use LLHTTPClient (at least for now). Error handling and retry on fetches wasn't 100% previously and that's still the case. I'll rip through this again to clean that up. Cleaned up logging in much of the inventory code with consistent labels on logging events and correct macros (removed deprecation warnings). This started as an attempt to get libcurl to do pipelining on POSTs and PUTs. Discovered that this is going to be very difficult to support in general in libcurl. May look at that again in the future. --- indra/newview/llappcorehttp.cpp | 9 +- indra/newview/llappcorehttp.h | 18 +- indra/newview/llinventorymodel.cpp | 601 ++++++++++++------ indra/newview/llinventorymodel.h | 82 ++- indra/newview/llinventorymodelbackgroundfetch.cpp | 740 +++++++++++++--------- indra/newview/llinventorymodelbackgroundfetch.h | 28 +- indra/newview/llinventoryobserver.cpp | 3 +- indra/newview/llsnapshotlivepreview.cpp | 16 +- indra/newview/llviewerinventory.cpp | 128 ++-- indra/newview/llviewermenu.cpp | 4 +- 10 files changed, 1034 insertions(+), 595 deletions(-) diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 464e60948a..2b7d91b5ff 100755 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -60,7 +60,7 @@ static const struct "other" }, { // AP_TEXTURE - 8, 1, 12, 0, true, + 8, 1, 12, 0, true, "TextureFetchConcurrency", "texture fetch" }, @@ -70,7 +70,7 @@ static const struct "mesh fetch" }, { // AP_MESH2 - 8, 1, 32, 100, true, + 8, 1, 32, 100, true, "Mesh2MaxConcurrentRequests", "mesh2 fetch" }, @@ -88,6 +88,11 @@ static const struct 32, 32, 32, 0, false, "", "long poll" + }, + { // AP_INVENTORY + 4, 1, 4, 0, false, + "", + "inventory" } }; diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h index 9ad4eb4b30..e822a40300 100755 --- a/indra/newview/llappcorehttp.h +++ b/indra/newview/llappcorehttp.h @@ -64,7 +64,7 @@ public: /// Texture fetching policy class. Used to /// download textures via capability or SSA /// baking service. Deep queueing of requests. - /// Do not share. + /// Do not share. GET requests only. /// /// Destination: simhost:12046 & bake-texture:80 /// Protocol: http: @@ -92,7 +92,8 @@ public: /// download textures via 'GetMesh2' capability. /// Used when fetch request (typically one LOD) /// is 'small', currently defined as 2MB. - /// Very deeply queued. Do not share. + /// Very deeply queued. Do not share. GET + /// requests only. /// /// Destination: simhost:12046 /// Protocol: http: @@ -150,6 +151,19 @@ public: /// Pipelined: no AP_LONG_POLL, + /// Inventory operations (really Capabilities- + /// related operations). Mix of high-priority + /// and low-priority operations. + /// + /// Destination: simhost:12043 + /// Protocol: https: + /// Transfer size: KB-MB + /// Long poll: no + /// Concurrency: high + /// Request rate: high + /// Pipelined: no + AP_INVENTORY, + AP_COUNT // Must be last }; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 14ca0095ae..2dd31f047f 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,9 @@ */ #include "llviewerprecompiledheaders.h" + +#include + #include "llinventorymodel.h" #include "llaisapi.h" @@ -50,7 +53,9 @@ #include "llvoavatarself.h" #include "llgesturemgr.h" #include "llsdutil.h" -#include +#include "bufferarray.h" +#include "bufferstream.h" +#include "llsdserialize.h" //#define DIFF_INVENTORY_FILES #ifdef DIFF_INVENTORY_FILES @@ -67,7 +72,14 @@ BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; ///---------------------------------------------------------------------------- //BOOL decompress_file(const char* src_filename, const char* dst_filename); -const char CACHE_FORMAT_STRING[] = "%s.inv"; +static const char CACHE_FORMAT_STRING[] = "%s.inv"; +static const char * const LOG_INV("Inventory"); + +static std::string dumpResponse() +{ + return std::string("ADD SOMETHING MEANINGFUL HERE"); +} + struct InventoryIDPtrLess { @@ -125,24 +137,32 @@ LLInventoryModel gInventory; // Default constructor LLInventoryModel::LLInventoryModel() -: mModifyMask(LLInventoryObserver::ALL), - mChangedItemIDs(), +: // These are now ordered, keep them that way. mBacklinkMMap(), + mIsAgentInvUsable(false), + mRootFolderID(), + mLibraryRootFolderID(), + mLibraryOwnerID(), mCategoryMap(), mItemMap(), - mCategoryLock(), - mItemLock(), - mLastItem(NULL), mParentChildCategoryTree(), mParentChildItemTree(), - mObservers(), - mRootFolderID(), - mLibraryRootFolderID(), - mLibraryOwnerID(), + mLastItem(NULL), mIsNotifyObservers(FALSE), - mIsAgentInvUsable(false) -{ -} + mModifyMask(LLInventoryObserver::ALL), + mChangedItemIDs(), + mObservers(), + mHttpRequestFG(NULL), + mHttpRequestBG(NULL), + mHttpOptions(NULL), + mHttpHeaders(NULL), + mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), + mHttpPriorityFG(0), + mHttpPriorityBG(0), + mCategoryLock(), + mItemLock() +{} + // Destroys the object LLInventoryModel::~LLInventoryModel() @@ -162,6 +182,22 @@ void LLInventoryModel::cleanupInventory() delete observer; } mObservers.clear(); + + // Run down HTTP transport + if (mHttpHeaders) + { + mHttpHeaders->release(); + mHttpHeaders = NULL; + } + if (mHttpOptions) + { + mHttpOptions->release(); + mHttpOptions = NULL; + } + delete mHttpRequestFG; + mHttpRequestFG = NULL; + delete mHttpRequestBG; + mHttpRequestBG = NULL; } // This is a convenience function to check if one object has a parent @@ -253,7 +289,7 @@ bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& LLInventoryObject *parent_object = getObject(object->getParentUUID()); if (!parent_object) { - LL_WARNS() << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL; + LL_WARNS(LOG_INV) << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL; return false; } object = parent_object; @@ -508,7 +544,7 @@ public: protected: virtual void httpFailure() { - LL_WARNS("InvAPI") << dumpResponse() << LL_ENDL; + LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; } virtual void httpSuccess() @@ -522,7 +558,7 @@ protected: } LLUUID category_id = content["folder_id"].asUUID(); - LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << LL_ENDL; + LL_DEBUGS(LOG_INV) << ll_pretty_print_sd(content) << LL_ENDL; // Add the category to the internal representation LLPointer cat = new LLViewerInventoryCategory( category_id, @@ -560,13 +596,13 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLUUID id; if(!isInventoryUsable()) { - LL_WARNS() << "Inventory is broken." << LL_ENDL; + LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL; return id; } if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup()) { - LL_DEBUGS() << "Attempt to create undefined category." << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL; return id; } @@ -599,7 +635,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, request["message"] = "CreateInventoryCategory"; request["payload"] = body; - LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << LL_ENDL; + LL_DEBUGS(LOG_INV) << "create category request: " << ll_pretty_print_sd(request) << LL_ENDL; // viewer_region->getCapAPI().post(request); LLHTTPClient::post( url, @@ -820,7 +856,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) if(!isInventoryUsable()) { - LL_WARNS() << "Inventory is broken." << LL_ENDL; + LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL; return mask; } @@ -883,7 +919,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) } else { - LL_WARNS() << "Couldn't find parent-child item tree for " << new_item->getName() << LL_ENDL; + LL_WARNS(LOG_INV) << "Couldn't find parent-child item tree for " << new_item->getName() << LL_ENDL; } } else @@ -912,8 +948,8 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) else { // Whoops! No such parent, make one. - LL_INFOS() << "Lost item: " << new_item->getUUID() << " - " - << new_item->getName() << LL_ENDL; + LL_INFOS(LOG_INV) << "Lost item: " << new_item->getUUID() << " - " + << new_item->getName() << LL_ENDL; parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); new_item->setParent(parent_id); item_array = get_ptr_in_map(mParentChildItemTree, parent_id); @@ -926,7 +962,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) } else { - LL_WARNS() << "Lost and found Not there!!" << LL_ENDL; + LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL; } } } @@ -1000,7 +1036,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 if(!isInventoryUsable()) { - LL_WARNS() << "Inventory is broken." << LL_ENDL; + LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL; return; } @@ -1062,17 +1098,17 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) { - LL_DEBUGS() << "LLInventoryModel::moveObject()" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "LLInventoryModel::moveObject()" << LL_ENDL; if(!isInventoryUsable()) { - LL_WARNS() << "Inventory is broken." << LL_ENDL; + LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL; return; } if((object_id == cat_id) || !is_in_map(mCategoryMap, cat_id)) { - LL_WARNS() << "Could not move inventory object " << object_id << " to " - << cat_id << LL_ENDL; + LL_WARNS(LOG_INV) << "Could not move inventory object " << object_id << " to " + << cat_id << LL_ENDL; return; } LLPointer cat = getCategory(object_id); @@ -1108,14 +1144,14 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, { if (item->getParentUUID() == new_parent_id) { - LL_DEBUGS("Inventory") << "'" << item->getName() << "' (" << item->getUUID() - << ") is already in folder " << new_parent_id << LL_ENDL; + LL_DEBUGS(LOG_INV) << "'" << item->getName() << "' (" << item->getUUID() + << ") is already in folder " << new_parent_id << LL_ENDL; } else { - LL_INFOS("Inventory") << "Moving '" << item->getName() << "' (" << item->getUUID() - << ") from " << item->getParentUUID() << " to folder " - << new_parent_id << LL_ENDL; + LL_INFOS(LOG_INV) << "Moving '" << item->getName() << "' (" << item->getUUID() + << ") from " << item->getParentUUID() << " to folder " + << new_parent_id << LL_ENDL; LLInventoryModel::update_list_t update; LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); update.push_back(old_folder); @@ -1171,7 +1207,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS AISUpdate ais_update(update); // parse update llsd into stuff to do. ais_update.doUpdate(); // execute the updates in the appropriate order. - LL_INFOS() << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; + LL_INFOS(LOG_INV) << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; } // Does not appear to be used currently. @@ -1180,7 +1216,7 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, U32 mask = LLInventoryObserver::NONE; LLPointer item = gInventory.getItem(item_id); - LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << LL_ENDL; + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << LL_ENDL; if(item) { for (LLSD::map_const_iterator it = updates.beginMap(); @@ -1188,19 +1224,19 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, { if (it->first == "name") { - LL_INFOS() << "Updating name from " << item->getName() << " to " << it->second.asString() << LL_ENDL; + LL_INFOS(LOG_INV) << "Updating name from " << item->getName() << " to " << it->second.asString() << LL_ENDL; item->rename(it->second.asString()); mask |= LLInventoryObserver::LABEL; } else if (it->first == "desc") { - LL_INFOS() << "Updating description from " << item->getActualDescription() - << " to " << it->second.asString() << LL_ENDL; + LL_INFOS(LOG_INV) << "Updating description from " << item->getActualDescription() + << " to " << it->second.asString() << LL_ENDL; item->setDescription(it->second.asString()); } else { - LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL; + LL_ERRS(LOG_INV) << "unhandled updates for field: " << it->first << LL_ENDL; } } mask |= LLInventoryObserver::INTERNAL; @@ -1211,7 +1247,7 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0); accountForUpdate(up); } - gInventory.notifyObservers(); // do we want to be able to make this optional? + notifyObservers(); // do we want to be able to make this optional? } } @@ -1221,7 +1257,7 @@ void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updat U32 mask = LLInventoryObserver::NONE; LLPointer cat = gInventory.getCategory(cat_id); - LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << LL_ENDL; + LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << LL_ENDL; if(cat) { for (LLSD::map_const_iterator it = updates.beginMap(); @@ -1229,18 +1265,18 @@ void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updat { if (it->first == "name") { - LL_INFOS() << "Updating name from " << cat->getName() << " to " << it->second.asString() << LL_ENDL; + LL_INFOS(LOG_INV) << "Updating name from " << cat->getName() << " to " << it->second.asString() << LL_ENDL; cat->rename(it->second.asString()); mask |= LLInventoryObserver::LABEL; } else { - LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL; + LL_ERRS(LOG_INV) << "unhandled updates for field: " << it->first << LL_ENDL; } } mask |= LLInventoryObserver::INTERNAL; addChangedMask(mask, cat->getUUID()); - gInventory.notifyObservers(); // do we want to be able to make this optional? + notifyObservers(); // do we want to be able to make this optional? } } @@ -1317,8 +1353,8 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo while (deleted_count > 0); if (total_deleted_count != count) { - LL_WARNS() << "Unexpected count of categories deleted, got " - << total_deleted_count << " expected " << count << LL_ENDL; + LL_WARNS(LOG_INV) << "Unexpected count of categories deleted, got " + << total_deleted_count << " expected " << count << LL_ENDL; } //gInventory.validate(); } @@ -1355,15 +1391,15 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f // Delete a particular inventory object by ID. void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, bool do_notify_observers) { - LL_DEBUGS() << "LLInventoryModel::deleteObject()" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "LLInventoryModel::deleteObject()" << LL_ENDL; LLPointer obj = getObject(id); if (!obj) { - LL_WARNS() << "Deleting non-existent object [ id: " << id << " ] " << LL_ENDL; + LL_WARNS(LOG_INV) << "Deleting non-existent object [ id: " << id << " ] " << LL_ENDL; return; } - LL_DEBUGS() << "Deleting inventory object " << id << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Deleting inventory object " << id << LL_ENDL; mLastItem = NULL; LLUUID parent_id = obj->getParentUUID(); mCategoryMap.erase(id); @@ -1386,7 +1422,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo { if (item_list->size()) { - LL_WARNS() << "Deleting cat " << id << " while it still has child items" << LL_ENDL; + LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child items" << LL_ENDL; } delete item_list; mParentChildItemTree.erase(id); @@ -1396,7 +1432,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo { if (cat_list->size()) { - LL_WARNS() << "Deleting cat " << id << " while it still has child cats" << LL_ENDL; + LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child cats" << LL_ENDL; } delete cat_list; mParentChildCategoryTree.erase(id); @@ -1431,7 +1467,7 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) // everything else on the changelist will also get rebuilt. if (item_array.size() > 0) { - gInventory.notifyObservers(); + notifyObservers(); for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); iter != item_array.end(); iter++) @@ -1441,7 +1477,7 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) if (item_id == baseobj_id) continue; addChangedMask(LLInventoryObserver::REBUILD, item_id); } - gInventory.notifyObservers(); + notifyObservers(); } } @@ -1464,6 +1500,9 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const void LLInventoryModel::idleNotifyObservers() { + // *FIX: Think I want this conditional or moved elsewhere... + handleResponses(true); + if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0)) { return; @@ -1479,7 +1518,7 @@ void LLInventoryModel::notifyObservers() // Within notifyObservers, something called notifyObservers // again. This type of recursion is unsafe because it causes items to be // processed twice, and this can easily lead to infinite loops. - LL_WARNS() << "Call was made to notifyObservers within notifyObservers!" << LL_ENDL; + LL_WARNS(LOG_INV) << "Call was made to notifyObservers within notifyObservers!" << LL_ENDL; return; } @@ -1509,18 +1548,18 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) // Something marked an item for change within a call to notifyObservers // (which is in the process of processing the list of items marked for change). // This means the change may fail to be processed. - LL_WARNS() << "Adding changed mask within notify observers! Change will likely be lost." << LL_ENDL; + LL_WARNS(LOG_INV) << "Adding changed mask within notify observers! Change will likely be lost." << LL_ENDL; LLViewerInventoryItem *item = getItem(referent); if (item) { - LL_WARNS() << "Item " << item->getName() << LL_ENDL; + LL_WARNS(LOG_INV) << "Item " << item->getName() << LL_ENDL; } else { LLViewerInventoryCategory *cat = getCategory(referent); if (cat) { - LL_WARNS() << "Category " << cat->getName() << LL_ENDL; + LL_WARNS(LOG_INV) << "Category " << cat->getName() << LL_ENDL; } } } @@ -1544,91 +1583,18 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) } } -// If we get back a normal response, handle it here -void LLInventoryModel::fetchInventoryResponder::httpSuccess() -{ - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - start_new_inventory_observer(); - - /*LLUUID agent_id; - agent_id = content["agent_id"].asUUID(); - if(agent_id != gAgent.getID()) - { - LL_WARNS() << "Got a inventory update for the wrong agent: " << agent_id - << LL_ENDL; - return; - }*/ - item_array_t items; - update_map_t update; - S32 count = content["items"].size(); - LLUUID folder_id; - // Does this loop ever execute more than once? - for(S32 i = 0; i < count; ++i) - { - LLPointer titem = new LLViewerInventoryItem; - titem->unpackMessage(content["items"][i]); - - LL_DEBUGS() << "LLInventoryModel::fetchInventoryResponder item id: " - << titem->getUUID() << LL_ENDL; - items.push_back(titem); - // examine update for changes. - LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID()); - if(itemp) - { - if(titem->getParentUUID() == itemp->getParentUUID()) - { - update[titem->getParentUUID()]; - } - else - { - ++update[titem->getParentUUID()]; - --update[itemp->getParentUUID()]; - } - } - else - { - ++update[titem->getParentUUID()]; - } - if (folder_id.isNull()) - { - folder_id = titem->getParentUUID(); - } - } - - U32 changes = 0x0; - //as above, this loop never seems to loop more than once per call - for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) - { - changes |= gInventory.updateItem(*it); - } - gInventory.notifyObservers(); - gViewerWindow->getWindow()->decBusyCount(); -} - -//If we get back an error (not found, etc...), handle it here -void LLInventoryModel::fetchInventoryResponder::httpFailure() -{ - LL_WARNS() << dumpResponse() << LL_ENDL; - gInventory.notifyObservers(); -} - bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) const { if(folder_id.isNull()) { - LL_WARNS() << "Calling fetch descendents on NULL folder id!" << LL_ENDL; + LL_WARNS(LOG_INV) << "Calling fetch descendents on NULL folder id!" << LL_ENDL; return false; } LLViewerInventoryCategory* cat = getCategory(folder_id); if(!cat) { - LL_WARNS() << "Asked to fetch descendents of non-existent folder: " - << folder_id << LL_ENDL; + LL_WARNS(LOG_INV) << "Asked to fetch descendents of non-existent folder: " + << folder_id << LL_ENDL; return false; } //S32 known_descendents = 0; @@ -1649,8 +1615,8 @@ void LLInventoryModel::cache( const LLUUID& parent_folder_id, const LLUUID& agent_id) { - LL_DEBUGS() << "Caching " << parent_folder_id << " for " << agent_id - << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Caching " << parent_folder_id << " for " << agent_id + << LL_ENDL; LLViewerInventoryCategory* root_cat = getCategory(parent_folder_id); if(!root_cat) return; cat_array_t categories; @@ -1675,19 +1641,19 @@ void LLInventoryModel::cache( gzip_filename.append(".gz"); if(gzip_file(inventory_filename, gzip_filename)) { - LL_DEBUGS() << "Successfully compressed " << inventory_filename << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Successfully compressed " << inventory_filename << LL_ENDL; LLFile::remove(inventory_filename); } else { - LL_WARNS() << "Unable to compress " << inventory_filename << LL_ENDL; + LL_WARNS(LOG_INV) << "Unable to compress " << inventory_filename << LL_ENDL; } } void LLInventoryModel::addCategory(LLViewerInventoryCategory* category) { - //LL_INFOS() << "LLInventoryModel::addCategory()" << LL_ENDL; + //LL_INFOS(LOG_INV) << "LLInventoryModel::addCategory()" << LL_ENDL; if(category) { // We aren't displaying the Meshes folder @@ -1757,7 +1723,9 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) if ((item->getType() == LLAssetType::AT_NONE) || LLAssetType::lookup(item->getType()) == LLAssetType::badLookup()) { - LL_WARNS() << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ], ignoring." << LL_ENDL; + LL_WARNS(LOG_INV) << "Got bad asset type for item [ name: " << item->getName() + << " type: " << item->getType() + << " inv-type: " << item->getInventoryType() << " ], ignoring." << LL_ENDL; return; } @@ -1765,7 +1733,9 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // The item will show up as a broken link. if (item->getIsBrokenLink()) { - LL_INFOS() << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << LL_ENDL; + LL_INFOS(LOG_INV) << "Adding broken link [ name: " << item->getName() + << " itemID: " << item->getUUID() + << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << LL_ENDL; } if (item->getIsLinkType()) { @@ -1781,7 +1751,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // Empty the entire contents void LLInventoryModel::empty() { -// LL_INFOS() << "LLInventoryModel::empty()" << LL_ENDL; +// LL_INFOS(LOG_INV) << "LLInventoryModel::empty()" << LL_ENDL; std::for_each( mParentChildCategoryTree.begin(), mParentChildCategoryTree.end(), @@ -1814,29 +1784,29 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const descendents_actual += update.mDescendentDelta; cat->setDescendentCount(descendents_actual); cat->setVersion(++version); - LL_DEBUGS("Inventory") << "accounted: '" << cat->getName() << "' " - << version << " with " << descendents_actual - << " descendents." << LL_ENDL; + LL_DEBUGS(LOG_INV) << "accounted: '" << cat->getName() << "' " + << version << " with " << descendents_actual + << " descendents." << LL_ENDL; } else { // Error condition, this means that the category did not register that // it got new descendents (perhaps because it is still being loaded) // which means its descendent count will be wrong. - LL_WARNS() << "Accounting failed for '" << cat->getName() << "' version:" - << version << " due to mismatched descendent count: server == " - << descendents_server << ", viewer == " << descendents_actual << LL_ENDL; + LL_WARNS(LOG_INV) << "Accounting failed for '" << cat->getName() << "' version:" + << version << " due to mismatched descendent count: server == " + << descendents_server << ", viewer == " << descendents_actual << LL_ENDL; } } else { - LL_WARNS() << "Accounting failed for '" << cat->getName() << "' version: unknown (" - << version << ")" << LL_ENDL; + LL_WARNS(LOG_INV) << "Accounting failed for '" << cat->getName() << "' version: unknown (" + << version << ")" << LL_ENDL; } } else { - LL_WARNS() << "No category found for update " << update.mCategoryID << LL_ENDL; + LL_WARNS(LOG_INV) << "No category found for update " << update.mCategoryID << LL_ENDL; } } @@ -1918,7 +1888,7 @@ bool LLInventoryModel::loadSkeleton( const LLSD& options, const LLUUID& owner_id) { - LL_DEBUGS() << "importing inventory skeleton for " << owner_id << LL_ENDL; + LL_DEBUGS(LOG_INV) << "importing inventory skeleton for " << owner_id << LL_ENDL; typedef std::set, InventoryIDPtrLess> cat_set_t; cat_set_t temp_cats; @@ -1955,7 +1925,7 @@ bool LLInventoryModel::loadSkeleton( } else { - LL_WARNS() << "Unable to import near " << name.asString() << LL_ENDL; + LL_WARNS(LOG_INV) << "Unable to import near " << name.asString() << LL_ENDL; rv = false; } } @@ -1992,7 +1962,7 @@ bool LLInventoryModel::loadSkeleton( } else { - LL_INFOS() << "Unable to gunzip " << gzip_filename << LL_ENDL; + LL_INFOS(LOG_INV) << "Unable to gunzip " << gzip_filename << LL_ENDL; } } bool is_cache_obsolete = false; @@ -2073,10 +2043,10 @@ bool LLInventoryModel::loadSkeleton( if (item->getIsBrokenLink()) { //bad_link_count++; - LL_DEBUGS() << "Attempted to add cached link item without baseobj present ( name: " - << item->getName() << " itemID: " << item->getUUID() - << " assetID: " << item->getAssetUUID() - << " ). Ignoring and invalidating " << cat->getName() << " . " << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Attempted to add cached link item without baseobj present ( name: " + << item->getName() << " itemID: " << item->getUUID() + << " assetID: " << item->getAssetUUID() + << " ). Ignoring and invalidating " << cat->getName() << " . " << LL_ENDL; possible_broken_links.push_back(item); continue; } @@ -2103,7 +2073,7 @@ bool LLInventoryModel::loadSkeleton( { bad_link_count++; invalid_categories.insert(cit->second); - //LL_INFOS() << "link still broken: " << item->getName() << " in folder " << cat->getName() << LL_ENDL; + //LL_INFOS(LOG_INV) << "link still broken: " << item->getName() << " in folder " << cat->getName() << LL_ENDL; } else { @@ -2115,11 +2085,11 @@ bool LLInventoryModel::loadSkeleton( } } - LL_INFOS() << "Attempted to add " << bad_link_count - << " cached link items without baseobj present. " - << good_link_count << " link items were successfully added. " - << recovered_link_count << " links added in recovery. " - << "The corresponding categories were invalidated." << LL_ENDL; + LL_INFOS(LOG_INV) << "Attempted to add " << bad_link_count + << " cached link items without baseobj present. " + << good_link_count << " link items were successfully added. " + << recovered_link_count << " links added in recovery. " + << "The corresponding categories were invalidated." << LL_ENDL; } } @@ -2143,9 +2113,9 @@ bool LLInventoryModel::loadSkeleton( { LLViewerInventoryCategory* cat = (*invalid_cat_it).get(); cat->setVersion(NO_VERSION); - LL_DEBUGS("Inventory") << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << LL_ENDL; } - LL_INFOS("Inventory") << "Invalidated " << invalid_categories.size() << " categories due to invalid descendents cache" << LL_ENDL; + LL_INFOS(LOG_INV) << "Invalidated " << invalid_categories.size() << " categories due to invalid descendents cache" << LL_ENDL; // At this point, we need to set the known descendents for each // category which successfully cached so that we do not @@ -2177,15 +2147,15 @@ bool LLInventoryModel::loadSkeleton( if(is_cache_obsolete) { // If out of date, remove the gzipped file too. - LL_WARNS() << "Inv cache out of date, removing" << LL_ENDL; + LL_WARNS(LOG_INV) << "Inv cache out of date, removing" << LL_ENDL; LLFile::remove(gzip_filename); } categories.clear(); // will unref and delete entries } - LL_INFOS() << "Successfully loaded " << cached_category_count - << " categories and " << cached_item_count << " items from cache." - << LL_ENDL; + LL_INFOS(LOG_INV) << "Successfully loaded " << cached_category_count + << " categories and " << cached_item_count << " items from cache." + << LL_ENDL; return rv; } @@ -2195,7 +2165,7 @@ bool LLInventoryModel::loadSkeleton( // should be sufficient for our needs. void LLInventoryModel::buildParentChildMap() { - LL_INFOS() << "LLInventoryModel::buildParentChildMap()" << LL_ENDL; + LL_INFOS(LOG_INV) << "LLInventoryModel::buildParentChildMap()" << LL_ENDL; // *NOTE: I am skipping the logic around folder version // synchronization here because it seems if a folder is lost, we @@ -2264,15 +2234,15 @@ void LLInventoryModel::buildParentChildMap() // implement it, we would need a set or map of uuid pairs // which would be (folder_id, new_parent_id) to be sent up // to the server. - LL_INFOS() << "Lost category: " << cat->getUUID() << " - " - << cat->getName() << LL_ENDL; + LL_INFOS(LOG_INV) << "Lost category: " << cat->getUUID() << " - " + << cat->getName() << LL_ENDL; ++lost; lost_cats.push_back(cat); } } if(lost) { - LL_WARNS() << "Found " << lost << " lost categories." << LL_ENDL; + LL_WARNS(LOG_INV) << "Found " << lost << " lost categories." << LL_ENDL; } // Do moves in a separate pass to make sure we've properly filed @@ -2307,7 +2277,7 @@ void LLInventoryModel::buildParentChildMap() } else { - LL_WARNS() << "Lost and found Not there!!" << LL_ENDL; + LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL; } } @@ -2342,8 +2312,8 @@ void LLInventoryModel::buildParentChildMap() } else { - LL_INFOS() << "Lost item: " << item->getUUID() << " - " - << item->getName() << LL_ENDL; + LL_INFOS(LOG_INV) << "Lost item: " << item->getUUID() << " - " + << item->getName() << LL_ENDL; ++lost; // plop it into the lost & found. // @@ -2359,13 +2329,13 @@ void LLInventoryModel::buildParentChildMap() } else { - LL_WARNS() << "Lost and found Not there!!" << LL_ENDL; + LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL; } } } if(lost) { - LL_WARNS() << "Found " << lost << " lost items." << LL_ENDL; + LL_WARNS(LOG_INV) << "Found " << lost << " lost items." << LL_ENDL; LLMessageSystem* msg = gMessageSystem; BOOL start_new_message = TRUE; const LLUUID lnf = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); @@ -2443,10 +2413,85 @@ void LLInventoryModel::buildParentChildMap() if (!gInventory.validate()) { - LL_WARNS() << "model failed validity check!" << LL_ENDL; + LL_WARNS(LOG_INV) << "model failed validity check!" << LL_ENDL; + } +} + +// Would normally do this at construction but that's too early +// in the process for gInventory. Have the first requestPost() +// call set things up. +void LLInventoryModel::initHttpRequest() +{ + if (! mHttpRequestFG) + { + // Haven't initialized, get to it + LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); + + mHttpRequestFG = new LLCore::HttpRequest; + mHttpRequestBG = new LLCore::HttpRequest; + mHttpOptions = new LLCore::HttpOptions; + mHttpOptions->setTransferTimeout(300); + mHttpOptions->setUseRetryAfter(true); + // mHttpOptions->setTrace(2); // Do tracing of requests + mHttpHeaders = new LLCore::HttpHeaders; + mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML); + mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML); + mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_INVENTORY); } } +void LLInventoryModel::handleResponses(bool foreground) +{ + if (foreground) + { + mHttpRequestFG->update(0); + } + else + { + mHttpRequestBG->update(50000L); + } +} + +LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground, + const std::string & url, + const LLSD & body, + LLCore::HttpHandler * handler, + const char * const message) +{ + if (! mHttpRequestFG) + { + // We do the initialization late and lazily as this class is + // statically-constructed and not all the bits are ready at + // that time. + initHttpRequest(); + } + + LLCore::HttpRequest * request(foreground ? mHttpRequestFG : mHttpRequestBG); + LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); + LLCore::BufferArray * ba = new LLCore::BufferArray; + LLCore::BufferArrayStream bas(ba); + LLSDSerialize::toXML(body, bas); + + handle = request->requestPost(mHttpPolicyClass, + (foreground ? mHttpPriorityFG : mHttpPriorityBG), + url, + ba, + mHttpOptions, + mHttpHeaders, + handler); + ba->release(); + if (LLCORE_HTTP_HANDLE_INVALID == handle) + { + LLCore::HttpStatus status(request->getStatus()); + LL_WARNS(LOG_INV) << "HTTP POST request failed for " << message + << ", Status: " << status.toTerseString() + << " Reason: '" << status.toString() << "'" + << LL_ENDL; + delete handler; + } + return handle; +} + void LLInventoryModel::createCommonSystemCategories() { gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH,true); @@ -2495,14 +2540,14 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, { if(filename.empty()) { - LL_ERRS() << "Filename is Null!" << LL_ENDL; + LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL; return false; } - LL_INFOS() << "LLInventoryModel::loadFromFile(" << filename << ")" << LL_ENDL; + LL_INFOS(LOG_INV) << "LLInventoryModel::loadFromFile(" << filename << ")" << LL_ENDL; LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ if(!file) { - LL_INFOS() << "unable to load inventory from: " << filename << LL_ENDL; + LL_INFOS(LOG_INV) << "unable to load inventory from: " << filename << LL_ENDL; return false; } // *NOTE: This buffer size is hard coded into scanf() below. @@ -2541,7 +2586,7 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, } else { - LL_WARNS() << "loadInventoryFromFile(). Ignoring invalid inventory category: " << inv_cat->getName() << LL_ENDL; + LL_WARNS(LOG_INV) << "loadInventoryFromFile(). Ignoring invalid inventory category: " << inv_cat->getName() << LL_ENDL; //delete inv_cat; // automatic when inv_cat is reassigned or destroyed } } @@ -2559,8 +2604,8 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, if(inv_item->getUUID().isNull()) { //delete inv_item; // automatic when inv_cat is reassigned or destroyed - LL_WARNS() << "Ignoring inventory with null item id: " - << inv_item->getName() << LL_ENDL; + LL_WARNS(LOG_INV) << "Ignoring inventory with null item id: " + << inv_item->getName() << LL_ENDL; } else @@ -2570,14 +2615,14 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, } else { - LL_WARNS() << "loadInventoryFromFile(). Ignoring invalid inventory item: " << inv_item->getName() << LL_ENDL; + LL_WARNS(LOG_INV) << "loadInventoryFromFile(). Ignoring invalid inventory item: " << inv_item->getName() << LL_ENDL; //delete inv_item; // automatic when inv_cat is reassigned or destroyed } } else { - LL_WARNS() << "Unknown token in inventory file '" << keyword << "'" - << LL_ENDL; + LL_WARNS(LOG_INV) << "Unknown token in inventory file '" << keyword << "'" + << LL_ENDL; } } fclose(file); @@ -2593,14 +2638,14 @@ bool LLInventoryModel::saveToFile(const std::string& filename, { if(filename.empty()) { - LL_ERRS() << "Filename is Null!" << LL_ENDL; + LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL; return false; } - LL_INFOS() << "LLInventoryModel::saveToFile(" << filename << ")" << LL_ENDL; + LL_INFOS(LOG_INV) << "LLInventoryModel::saveToFile(" << filename << ")" << LL_ENDL; LLFILE* file = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ if(!file) { - LL_WARNS() << "unable to save inventory to: " << filename << LL_ENDL; + LL_WARNS(LOG_INV) << "unable to save inventory to: " << filename << LL_ENDL; return false; } @@ -2705,8 +2750,8 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) { - LL_WARNS() << "Got a inventory update for the wrong agent: " << agent_id - << LL_ENDL; + LL_WARNS(LOG_INV) << "Got a inventory update for the wrong agent: " << agent_id + << LL_ENDL; return false; } item_array_t items; @@ -2718,8 +2763,8 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 { LLPointer titem = new LLViewerInventoryItem; titem->unpackMessage(msg, _PREHASH_InventoryData, i); - LL_DEBUGS() << "LLInventoryModel::messageUpdateCore() item id:" - << titem->getUUID() << LL_ENDL; + LL_DEBUGS(LOG_INV) << "LLInventoryModel::messageUpdateCore() item id: " + << titem->getUUID() << LL_ENDL; items.push_back(titem); // examine update for changes. LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID()); @@ -2770,17 +2815,17 @@ void LLInventoryModel::removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg { LLUUID item_id; S32 count = msg->getNumberOfBlocksFast(msg_label); - LL_DEBUGS() << "Message has " << count << " item blocks" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Message has " << count << " item blocks" << LL_ENDL; uuid_vec_t item_ids; update_map_t update; for(S32 i = 0; i < count; ++i) { msg->getUUIDFast(msg_label, _PREHASH_ItemID, item_id, i); - LL_DEBUGS() << "Checking for item-to-be-removed " << item_id << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Checking for item-to-be-removed " << item_id << LL_ENDL; LLViewerInventoryItem* itemp = gInventory.getItem(item_id); if(itemp) { - LL_DEBUGS() << "Item will be removed " << item_id << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Item will be removed " << item_id << LL_ENDL; // we only bother with the delete and account if we found // the item - this is usually a back-up for permissions, // so frequently the item will already be gone. @@ -2791,7 +2836,7 @@ void LLInventoryModel::removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg gInventory.accountForUpdate(update); for(uuid_vec_t::iterator it = item_ids.begin(); it != item_ids.end(); ++it) { - LL_DEBUGS() << "Calling deleteObject " << *it << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Calling deleteObject " << *it << LL_ENDL; gInventory.deleteObject(*it); } } @@ -2799,13 +2844,13 @@ void LLInventoryModel::removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg // static void LLInventoryModel::processRemoveInventoryItem(LLMessageSystem* msg, void**) { - LL_DEBUGS() << "LLInventoryModel::processRemoveInventoryItem()" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "LLInventoryModel::processRemoveInventoryItem()" << LL_ENDL; LLUUID agent_id, item_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) { - LL_WARNS() << "Got a RemoveInventoryItem for the wrong agent." - << LL_ENDL; + LL_WARNS(LOG_INV) << "Got a RemoveInventoryItem for the wrong agent." + << LL_ENDL; return; } LLInventoryModel::removeInventoryItem(agent_id, msg, _PREHASH_InventoryData); @@ -2816,14 +2861,14 @@ void LLInventoryModel::processRemoveInventoryItem(LLMessageSystem* msg, void**) void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg, void**) { - LL_DEBUGS() << "LLInventoryModel::processUpdateInventoryFolder()" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "LLInventoryModel::processUpdateInventoryFolder()" << LL_ENDL; LLUUID agent_id, folder_id, parent_id; //char name[DB_INV_ITEM_NAME_BUF_SIZE]; msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) { - LL_WARNS() << "Got an UpdateInventoryFolder for the wrong agent." - << LL_ENDL; + LL_WARNS(LOG_INV) << "Got an UpdateInventoryFolder for the wrong agent." + << LL_ENDL; return; } LLPointer lastfolder; // hack @@ -3881,7 +3926,7 @@ bool LLInventoryModel::validate() const ///---------------------------------------------------------------------------- -/* +#if 0 BOOL decompress_file(const char* src_filename, const char* dst_filename) { BOOL rv = FALSE; @@ -3920,4 +3965,140 @@ BOOL decompress_file(const char* src_filename, const char* dst_filename) if(dst != NULL) fclose(dst); return rv; } -*/ +#endif + +// ==== FetchItemHttpHandler ==== + +LLInventoryModel::FetchItemHttpHandler::FetchItemHttpHandler(const LLSD & request_sd) + : LLCore::HttpHandler(), + mRequestSD(request_sd) +{} + +LLInventoryModel::FetchItemHttpHandler::~FetchItemHttpHandler() +{} + +void LLInventoryModel::FetchItemHttpHandler::onCompleted(LLCore::HttpHandle handle, + LLCore::HttpResponse * response) +{ + LLCore::HttpStatus status(response->getStatus()); + if (! status) + { + processFailure(status, response); + } + else + { + LLCore::BufferArray * body(response->getBody()); + if (! body || ! body->size()) + { + LL_WARNS(LOG_INV) << "Missing data in inventory item query." << LL_ENDL; + processFailure("HTTP response for inventory item query missing body", response); + goto only_exit; + } + + LLCore::BufferArrayStream bas(body); + LLSD body_llsd; + S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas)); + if (LLSDParser::PARSE_FAILURE == parse_status) + { + // INFOS-level logging will occur on the parsed failure + processFailure("HTTP response for inventory item query has malformed LLSD", response); + goto only_exit; + } + + // Okay, process data if possible + processData(body_llsd, response); + } + +only_exit: + // Must delete on completion. + delete this; +} + +void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore::HttpResponse * response) +{ + if (! content.isMap()) + { + processFailure("LLSD response for inventory item not a map", response); + return; + } + + start_new_inventory_observer(); + +#if 0 + LLUUID agent_id; + agent_id = content["agent_id"].asUUID(); + if (agent_id != gAgent.getID()) + { + LL_WARNS(LOG_INV) << "Got a inventory update for the wrong agent: " << agent_id + << LL_ENDL; + return; + } +#endif + + LLInventoryModel::item_array_t items; + LLInventoryModel::update_map_t update; + LLUUID folder_id; + LLSD content_items(content["items"]); + const S32 count(content_items.size()); + + // Does this loop ever execute more than once? + for (S32 i(0); i < count; ++i) + { + LLPointer titem = new LLViewerInventoryItem; + titem->unpackMessage(content_items[i]); + + LL_DEBUGS(LOG_INV) << "ItemHttpHandler::httpSuccess item id: " + << titem->getUUID() << LL_ENDL; + items.push_back(titem); + + // examine update for changes. + LLViewerInventoryItem * itemp(gInventory.getItem(titem->getUUID())); + + if (itemp) + { + if (titem->getParentUUID() == itemp->getParentUUID()) + { + update[titem->getParentUUID()]; + } + else + { + ++update[titem->getParentUUID()]; + --update[itemp->getParentUUID()]; + } + } + else + { + ++update[titem->getParentUUID()]; + } + + if (folder_id.isNull()) + { + folder_id = titem->getParentUUID(); + } + } + + // as above, this loop never seems to loop more than once per call + U32 changes(0U); + for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it) + { + changes |= gInventory.updateItem(*it); + } + // *HUH: Have computed changes, nothing uses it. + + gInventory.notifyObservers(); + gViewerWindow->getWindow()->decBusyCount(); +} + + +void LLInventoryModel::FetchItemHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::HttpResponse * response) +{ + LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + gInventory.notifyObservers(); +} + +void LLInventoryModel::FetchItemHttpHandler::processFailure(const char * const reason, LLCore::HttpResponse * response) +{ + LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + gInventory.notifyObservers(); +} + diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 2e957809be..ac336e347c 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -27,6 +27,11 @@ #ifndef LL_LLINVENTORYMODEL_H #define LL_LLINVENTORYMODEL_H +#include +#include +#include +#include + #include "llassettype.h" #include "llfoldertype.h" #include "llframetimer.h" @@ -36,10 +41,11 @@ #include "llviewerinventory.h" #include "llstring.h" #include "llmd5.h" -#include -#include -#include -#include +#include "httpcommon.h" +#include "httprequest.h" +#include "httpoptions.h" +#include "httpheaders.h" +#include "httphandler.h" class LLInventoryObserver; class LLInventoryObject; @@ -60,9 +66,8 @@ class LLInventoryCollectFunctor; class LLInventoryModel { LOG_CLASS(LLInventoryModel); -public: - friend class LLInventoryModelFetchDescendentsResponder; +public: enum EHasChildren { CHILDREN_NO, @@ -74,14 +79,31 @@ public: typedef std::vector > item_array_t; typedef std::set changed_items_t; - class fetchInventoryResponder : public LLCurl::Responder + // HTTP handler for individual item requests (inventory or library). + // Background item requests are derived from this in the background + // inventory system. All folder requests are also located there + // but have their own handler derived from HttpHandler. + class FetchItemHttpHandler : public LLCore::HttpHandler { - LOG_CLASS(fetchInventoryResponder); public: - fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; + LOG_CLASS(FetchItemHttpHandler); + + FetchItemHttpHandler(const LLSD & request_sd); + virtual ~FetchItemHttpHandler(); + protected: - virtual void httpSuccess(); - virtual void httpFailure(); + FetchItemHttpHandler(const FetchItemHttpHandler &); // Not defined + void operator=(const FetchItemHttpHandler &); // Not defined + + public: + virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); + + private: + void processData(LLSD & body, LLCore::HttpResponse * response); + void processFailure(LLCore::HttpStatus status, LLCore::HttpResponse * response); + void processFailure(const char * const reason, LLCore::HttpResponse * response); + + private: LLSD mRequestSD; }; @@ -109,6 +131,9 @@ public: private: bool mIsAgentInvUsable; // used to handle an invalid inventory state + // One-time initialization of HTTP system. + void initHttpRequest(); + //-------------------------------------------------------------------- // Root Folders //-------------------------------------------------------------------- @@ -518,6 +543,41 @@ private: *******************************************************************************/ +/******************************************************************************** + ** ** + ** HTTP Transport + **/ +public: + // Invoke handler completion method (onCompleted) for all + // requests that are ready. + void handleResponses(bool foreground); + + // Request an inventory HTTP operation to either the + // foreground or background processor. These are actually + // the same service queue but the background requests are + // seviced more slowly effectively de-prioritizing new + // requests. + LLCore::HttpHandle requestPost(bool foreground, + const std::string & url, + const LLSD & body, + LLCore::HttpHandler * handler, + const char * const message); + +private: + // Usual plumbing for LLCore:: HTTP operations. + LLCore::HttpRequest * mHttpRequestFG; + LLCore::HttpRequest * mHttpRequestBG; + LLCore::HttpOptions * mHttpOptions; + LLCore::HttpHeaders * mHttpHeaders; + LLCore::HttpRequest::policy_t mHttpPolicyClass; + LLCore::HttpRequest::priority_t mHttpPriorityFG; + LLCore::HttpRequest::priority_t mHttpPriorityBG; + +/** HTTP Transport + ** ** + *******************************************************************************/ + + /******************************************************************************** ** ** ** MISCELLANEOUS diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 2de37b0790..443c54df42 100755 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,31 +37,113 @@ #include "llviewermessage.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llhttpconstants.h" +#include "bufferarray.h" +#include "bufferstream.h" +#include "llsdserialize.h" + +namespace +{ + +// Http request handler class for single inventory item requests. +// +// We'll use a handler-per-request pattern here rather than +// a shared handler. Mainly convenient as this was converted +// from a Responder class model. +// +class BGItemHttpHandler : public LLInventoryModel::FetchItemHttpHandler +{ + LOG_CLASS(BGItemHttpHandler); + +public: + BGItemHttpHandler(const LLSD & request_sd) + : LLInventoryModel::FetchItemHttpHandler(request_sd) + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(1); + } + + virtual ~BGItemHttpHandler() + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); + } + +protected: + BGItemHttpHandler(const BGItemHttpHandler &); // Not defined + void operator=(const BGItemHttpHandler &); // Not defined +}; + + +// Http request handler class for folders. +class BGFolderHttpHandler : public LLCore::HttpHandler +{ + LOG_CLASS(BGFolderHttpHandler); + +public: + BGFolderHttpHandler(const LLSD & request_sd, const uuid_vec_t & recursive_cats) + : LLCore::HttpHandler(), + mRequestSD(request_sd), + mRecursiveCatUUIDs(recursive_cats) + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(1); + } + + virtual ~BGFolderHttpHandler() + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); + } + +protected: + BGFolderHttpHandler(const BGFolderHttpHandler &); // Not defined + void operator=(const BGFolderHttpHandler &); // Not defined + +public: + virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); + + bool getIsRecursive(const LLUUID & cat_id) const; + +private: + void processData(LLSD & body, LLCore::HttpResponse * response); + void processFailure(LLCore::HttpStatus status, LLCore::HttpResponse * response); + void processFailure(const char * const reason, LLCore::HttpResponse * response); + +private: + LLSD mRequestSD; + const uuid_vec_t mRecursiveCatUUIDs; // hack for storing away which cat fetches are recursive +}; + -const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; const S32 MAX_FETCH_RETRIES = 10; -LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() : +const char * const LOG_INV("Inventory"); + +std::string dumpResponse() +{ + return std::string("ADD SOMETHING MEANINGFUL HERE"); +} + + +} // end of namespace anonymous + + +LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch(): mBackgroundFetchActive(FALSE), mFolderFetchActive(false), + mFetchCount(0), mAllFoldersFetched(FALSE), mRecursiveInventoryFetchStarted(FALSE), mRecursiveLibraryFetchStarted(FALSE), mNumFetchRetries(0), mMinTimeBetweenFetches(0.3f), mMaxTimeBetweenFetches(10.f), - mTimelyFetchPending(FALSE), - mFetchCount(0) -{ -} + mTimelyFetchPending(FALSE) +{} LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch() -{ -} +{} bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const { - return mFetchQueue.empty() && mFetchCount<=0; + return mFetchQueue.empty() && mFetchCount <= 0; } bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const @@ -91,7 +173,7 @@ bool LLInventoryModelBackgroundFetch::inventoryFetchCompleted() const bool LLInventoryModelBackgroundFetch::inventoryFetchInProgress() const { - return inventoryFetchStarted() && !inventoryFetchCompleted(); + return inventoryFetchStarted() && ! inventoryFetchCompleted(); } bool LLInventoryModelBackgroundFetch::isEverythingFetched() const @@ -104,24 +186,36 @@ BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const return mFolderFetchActive; } +void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category) +{ + mFetchQueue.push_front(FetchQueueInfo(id, recursive, is_category)); +} + +void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category) +{ + mFetchQueue.push_back(FetchQueueInfo(id, recursive, is_category)); +} + void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { - LLViewerInventoryCategory* cat = gInventory.getCategory(id); - if (cat || (id.isNull() && !isEverythingFetched())) - { // it's a folder, do a bulk fetch - LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL; + LLViewerInventoryCategory * cat(gInventory.getCategory(id)); + + if (cat || (id.isNull() && ! isEverythingFetched())) + { + // it's a folder, do a bulk fetch + LL_DEBUGS(LOG_INV) << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL; mBackgroundFetchActive = TRUE; mFolderFetchActive = true; if (id.isNull()) { - if (!mRecursiveInventoryFetchStarted) + if (! mRecursiveInventoryFetchStarted) { mRecursiveInventoryFetchStarted |= recursive; mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } - if (!mRecursiveLibraryFetchStarted) + if (! mRecursiveLibraryFetchStarted) { mRecursiveLibraryFetchStarted |= recursive; mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); @@ -146,9 +240,9 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) } } } - else if (LLViewerInventoryItem* itemp = gInventory.getItem(id)) + else if (LLViewerInventoryItem * itemp = gInventory.getItem(id)) { - if (!itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)) + if (! itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)) { mBackgroundFetchActive = TRUE; @@ -172,7 +266,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() mRecursiveLibraryFetchStarted) { mAllFoldersFetched = TRUE; - //LL_INFOS() << "All folders fetched, validating" << LL_ENDL; + //LL_INFOS(LOG_INV) << "All folders fetched, validating" << LL_ENDL; //gInventory.validate(); } mFolderFetchActive = false; @@ -203,7 +297,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() // No more categories to fetch, stop fetch process. if (mFetchQueue.empty()) { - LL_INFOS() << "Inventory fetch completed" << LL_ENDL; + LL_INFOS(LOG_INV) << "Inventory fetch completed" << LL_ENDL; setAllFoldersFetched(); mBackgroundFetchActive = false; @@ -219,7 +313,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() // Double timeouts on failure. mMinTimeBetweenFetches = llmin(mMinTimeBetweenFetches * 2.f, 10.f); mMaxTimeBetweenFetches = llmin(mMaxTimeBetweenFetches * 2.f, 120.f); - LL_DEBUGS() << "Inventory fetch times grown to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Inventory fetch times grown to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << LL_ENDL; // fetch is no longer considered "timely" although we will wait for full time-out. mTimelyFetchPending = FALSE; } @@ -231,7 +325,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() break; } - if(gDisconnected) + if (gDisconnected) { // Just bail if we are disconnected. break; @@ -292,7 +386,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() // Shrink timeouts based on success. mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f); mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f); - LL_DEBUGS() << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << LL_ENDL; } mTimelyFetchPending = FALSE; @@ -355,257 +449,53 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() } } -void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching) +void LLInventoryModelBackgroundFetch::incrFetchCount(S32 fetching) { mFetchCount += fetching; if (mFetchCount < 0) { + LL_WARNS_ONCE(LOG_INV) << "Inventory fetch count fell below zero (0)." << LL_ENDL; mFetchCount = 0; } } -class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder -{ - LOG_CLASS(LLInventoryModelFetchItemResponder); -public: - LLInventoryModelFetchItemResponder(const LLSD& request_sd) : - LLInventoryModel::fetchInventoryResponder(request_sd) - { - LLInventoryModelBackgroundFetch::instance().incrFetchCount(1); - } -private: - /* virtual */ void httpCompleted() - { - LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); - LLInventoryModel::fetchInventoryResponder::httpCompleted(); - } -}; - -class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder -{ - LOG_CLASS(LLInventoryModelFetchDescendentsResponder); -public: - LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) : - mRequestSD(request_sd), - mRecursiveCatUUIDs(recursive_cats) - { - LLInventoryModelBackgroundFetch::instance().incrFetchCount(1); - } - //LLInventoryModelFetchDescendentsResponder() {}; -private: - /* virtual */ void httpCompleted() - { - LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); - LLHTTPClient::Responder::httpCompleted(); - } - /* virtual */ void httpSuccess(); - /* virtual */ void httpFailure(); -protected: - BOOL getIsRecursive(const LLUUID& cat_id) const; -private: - LLSD mRequestSD; - uuid_vec_t mRecursiveCatUUIDs; // hack for storing away which cat fetches are recursive -}; - -// If we get back a normal response, handle it here. -void LLInventoryModelFetchDescendentsResponder::httpSuccess() +// Bundle up a bunch of requests to send all at once. +void LLInventoryModelBackgroundFetch::bulkFetch() { - const LLSD& content = getContent(); - if (!content.isMap()) + //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. + //If there are items in mFetchQueue, we want to check the time since the last bulkFetch was + //sent. If it exceeds our retry time, go ahead and fire off another batch. + LLViewerRegion * region(gAgent.getRegion()); + if (! region || gDisconnected) { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); return; } - LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - if (content.has("folders")) - { - - for(LLSD::array_const_iterator folder_it = content["folders"].beginArray(); - folder_it != content["folders"].endArray(); - ++folder_it) - { - LLSD folder_sd = *folder_it; - - - //LLUUID agent_id = folder_sd["agent_id"]; - - //if(agent_id != gAgent.getID()) //This should never happen. - //{ - // LL_WARNS() << "Got a UpdateInventoryItem for the wrong agent." - // << LL_ENDL; - // break; - //} - - LLUUID parent_id = folder_sd["folder_id"]; - LLUUID owner_id = folder_sd["owner_id"]; - S32 version = (S32)folder_sd["version"].asInteger(); - S32 descendents = (S32)folder_sd["descendents"].asInteger(); - LLPointer tcategory = new LLViewerInventoryCategory(owner_id); - if (parent_id.isNull()) - { - LLPointer titem = new LLViewerInventoryItem; - for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray(); - item_it != folder_sd["items"].endArray(); - ++item_it) - { - const LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - if (lost_uuid.notNull()) - { - LLSD item = *item_it; - titem->unpackMessage(item); - - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - titem->setParent(lost_uuid); - titem->updateParentOnServer(FALSE); - gInventory.updateItem(titem); - gInventory.notifyObservers(); - - } - } - } - - LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id); - if (!pcat) - { - continue; - } - - for(LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray(); - category_it != folder_sd["categories"].endArray(); - ++category_it) - { - LLSD category = *category_it; - tcategory->fromLLSD(category); - - const BOOL recursive = getIsRecursive(tcategory->getUUID()); - - if (recursive) - { - fetcher->mFetchQueue.push_back(LLInventoryModelBackgroundFetch::FetchQueueInfo(tcategory->getUUID(), recursive)); - } - else if ( !gInventory.isCategoryComplete(tcategory->getUUID()) ) - { - gInventory.updateCategory(tcategory); - } - - } - LLPointer titem = new LLViewerInventoryItem; - for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray(); - item_it != folder_sd["items"].endArray(); - ++item_it) - { - LLSD item = *item_it; - titem->unpackMessage(item); - - gInventory.updateItem(titem); - } - - // Set version and descendentcount according to message. - LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id); - if(cat) - { - cat->setVersion(version); - cat->setDescendentCount(descendents); - cat->determineFolderType(); - } - - } - } - - if (content.has("bad_folders")) - { - for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray(); - folder_it != content["bad_folders"].endArray(); - ++folder_it) - { - // *TODO: Stop copying data - LLSD folder_sd = *folder_it; - - // These folders failed on the dataserver. We probably don't want to retry them. - LL_WARNS() << "Folder " << folder_sd["folder_id"].asString() - << "Error: " << folder_sd["error"].asString() << LL_ENDL; - } - } + static const S32 max_concurrent_fetches(12); // Outstanding requests, not connections + static const F32 new_min_time(0.5f); // *HACK: Clean this up when old code goes away entirely. + static const U32 max_batch_size(10); - if (fetcher->isBulkFetchProcessingComplete()) + if (mMinTimeBetweenFetches < new_min_time) { - LL_INFOS() << "Inventory fetch completed" << LL_ENDL; - fetcher->setAllFoldersFetched(); + mMinTimeBetweenFetches = new_min_time; // *HACK: See above. } - - gInventory.notifyObservers(); -} - -// If we get back an error (not found, etc...), handle it here. -void LLInventoryModelFetchDescendentsResponder::httpFailure() -{ - LL_WARNS() << dumpResponse() << LL_ENDL; - LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - - LL_INFOS() << dumpResponse() << LL_ENDL; - - fetcher->incrFetchCount(-1); - if (getStatus()==HTTP_INTERNAL_ERROR) // timed out or curl failure - { - for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); - folder_it != mRequestSD["folders"].endArray(); - ++folder_it) - { - LLSD folder_sd = *folder_it; - LLUUID folder_id = folder_sd["folder_id"]; - const BOOL recursive = getIsRecursive(folder_id); - fetcher->mFetchQueue.push_front(LLInventoryModelBackgroundFetch::FetchQueueInfo(folder_id, recursive)); - } - } - else + if (mFetchCount) { - if (fetcher->isBulkFetchProcessingComplete()) - { - fetcher->setAllFoldersFetched(); - } - } - gInventory.notifyObservers(); -} - -BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat_id) const -{ - return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end()); -} -// Bundle up a bunch of requests to send all at once. -// static -void LLInventoryModelBackgroundFetch::bulkFetch() -{ - //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. - //If there are items in mFetchQueue, we want to check the time since the last bulkFetch was - //sent. If it exceeds our retry time, go ahead and fire off another batch. - LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; - - S16 max_concurrent_fetches=8; - F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely. - if (mMinTimeBetweenFetches < new_min_time) - { - mMinTimeBetweenFetches=new_min_time; //HACK! See above. + // Process completed HTTP requests + gInventory.handleResponses(false); } - if (gDisconnected || - (mFetchCount > max_concurrent_fetches) || + if ((mFetchCount > max_concurrent_fetches) || (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) { - return; // just bail if we are disconnected + return; } - U32 item_count=0; - U32 folder_count=0; - U32 max_batch_size=5; + U32 item_count(0); + U32 folder_count(0); - U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1; + const U32 sort_order(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1); uuid_vec_t recursive_cats; @@ -614,27 +504,27 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLSD item_request_body; LLSD item_request_body_lib; - while (!mFetchQueue.empty() + while (! mFetchQueue.empty() && (item_count + folder_count) < max_batch_size) { - const FetchQueueInfo& fetch_info = mFetchQueue.front(); + const FetchQueueInfo & fetch_info(mFetchQueue.front()); if (fetch_info.mIsCategory) { - const LLUUID &cat_id = fetch_info.mUUID; + const LLUUID & cat_id(fetch_info.mUUID); if (cat_id.isNull()) //DEV-17797 { LLSD folder_sd; folder_sd["folder_id"] = LLUUID::null.asString(); folder_sd["owner_id"] = gAgent.getID(); - folder_sd["sort_order"] = (LLSD::Integer)sort_order; - folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE; - folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; + folder_sd["sort_order"] = LLSD::Integer(sort_order); + folder_sd["fetch_folders"] = LLSD::Boolean(FALSE); + folder_sd["fetch_items"] = LLSD::Boolean(TRUE); folder_request_body["folders"].append(folder_sd); folder_count++; } else { - const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); if (cat) { @@ -643,21 +533,26 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLSD folder_sd; folder_sd["folder_id"] = cat->getUUID(); folder_sd["owner_id"] = cat->getOwnerID(); - folder_sd["sort_order"] = (LLSD::Integer)sort_order; - folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted; - folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; + folder_sd["sort_order"] = LLSD::Integer(sort_order); + folder_sd["fetch_folders"] = LLSD::Boolean(TRUE); //(LLSD::Boolean)sFullFetchStarted; + folder_sd["fetch_items"] = LLSD::Boolean(TRUE); if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) + { folder_request_body_lib["folders"].append(folder_sd); + } else + { folder_request_body["folders"].append(folder_sd); + } folder_count++; } + // May already have this folder, but append child folders to list. if (fetch_info.mRecursive) { - LLInventoryModel::cat_array_t* categories; - LLInventoryModel::item_array_t* items; + LLInventoryModel::cat_array_t * categories(NULL); + LLInventoryModel::item_array_t * items(NULL); gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); @@ -669,11 +564,14 @@ void LLInventoryModelBackgroundFetch::bulkFetch() } } if (fetch_info.mRecursive) + { recursive_cats.push_back(cat_id); + } } else { - LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID); + LLViewerInventoryItem * itemp(gInventory.getItem(fetch_info.mUUID)); + if (itemp) { LLSD item_sd; @@ -694,72 +592,80 @@ void LLInventoryModelBackgroundFetch::bulkFetch() mFetchQueue.pop_front(); } - + + // Issue HTTP POST requests to fetch folders and items + if (item_count + folder_count > 0) { if (folder_count) { - std::string url = region->getCapability("FetchInventoryDescendents2"); - if ( !url.empty() ) + if (folder_request_body["folders"].size()) { - if (folder_request_body["folders"].size()) + const std::string url(region->getCapability("FetchInventoryDescendents2")); + + if (! url.empty()) { - LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats); - LLHTTPClient::post(url, folder_request_body, fetcher, 300.0); + BGFolderHttpHandler * handler(new BGFolderHttpHandler(folder_request_body, recursive_cats)); + gInventory.requestPost(false, url, folder_request_body, handler, "Inventory Folder"); } - if (folder_request_body_lib["folders"].size()) - { - std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); + } + + if (folder_request_body_lib["folders"].size()) + { + const std::string url(region->getCapability("FetchLibDescendents2")); - LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats); - LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0); + if (! url.empty()) + { + BGFolderHttpHandler * handler(new BGFolderHttpHandler(folder_request_body_lib, recursive_cats)); + gInventory.requestPost(false, url, folder_request_body_lib, handler, "Library Folder"); } } - } + } // if (folder_count) + if (item_count) { - std::string url; - if (item_request_body.size()) { - url = region->getCapability("FetchInventory2"); - if (!url.empty()) + const std::string url(region->getCapability("FetchInventory2")); + + if (! url.empty()) { LLSD body; body["items"] = item_request_body; - - LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); + BGItemHttpHandler * handler(new BGItemHttpHandler(body)); + gInventory.requestPost(false, url, body, handler, "Inventory Item"); } } if (item_request_body_lib.size()) { + const std::string url(region->getCapability("FetchLib2")); - url = region->getCapability("FetchLib2"); - if (!url.empty()) + if (! url.empty()) { LLSD body; body["items"] = item_request_body_lib; - - LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); + BGItemHttpHandler * handler(new BGItemHttpHandler(body)); + gInventory.requestPost(false, url, body, handler, "Library Item"); } } - } + } // if (item_count) + mFetchTimer.reset(); } - else if (isBulkFetchProcessingComplete()) { setAllFoldersFetched(); } } -bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const +bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LLUUID & cat_id) const { for (fetch_queue_t::const_iterator it = mFetchQueue.begin(); - it != mFetchQueue.end(); ++it) + it != mFetchQueue.end(); + ++it) { - const LLUUID& fetch_id = (*it).mUUID; + const LLUUID & fetch_id = (*it).mUUID; if (gInventory.isObjectDescendentOf(fetch_id, cat_id)) return false; } @@ -767,3 +673,257 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL } +// Anonymous Namespace Definitions + +namespace +{ + +// ==== BGFolderHttpHandler ==== + +void BGFolderHttpHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) +{ + LLCore::HttpStatus status(response->getStatus()); + if (! status) + { + processFailure(status, response); + } + else + { + LLCore::BufferArray * body(response->getBody()); + if (! body || ! body->size()) + { + LL_WARNS(LOG_INV) << "Missing data in inventory folder query." << LL_ENDL; + processFailure("HTTP response missing expected body", response); + goto only_exit; + } + + LLCore::BufferArrayStream bas(body); + LLSD body_llsd; + S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas)); + if (LLSDParser::PARSE_FAILURE == parse_status) + { + // INFOS-level logging will occur on the parsed failure + processFailure("HTTP response contained malformed LLSD", response); + goto only_exit; + } + + // Okay, process data if possible + processData(body_llsd, response); + } + +only_exit: + // Must delete on completion. + delete this; +} + + +void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * response) +{ + if (! content.isMap()) + { + processFailure("LLSD response not a map", response); + return; + } + + LLInventoryModelBackgroundFetch * fetcher(LLInventoryModelBackgroundFetch::getInstance()); + if (content.has("folders")) + { + LLSD folders(content["folders"]); + + for (LLSD::array_const_iterator folder_it = folders.beginArray(); + folder_it != folders.endArray(); + ++folder_it) + { + LLSD folder_sd(*folder_it); + + //LLUUID agent_id = folder_sd["agent_id"]; + + //if(agent_id != gAgent.getID()) //This should never happen. + //{ + // LL_WARNS(LOG_INV) << "Got a UpdateInventoryItem for the wrong agent." + // << LL_ENDL; + // break; + //} + + LLUUID parent_id(folder_sd["folder_id"].asUUID()); + LLUUID owner_id(folder_sd["owner_id"].asUUID()); + S32 version(folder_sd["version"].asInteger()); + S32 descendents(folder_sd["descendents"].asInteger()); + LLPointer tcategory = new LLViewerInventoryCategory(owner_id); + + if (parent_id.isNull()) + { + LLSD items(folder_sd["items"]); + LLPointer titem = new LLViewerInventoryItem; + + for (LLSD::array_const_iterator item_it = items.beginArray(); + item_it != items.endArray(); + ++item_it) + { + const LLUUID lost_uuid(gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); + + if (lost_uuid.notNull()) + { + LLSD item(*item_it); + + titem->unpackMessage(item); + + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + titem->setParent(lost_uuid); + titem->updateParentOnServer(FALSE); + gInventory.updateItem(titem); + gInventory.notifyObservers(); + } + } + } + + LLViewerInventoryCategory * pcat(gInventory.getCategory(parent_id)); + if (! pcat) + { + continue; + } + + LLSD categories(folder_sd["categories"]); + for (LLSD::array_const_iterator category_it = categories.beginArray(); + category_it != categories.endArray(); + ++category_it) + { + LLSD category(*category_it); + tcategory->fromLLSD(category); + + const bool recursive(getIsRecursive(tcategory->getUUID())); + if (recursive) + { + fetcher->addRequestAtBack(tcategory->getUUID(), recursive, true); + } + else if (! gInventory.isCategoryComplete(tcategory->getUUID())) + { + gInventory.updateCategory(tcategory); + } + } + + LLSD items(folder_sd["items"]); + LLPointer titem = new LLViewerInventoryItem; + for (LLSD::array_const_iterator item_it = items.beginArray(); + item_it != items.endArray(); + ++item_it) + { + LLSD item(*item_it); + titem->unpackMessage(item); + + gInventory.updateItem(titem); + } + + // Set version and descendentcount according to message. + LLViewerInventoryCategory * cat(gInventory.getCategory(parent_id)); + if (cat) + { + cat->setVersion(version); + cat->setDescendentCount(descendents); + cat->determineFolderType(); + } + } + } + + if (content.has("bad_folders")) + { + LLSD bad_folders(content["bad_folders"]); + for (LLSD::array_const_iterator folder_it = bad_folders.beginArray(); + folder_it != bad_folders.endArray(); + ++folder_it) + { + // *TODO: Stop copying data + LLSD folder_sd(*folder_it); + + // These folders failed on the dataserver. We probably don't want to retry them. + LL_WARNS(LOG_INV) << "Folder " << folder_sd["folder_id"].asString() + << "Error: " << folder_sd["error"].asString() << LL_ENDL; + } + } + + if (fetcher->isBulkFetchProcessingComplete()) + { + LL_INFOS(LOG_INV) << "Inventory fetch completed" << LL_ENDL; + fetcher->setAllFoldersFetched(); + } + + gInventory.notifyObservers(); +} + + +void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::HttpResponse * response) +{ + LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); + + LL_INFOS(LOG_INV) << dumpResponse() << LL_ENDL; + + // *FIX: Not the correct test here... + if (status == LLCore::HttpStatus(408)) // timed out or curl failure + { + for (LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); + folder_it != mRequestSD["folders"].endArray(); + ++folder_it) + { + LLSD folder_sd(*folder_it); + LLUUID folder_id(folder_sd["folder_id"]); + const BOOL recursive = getIsRecursive(folder_id); + fetcher->addRequestAtFront(folder_id, recursive, true); + } + } + else + { + if (fetcher->isBulkFetchProcessingComplete()) + { + fetcher->setAllFoldersFetched(); + } + } + gInventory.notifyObservers(); +} + + +void BGFolderHttpHandler::processFailure(const char * const reason, LLCore::HttpResponse * response) +{ + LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); + + LL_INFOS(LOG_INV) << dumpResponse() << LL_ENDL; + + if (true /* status == LLCore::HttpStatus(408)*/) // timed out or curl failure + { + for (LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); + folder_it != mRequestSD["folders"].endArray(); + ++folder_it) + { + LLSD folder_sd(*folder_it); + LLUUID folder_id(folder_sd["folder_id"]); + const BOOL recursive = getIsRecursive(folder_id); + fetcher->addRequestAtFront(folder_id, recursive, true); + } + } + else + { + if (fetcher->isBulkFetchProcessingComplete()) + { + fetcher->setAllFoldersFetched(); + } + } + gInventory.notifyObservers(); +} + + +bool BGFolderHttpHandler::getIsRecursive(const LLUUID & cat_id) const +{ + return std::find(mRecursiveCatUUIDs.begin(), mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end(); +} + + +// ==== BGItemHttpHandler ==== + +// Nothing to implement here. All ctor/dtor changes. + +} // end namespace anonymous diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 9dfedddd6d..2139f85519 100755 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -29,6 +29,11 @@ #include "llsingleton.h" #include "lluuid.h" +#include "httpcommon.h" +#include "httprequest.h" +#include "httpoptions.h" +#include "httpheaders.h" +#include "httphandler.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryModelBackgroundFetch @@ -38,8 +43,6 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInventoryModelBackgroundFetch : public LLSingleton { - friend class LLInventoryModelFetchDescendentsResponder; - public: LLInventoryModelBackgroundFetch(); ~LLInventoryModelBackgroundFetch(); @@ -60,16 +63,22 @@ public: bool inventoryFetchInProgress() const; void findLostItems(); - void incrFetchCount(S16 fetching); -protected: + void incrFetchCount(S32 fetching); + bool isBulkFetchProcessingComplete() const; + void setAllFoldersFetched(); + + void addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category); + void addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category); + +protected: void bulkFetch(); void backgroundFetch(); static void backgroundFetchCB(void*); // background fetch idle function - void setAllFoldersFetched(); bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const; + private: BOOL mRecursiveInventoryFetchStarted; BOOL mRecursiveLibraryFetchStarted; @@ -77,7 +86,7 @@ private: BOOL mBackgroundFetchActive; bool mFolderFetchActive; - S16 mFetchCount; + S32 mFetchCount; BOOL mTimelyFetchPending; S32 mNumFetchRetries; @@ -87,9 +96,12 @@ private: struct FetchQueueInfo { - FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) : - mUUID(id), mRecursive(recursive), mIsCategory(is_category) + FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) + : mUUID(id), + mIsCategory(is_category), + mRecursive(recursive) {} + LLUUID mUUID; bool mIsCategory; BOOL mRecursive; diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 2dd8dce42f..d81401b59b 100755 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -237,7 +237,8 @@ void fetch_items_from_llsd(const LLSD& items_llsd) if (!url.empty()) { body[i]["agent_id"] = gAgent.getID(); - LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i])); + LLInventoryModel::FetchItemHttpHandler * handler(new LLInventoryModel::FetchItemHttpHandler(body[i])); + gInventory.requestPost(true, url, body[i], handler, (i ? "Library Item" : "Inventory Item")); continue; } diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index f61db77169..942360b650 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2013&license=viewerlgpl$ * Second Life Viewer Source Code -* Copyright (C) 2013, Linden Research, Inc. +* Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -151,7 +151,7 @@ F32 LLSnapshotLivePreview::getImageAspect() void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) { - lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl; + LL_DEBUGS() << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << LL_ENDL; // Update snapshot if requested. if (new_snapshot) @@ -594,7 +594,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) } else { - llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; + LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; } } // Scale to a power of 2 so it can be mapped to a texture @@ -642,7 +642,7 @@ LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage() } else { - llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; + LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; } } // Scale to a power of 2 so it can be mapped to a texture @@ -695,7 +695,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // time to produce a snapshot if(!previewp->getSnapshotUpToDate()) { - lldebugs << "producing snapshot" << llendl; + LL_DEBUGS() << "producing snapshot" << LL_ENDL; if (!previewp->mPreviewImage) { previewp->mPreviewImage = new LLImageRaw; @@ -775,7 +775,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode previewp->mSnapshotDelayTimer.stop(); previewp->mSnapshotActive = FALSE; - lldebugs << "done creating snapshot" << llendl; + LL_DEBUGS() << "done creating snapshot" << LL_ENDL; } if (!previewp->getThumbnailUpToDate()) @@ -910,13 +910,13 @@ LLPointer LLSnapshotLivePreview::getFormattedImage() } else { - llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; + LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; } } // Create the new formatted image of the appropriate format. LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat(); - lldebugs << "Encoding new image of format " << format << llendl; + LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL; switch (format) { diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 4e4c3471be..d364fce45a 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -75,6 +75,10 @@ void no_op_inventory_func(const LLUUID&) {} void no_op_llsd_func(const LLSD&) {} void no_op() {} +static const char * const LOG_INV("Inventory"); +static const char * const LOG_LOCAL("InventoryLocalize"); +static const char * const LOG_NOTECARD("copy_inventory_from_notecard"); + ///---------------------------------------------------------------------------- /// Helper class to store special inventory item names and their localized values. ///---------------------------------------------------------------------------- @@ -189,7 +193,7 @@ public: */ bool localizeInventoryObjectName(std::string& object_name) { - LL_DEBUGS("InventoryLocalize") << "Searching for localization: " << object_name << LL_ENDL; + LL_DEBUGS(LOG_LOCAL) << "Searching for localization: " << object_name << LL_ENDL; std::map::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name); @@ -197,7 +201,7 @@ public: if(found) { object_name = dictionary_iter->second; - LL_DEBUGS("InventoryLocalize") << "Found, new name is: " << object_name << LL_ENDL; + LL_DEBUGS(LOG_LOCAL) << "Found, new name is: " << object_name << LL_ENDL; } return found; } @@ -307,8 +311,8 @@ LLViewerInventoryItem::LLViewerInventoryItem(const LLViewerInventoryItem* other) copyViewerItem(other); if (!mIsComplete) { - LL_WARNS() << "LLViewerInventoryItem copy constructor for incomplete item" - << mUUID << LL_ENDL; + LL_WARNS(LOG_INV) << "LLViewerInventoryItem copy constructor for incomplete item" + << mUUID << LL_ENDL; } } @@ -355,16 +359,16 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const { // *FIX: deal with this better. // If we're crashing here then the UI is incorrectly enabled. - LL_ERRS() << "LLViewerInventoryItem::updateServer() - for incomplete item" - << LL_ENDL; + LL_ERRS(LOG_INV) << "LLViewerInventoryItem::updateServer() - for incomplete item" + << LL_ENDL; return; } if(gAgent.getID() != mPermissions.getOwner()) { // *FIX: deal with this better. - LL_WARNS() << "LLViewerInventoryItem::updateServer() - for unowned item " - << ll_pretty_print_sd(this->asLLSD()) - << LL_ENDL; + LL_WARNS(LOG_INV) << "LLViewerInventoryItem::updateServer() - for unowned item " + << ll_pretty_print_sd(this->asLLSD()) + << LL_ENDL; return; } LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); @@ -392,18 +396,18 @@ void LLViewerInventoryItem::fetchFromServer(void) const // we have to check region. It can be null after region was destroyed. See EXT-245 if (region) { - if(gAgent.getID() != mPermissions.getOwner()) - { + if (gAgent.getID() != mPermissions.getOwner()) + { url = region->getCapability("FetchLib2"); - } + } else - { + { url = region->getCapability("FetchInventory2"); - } + } } else { - LL_WARNS() << "Agent Region is absent" << LL_ENDL; + LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL; } if (!url.empty()) @@ -413,7 +417,8 @@ void LLViewerInventoryItem::fetchFromServer(void) const body["items"][0]["owner_id"] = mPermissions.getOwner(); body["items"][0]["item_id"] = mUUID; - LLHTTPClient::post(url, body, new LLInventoryModel::fetchInventoryResponder(body)); + LLInventoryModel::FetchItemHttpHandler * handler(new LLInventoryModel::FetchItemHttpHandler(body)); + gInventory.requestPost(true, url, body, handler, "Inventory Item"); } else { @@ -649,7 +654,7 @@ bool LLViewerInventoryCategory::fetch() if((VERSION_UNKNOWN == getVersion()) && mDescendentsRequested.hasExpired()) //Expired check prevents multiple downloads. { - LL_DEBUGS("InventoryFetch") << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL; const F32 FETCH_TIMER_EXPIRY = 10.0f; mDescendentsRequested.reset(); mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); @@ -674,7 +679,7 @@ bool LLViewerInventoryCategory::fetch() } else { - LL_WARNS() << "agent region is null" << LL_ENDL; + LL_WARNS(LOG_INV) << "agent region is null" << LL_ENDL; } if (!url.empty()) //Capability found. Build up LLSD and use it. { @@ -682,7 +687,8 @@ bool LLViewerInventoryCategory::fetch() } else { //Deprecated, but if we don't have a capability, use the old system. - LL_INFOS() << "FetchInventoryDescendents2 capability not found. Using deprecated UDP message." << LL_ENDL; + LL_INFOS(LOG_INV) << "FetchInventoryDescendents2 capability not found. Using deprecated UDP message." << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; msg->newMessage("FetchInventoryDescendents"); msg->nextBlock("AgentData"); @@ -777,8 +783,8 @@ bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp) } else { - LL_WARNS() << "unknown keyword '" << keyword - << "' in inventory import category " << mUUID << LL_ENDL; + LL_WARNS(LOG_INV) << "unknown keyword '" << keyword + << "' in inventory import category " << mUUID << LL_ENDL; } } return true; @@ -906,7 +912,7 @@ LLInventoryCallbackManager::LLInventoryCallbackManager() : { if( sInstance != NULL ) { - LL_WARNS() << "LLInventoryCallbackManager::LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; + LL_WARNS(LOG_INV) << "LLInventoryCallbackManager::LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; return; } sInstance = this; @@ -916,7 +922,7 @@ LLInventoryCallbackManager::~LLInventoryCallbackManager() { if( sInstance != this ) { - LL_WARNS() << "LLInventoryCallbackManager::~LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; + LL_WARNS(LOG_INV) << "LLInventoryCallbackManager::~LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; return; } sInstance = NULL; @@ -1144,7 +1150,7 @@ void link_inventory_object(const LLUUID& category, { if (!baseobj) { - LL_WARNS() << "Attempt to link to non-existent object" << LL_ENDL; + LL_WARNS(LOG_INV) << "Attempt to link to non-existent object" << LL_ENDL; return; } @@ -1178,7 +1184,7 @@ void link_inventory_array(const LLUUID& category, const LLInventoryObject* baseobj = *it; if (!baseobj) { - LL_WARNS() << "attempt to link to unknown object" << LL_ENDL; + LL_WARNS(LOG_INV) << "attempt to link to unknown object" << LL_ENDL; continue; } @@ -1187,7 +1193,7 @@ void link_inventory_array(const LLUUID& category, // Fail if item can be found but is of a type that can't be linked. // Arguably should fail if the item can't be found too, but that could // be a larger behavioral change. - LL_WARNS() << "attempt to link an unlinkable object, type = " << baseobj->getActualType() << LL_ENDL; + LL_WARNS(LOG_INV) << "attempt to link an unlinkable object, type = " << baseobj->getActualType() << LL_ENDL; continue; } @@ -1223,7 +1229,7 @@ void link_inventory_array(const LLUUID& category, } else { - LL_WARNS() << "could not convert object into an item or category: " << baseobj->getUUID() << LL_ENDL; + LL_WARNS(LOG_INV) << "could not convert object into an item or category: " << baseobj->getUUID() << LL_ENDL; continue; } } @@ -1237,10 +1243,10 @@ void link_inventory_array(const LLUUID& category, links.append(link); #ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS("Inventory") << "Linking Object [ name:" << baseobj->getName() - << " UUID:" << baseobj->getUUID() - << " ] into Category [ name:" << cat_name - << " UUID:" << category << " ] " << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Linking Object [ name:" << baseobj->getName() + << " UUID:" << baseobj->getUUID() + << " ] into Category [ name:" << cat_name + << " UUID:" << category << " ] " << LL_ENDL; #endif } @@ -1331,7 +1337,7 @@ void update_inventory_item( if (!ais_ran) { LLPointer obj = gInventory.getItem(item_id); - LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL; + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL; if(obj) { LLMessageSystem* msg = gMessageSystem; @@ -1373,7 +1379,7 @@ void update_inventory_item( if (!ais_ran) { LLPointer obj = gInventory.getItem(item_id); - LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; if(obj) { LLPointer new_item(new LLViewerInventoryItem); @@ -1408,7 +1414,7 @@ void update_inventory_category( LLPointer cb) { LLPointer obj = gInventory.getCategory(cat_id); - LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; + LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; if(obj) { if (LLFolderType::lookupIsProtectedType(obj->getPreferredType())) @@ -1471,7 +1477,7 @@ void remove_inventory_item( } else { - LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << LL_ENDL; } } @@ -1482,7 +1488,7 @@ void remove_inventory_item( if(obj) { const LLUUID item_id(obj->getUUID()); - LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL; + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL; if (AISCommand::isAPIAvailable()) { LLPointer cmd_ptr = new RemoveItemCommand(item_id, cb); @@ -1511,7 +1517,7 @@ void remove_inventory_item( else { // *TODO: Clean up callback? - LL_WARNS() << "remove_inventory_item called for invalid or nonexistent item." << LL_ENDL; + LL_WARNS(LOG_INV) << "remove_inventory_item called for invalid or nonexistent item." << LL_ENDL; } } @@ -1529,7 +1535,7 @@ public: LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(mID); if(children != LLInventoryModel::CHILDREN_NO) { - LL_WARNS() << "remove descendents failed, cannot remove category " << LL_ENDL; + LL_WARNS(LOG_INV) << "remove descendents failed, cannot remove category " << LL_ENDL; } else { @@ -1545,7 +1551,7 @@ void remove_inventory_category( const LLUUID& cat_id, LLPointer cb) { - LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] " << LL_ENDL; + LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] " << LL_ENDL; LLPointer obj = gInventory.getCategory(cat_id); if(obj) { @@ -1566,7 +1572,7 @@ void remove_inventory_category( LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id); if(children != LLInventoryModel::CHILDREN_NO) { - LL_DEBUGS("Inventory") << "Will purge descendents first before deleting category " << cat_id << LL_ENDL; + LL_DEBUGS(LOG_INV) << "Will purge descendents first before deleting category " << cat_id << LL_ENDL; LLPointer wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb); purge_descendents_of(cat_id, wrap_cb); return; @@ -1592,7 +1598,7 @@ void remove_inventory_category( } else { - LL_WARNS() << "remove_inventory_category called for invalid or nonexistent item " << cat_id << LL_ENDL; + LL_WARNS(LOG_INV) << "remove_inventory_category called for invalid or nonexistent item " << cat_id << LL_ENDL; } } @@ -1620,7 +1626,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id); if(children == LLInventoryModel::CHILDREN_NO) { - LL_DEBUGS("Inventory") << "No descendents to purge for " << id << LL_ENDL; + LL_DEBUGS(LOG_INV) << "No descendents to purge for " << id << LL_ENDL; return; } LLPointer cat = gInventory.getCategory(id); @@ -1629,8 +1635,8 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) { // Something on the clipboard is in "cut mode" and needs to be preserved - LL_DEBUGS("Inventory") << "purge_descendents_of clipboard case " << cat->getName() - << " iterate and purge non hidden items" << LL_ENDL; + LL_DEBUGS(LOG_INV) << "purge_descendents_of clipboard case " << cat->getName() + << " iterate and purge non hidden items" << LL_ENDL; LLInventoryModel::cat_array_t* categories; LLInventoryModel::item_array_t* items; // Get the list of direct descendants in tha categoy passed as argument @@ -1665,7 +1671,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) else // no cap { // Fast purge - LL_DEBUGS("Inventory") << "purge_descendents_of fast case " << cat->getName() << LL_ENDL; + LL_DEBUGS(LOG_INV) << "purge_descendents_of fast case " << cat->getName() << LL_ENDL; // send it upstream LLMessageSystem* msg = gMessageSystem; @@ -1708,9 +1714,9 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, { if (NULL == src) { - LL_WARNS("copy_inventory_from_notecard") << "Null pointer to item was passed for object_id " - << object_id << " and notecard_inv_id " - << notecard_inv_id << LL_ENDL; + LL_WARNS(LOG_NOTECARD) << "Null pointer to item was passed for object_id " + << object_id << " and notecard_inv_id " + << notecard_inv_id << LL_ENDL; return; } @@ -1730,9 +1736,9 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, if (! viewer_region) { - LL_WARNS("copy_inventory_from_notecard") << "Can't find region from object_id " - << object_id << " or gAgent" - << LL_ENDL; + LL_WARNS(LOG_NOTECARD) << "Can't find region from object_id " + << object_id << " or gAgent" + << LL_ENDL; return; } @@ -1740,9 +1746,9 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, std::string url = viewer_region->getCapability("CopyInventoryFromNotecard"); if (url.empty()) { - LL_WARNS("copy_inventory_from_notecard") << "There is no 'CopyInventoryFromNotecard' capability" - << " for region: " << viewer_region->getName() - << LL_ENDL; + LL_WARNS(LOG_NOTECARD) << "There is no 'CopyInventoryFromNotecard' capability" + << " for region: " << viewer_region->getName() + << LL_ENDL; return; } @@ -1816,15 +1822,15 @@ void slam_inventory_folder(const LLUUID& folder_id, { if (AISCommand::isAPIAvailable()) { - LL_DEBUGS("Avatar") << "using AISv3 to slam folder, id " << folder_id - << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; + LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id + << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; LLPointer cmd_ptr = new SlamFolderCommand(folder_id, contents, cb); cmd_ptr->run_command(); } else // no cap { - LL_DEBUGS("Avatar") << "using item-by-item calls to slam folder, id " << folder_id - << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; + LL_DEBUGS(LOG_INV) << "using item-by-item calls to slam folder, id " << folder_id + << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; for (LLSD::array_const_iterator it = contents.beginArray(); it != contents.endArray(); ++it) @@ -1926,7 +1932,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, } else { - LL_WARNS() << "Can't create unrecognized type " << type_name << LL_ENDL; + LL_WARNS(LOG_INV) << "Can't create unrecognized type " << type_name << LL_ENDL; } } panel->getRootFolder()->setNeedsAutoRename(TRUE); @@ -2161,7 +2167,7 @@ LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID); if (linked_item && linked_item->getIsLinkType()) { - LL_WARNS() << "Warning: Accessing link to link" << LL_ENDL; + LL_WARNS(LOG_INV) << "Warning: Accessing link to link" << LL_ENDL; return NULL; } return linked_item; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8c9429c05d..10c77da5f3 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -8258,7 +8258,7 @@ class LLWorldEnableEnvSettings : public view_listener_t } else { - llwarns << "Unknown item" << llendl; + LL_WARNS() << "Unknown time-of-day item: " << tod << LL_ENDL; } } return result; -- cgit v1.2.3 From b64ef2ecd4af5265483527f2ef030554133ab137 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 22 Aug 2014 19:00:11 -0400 Subject: Fix ambiguous constructor due to LLSD access which broke *ix builds. --- indra/newview/llinventorymodelbackgroundfetch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 443c54df42..7b944edf45 100755 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -870,7 +870,7 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http ++folder_it) { LLSD folder_sd(*folder_it); - LLUUID folder_id(folder_sd["folder_id"]); + LLUUID folder_id(folder_sd["folder_id"].asUUID()); const BOOL recursive = getIsRecursive(folder_id); fetcher->addRequestAtFront(folder_id, recursive, true); } @@ -900,7 +900,7 @@ void BGFolderHttpHandler::processFailure(const char * const reason, LLCore::Http ++folder_it) { LLSD folder_sd(*folder_it); - LLUUID folder_id(folder_sd["folder_id"]); + LLUUID folder_id(folder_sd["folder_id"].asUUID()); const BOOL recursive = getIsRecursive(folder_id); fetcher->addRequestAtFront(folder_id, recursive, true); } -- cgit v1.2.3 From ed29df03092092247d2743fe1c0ec9e501c4da28 Mon Sep 17 00:00:00 2001 From: NiranV Date: Tue, 26 Aug 2014 21:04:54 +0200 Subject: STORM-2073: Fixed: Double post when clicking "Post" while not logged in. Makes the previous double post for "Connect" obselete. --- indra/newview/llfloaterfacebook.cpp | 34 ++++++++++++++++++---------------- indra/newview/llfloaterfacebook.h | 3 +-- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 33422fb5fd..6888e076aa 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -157,7 +157,6 @@ void LLFacebookStatusPanel::onSend() LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); - pressedConnect = FALSE; // Connect to Facebook if necessary and then post if (LLFacebookConnect::instance().isConnected()) { @@ -170,6 +169,23 @@ void LLFacebookStatusPanel::onSend() } bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data) +{ + switch (data.get("enum").asInteger()) + { + case LLFacebookConnect::FB_CONNECTED: + sendStatus(); + break; + + case LLFacebookConnect::FB_POSTED: + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); + clearAndClose(); + break; + } + + return false; +} + +bool LLFacebookStatusPanel::onFacebookConnectAccountStateChange(const LLSD& data) { if(LLFacebookConnect::instance().isConnected()) { @@ -184,19 +200,6 @@ bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data) showDisconnectedLayout(); } - switch (data.get("enum").asInteger()) - { - case LLFacebookConnect::FB_CONNECTED: - if(!pressedConnect) - sendStatus(); - break; - - case LLFacebookConnect::FB_POSTED: - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); - clearAndClose(); - break; - } - return false; } @@ -214,7 +217,7 @@ void LLFacebookStatusPanel::onVisibilityChange(BOOL visible) if(visible) { LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1)); LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); @@ -295,7 +298,6 @@ void LLFacebookStatusPanel::onConnect() { LLFacebookConnect::instance().checkConnectionToFacebook(true); - pressedConnect = TRUE; //Clear only the facebook browser cookies so that the facebook login screen appears LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index 6fe7a6541b..a4ca666b20 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -46,6 +46,7 @@ public: void draw(); void onSend(); bool onFacebookConnectStateChange(const LLSD& data); + bool onFacebookConnectAccountStateChange(const LLSD& data); void sendStatus(); void clearAndClose(); @@ -62,8 +63,6 @@ private: void showDisconnectedLayout(); void showConnectedLayout(); - bool pressedConnect; - LLTextBox * mAccountCaptionLabel; LLTextBox * mAccountNameLabel; LLUICtrl * mPanelButtons; -- cgit v1.2.3 From bbf9de9c6717f38a77a39d42d8493d275d558db9 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Tue, 26 Aug 2014 18:33:14 -0400 Subject: Bring better error handling to inventory item and folder fetching. First, introduced some LLSD-based interfaces to the llcorehttp code using utils classes (in llcorehttputil). I've kept LLSD out of the llcorehttp library up to now and will continue to do that. Functions provide a requestPost based on LLSD body and conversion utils for HttpResponse-to-LLSD and HttpResponse-to-string conversions. Inventory fetch operations now do more thorough error checking including 200-with-error status checking. Still do retry forever on folders though I don't like that. --- indra/llmessage/CMakeLists.txt | 4 + indra/llmessage/llcorehttputil.cpp | 137 ++++++++++++++++++++++ indra/llmessage/llcorehttputil.h | 115 ++++++++++++++++++ indra/newview/llinventorymodel.cpp | 76 +++++++----- indra/newview/llinventorymodelbackgroundfetch.cpp | 115 +++++++++++++----- 5 files changed, 386 insertions(+), 61 deletions(-) create mode 100644 indra/llmessage/llcorehttputil.cpp create mode 100644 indra/llmessage/llcorehttputil.h diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 8bd134dc84..40eddcb0ab 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -6,6 +6,7 @@ include(00-Common) include(GoogleMock) include(LLAddBuildTest) include(LLCommon) +include(LLCoreHttp) include(LLMath) include(LLMessage) include(LLVFS) @@ -18,6 +19,7 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR}) include_directories( ${LLCOMMON_INCLUDE_DIRS} + ${LLCOREHTTP_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} @@ -36,6 +38,7 @@ set(llmessage_SOURCE_FILES llchainio.cpp llcircuit.cpp llclassifiedflags.cpp + llcorehttputil.cpp llcurl.cpp lldatapacker.cpp lldispatcher.cpp @@ -124,6 +127,7 @@ set(llmessage_HEADER_FILES llcipher.h llcircuit.h llclassifiedflags.h + llcorehttputil.h llcurl.h lldatapacker.h lldbstrings.h diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp new file mode 100644 index 0000000000..8d09aac971 --- /dev/null +++ b/indra/llmessage/llcorehttputil.cpp @@ -0,0 +1,137 @@ +/** + * @file llcorehttputil.cpp + * @date 2014-08-25 + * @brief Implementation of adapter and utility classes expanding the llcorehttp interfaces. + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include + +#include "llcorehttputil.h" +#include "llsdserialize.h" + + +using namespace LLCore; + + +namespace LLCoreHttpUtil +{ + + +bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd) +{ + // Convert response to LLSD + BufferArray * body(response->getBody()); + if (! body || ! body->size()) + { + return false; + } + + LLCore::BufferArrayStream bas(body); + LLSD body_llsd; + S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas, log)); + if (LLSDParser::PARSE_FAILURE == parse_status){ + return false; + } + out_llsd = body_llsd; + return true; +} + + +HttpHandle requestPostWithLLSD(HttpRequest * request, + HttpRequest::policy_t policy_id, + HttpRequest::priority_t priority, + const std::string & url, + const LLSD & body, + HttpOptions * options, + HttpHeaders * headers, + HttpHandler * handler) +{ + HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); + + BufferArray * ba = new BufferArray(); + BufferArrayStream bas(ba); + LLSDSerialize::toXML(body, bas); + + handle = request->requestPost(policy_id, + priority, + url, + ba, + options, + headers, + handler); + ba->release(); + return handle; +} + + +std::string responseToString(LLCore::HttpResponse * response) +{ + static const std::string empty("[Empty]"); + + if (! response) + { + return empty; + } + + BufferArray * body(response->getBody()); + if (! body || ! body->size()) + { + return empty; + } + + // Attempt to parse as LLSD regardless of content-type + LLSD body_llsd; + if (responseToLLSD(response, false, body_llsd)) + { + std::ostringstream tmp; + + LLSDSerialize::toPrettyNotation(body_llsd, tmp); + std::size_t temp_len(tmp.tellp()); + + if (temp_len) + { + return tmp.str().substr(0, std::min(temp_len, std::size_t(1024))); + } + } + else + { + // *TODO: More elaborate forms based on Content-Type as needed. + char content[1024]; + + size_t len(body->read(0, content, sizeof(content))); + if (len) + { + return std::string(content, 0, len); + } + } + + // Default + return empty; +} + + +} // end namespace LLCoreHttpUtil + diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h new file mode 100644 index 0000000000..d40172bc7a --- /dev/null +++ b/indra/llmessage/llcorehttputil.h @@ -0,0 +1,115 @@ +/** + * @file llcorehttputil.h + * @date 2014-08-25 + * @brief Adapter and utility classes expanding the llcorehttp interfaces. + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLCOREHTTPUTIL_H +#define LL_LLCOREHTTPUTIL_H + +#include + +#include "httpcommon.h" +#include "httprequest.h" +#include "httpresponse.h" +#include "httpheaders.h" +#include "httpoptions.h" +#include "httphandler.h" +#include "bufferarray.h" +#include "bufferstream.h" +#include "llsd.h" + +/// +/// The base llcorehttp library implements many HTTP idioms +/// used in the viewer but not all. That library intentionally +/// avoids the use of LLSD and its conventions which aren't +/// universally applicable. This module, using namespace +/// LLCoreHttpUtil, provides the additional helper functions +/// that support idiomatic LLSD transport via the newer +/// llcorehttp library. +/// +namespace LLCoreHttpUtil +{ + +/// Attempt to convert a response object's contents to LLSD. +/// It is expected that the response body will be of non-zero +/// length on input but basic checks will be performed and +/// and error (false status) returned if there is no data. +/// If there is data but it cannot be successfully parsed, +/// an error is also returned. If successfully parsed, +/// the output LLSD object, out_llsd, is written with the +/// result and true is returned. +/// +/// @arg response Response object as returned in +/// in an HttpHandler onCompleted() callback. +/// @arg log If true, LLSD parser will emit errors +/// as LL_INFOS-level messages as it parses. +/// Otherwise, it *should* be a quiet parse. +/// @arg out_llsd Output LLSD object written only upon +/// successful parse of the response object. +/// +/// @return Returns true (and writes to out_llsd) if +/// parse was successful. False otherwise. +/// +bool responseToLLSD(LLCore::HttpResponse * response, + bool log, + LLSD & out_llsd); + +/// Create a std::string representation of a response object +/// suitable for logging. Mainly intended for logging of +/// failures and debug information. This won't be fast, +/// just adequate. +std::string responseToString(LLCore::HttpResponse * response); + + +/// Issue a standard HttpRequest::requestPost() call but using +/// and LLSD object as the request body. Conventions are the +/// same as with that method. Caller is expected to provide +/// an HttpHeaders object with a correct 'Content-Type:' header. +/// One will not be provided by this call. You might look after +/// the 'Accept:' header as well. +/// +/// @return If request is successfully issued, the +/// HttpHandle representing the request. +/// On error, LLCORE_HTTP_HANDLE_INVALID +/// is returned and caller can fetch detailed +/// status with the getStatus() method on the +/// request object. In case of error, no +/// request is queued and caller may need to +/// perform additional cleanup such as freeing +/// a now-useless HttpHandler object. +/// +LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request, + LLCore::HttpRequest::policy_t policy_id, + LLCore::HttpRequest::priority_t priority, + const std::string & url, + const LLSD & body, + LLCore::HttpOptions * options, + LLCore::HttpHeaders * headers, + LLCore::HttpHandler * handler); + +} // end namespace LLCoreHttpUtil + + +#endif // LL_LLCOREHTTPUTIL_H diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 2dd31f047f..5273fb6d96 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -55,7 +55,7 @@ #include "llsdutil.h" #include "bufferarray.h" #include "bufferstream.h" -#include "llsdserialize.h" +#include "llcorehttputil.h" //#define DIFF_INVENTORY_FILES #ifdef DIFF_INVENTORY_FILES @@ -75,12 +75,6 @@ BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; static const char CACHE_FORMAT_STRING[] = "%s.inv"; static const char * const LOG_INV("Inventory"); -static std::string dumpResponse() -{ - return std::string("ADD SOMETHING MEANINGFUL HERE"); -} - - struct InventoryIDPtrLess { bool operator()(const LLViewerInventoryCategory* i1, const LLViewerInventoryCategory* i2) const @@ -2468,18 +2462,15 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground, LLCore::HttpRequest * request(foreground ? mHttpRequestFG : mHttpRequestBG); LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); - LLCore::BufferArray * ba = new LLCore::BufferArray; - LLCore::BufferArrayStream bas(ba); - LLSDSerialize::toXML(body, bas); - handle = request->requestPost(mHttpPolicyClass, - (foreground ? mHttpPriorityFG : mHttpPriorityBG), - url, - ba, - mHttpOptions, - mHttpHeaders, - handler); - ba->release(); + handle = LLCoreHttpUtil::requestPostWithLLSD(request, + mHttpPolicyClass, + (foreground ? mHttpPriorityFG : mHttpPriorityBG), + url, + body, + mHttpOptions, + mHttpHeaders, + handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) { LLCore::HttpStatus status(request->getStatus()); @@ -3981,6 +3972,7 @@ void LLInventoryModel::FetchItemHttpHandler::onCompleted(LLCore::HttpHandle hand LLCore::HttpResponse * response) { LLCore::HttpStatus status(response->getStatus()); + // status = LLCore::HttpStatus(404); // Dev tool to force error handling if (! status) { processFailure(status, response); @@ -3988,23 +3980,41 @@ void LLInventoryModel::FetchItemHttpHandler::onCompleted(LLCore::HttpHandle hand else { LLCore::BufferArray * body(response->getBody()); + // body = NULL; // Dev tool to force error handling if (! body || ! body->size()) { LL_WARNS(LOG_INV) << "Missing data in inventory item query." << LL_ENDL; processFailure("HTTP response for inventory item query missing body", response); goto only_exit; } - - LLCore::BufferArrayStream bas(body); + + // body->write(0, "Garbage Response", 16); // Dev tool to force error handling LLSD body_llsd; - S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas)); - if (LLSDParser::PARSE_FAILURE == parse_status) + if (! LLCoreHttpUtil::responseToLLSD(response, true, body_llsd)) { // INFOS-level logging will occur on the parsed failure processFailure("HTTP response for inventory item query has malformed LLSD", response); goto only_exit; } + // Expect top-level structure to be a map + // body_llsd = LLSD::emptyArray(); // Dev tool to force error handling + if (! body_llsd.isMap()) + { + processFailure("LLSD response for inventory item not a map", response); + goto only_exit; + } + + // Check for 200-with-error failures + // body_llsd["error"] = LLSD::emptyMap(); // Dev tool to force error handling + // body_llsd["error"]["identifier"] = "Development"; + // body_llsd["error"]["message"] = "You left development code in the viewer"; + if (body_llsd.has("error")) + { + processFailure("Inventory application error (200-with-error)", response); + goto only_exit; + } + // Okay, process data if possible processData(body_llsd, response); } @@ -4016,12 +4026,6 @@ only_exit: void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore::HttpResponse * response) { - if (! content.isMap()) - { - processFailure("LLSD response for inventory item not a map", response); - return; - } - start_new_inventory_observer(); #if 0 @@ -4083,7 +4087,7 @@ void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore: { changes |= gInventory.updateItem(*it); } - // *HUH: Have computed changes, nothing uses it. + // *HUH: Have computed 'changes', nothing uses it. gInventory.notifyObservers(); gViewerWindow->getWindow()->decBusyCount(); @@ -4092,13 +4096,23 @@ void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore: void LLInventoryModel::FetchItemHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::HttpResponse * response) { - LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + const std::string & ct(response->getContentType()); + LL_WARNS(LOG_INV) << "Inventory item fetch failure\n" + << "[Status: " << status.toTerseString() << "]\n" + << "[Reason: " << status.toString() << "]\n" + << "[Content-type: " << ct << "]\n" + << "[Content (abridged): " + << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL; gInventory.notifyObservers(); } void LLInventoryModel::FetchItemHttpHandler::processFailure(const char * const reason, LLCore::HttpResponse * response) { - LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + LL_WARNS(LOG_INV) << "Inventory item fetch failure\n" + << "[Status: internal error]\n" + << "[Reason: " << reason << "]\n" + << "[Content (abridged): " + << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL; gInventory.notifyObservers(); } diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 7b944edf45..0c04a9c039 100755 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -40,17 +40,24 @@ #include "llhttpconstants.h" #include "bufferarray.h" #include "bufferstream.h" -#include "llsdserialize.h" +#include "llcorehttputil.h" namespace { +// // Http request handler class for single inventory item requests. // // We'll use a handler-per-request pattern here rather than // a shared handler. Mainly convenient as this was converted // from a Responder class model. // +// Derives from and is identical to the normal FetchItemHttpHandler +// except that: 1) it uses the background request object which is +// updated more slowly than the foreground and 2) keeps a count of +// active requests on the LLInventoryModelBackgroundFetch object +// to indicate outstanding operations are in-flight. +// class BGItemHttpHandler : public LLInventoryModel::FetchItemHttpHandler { LOG_CLASS(BGItemHttpHandler); @@ -74,6 +81,10 @@ protected: // Http request handler class for folders. +// +// Handler for FetchInventoryDescendents2 and FetchLibDescendents2 +// caps requests for folders. +// class BGFolderHttpHandler : public LLCore::HttpHandler { LOG_CLASS(BGFolderHttpHandler); @@ -116,12 +127,6 @@ const S32 MAX_FETCH_RETRIES = 10; const char * const LOG_INV("Inventory"); -std::string dumpResponse() -{ - return std::string("ADD SOMETHING MEANINGFUL HERE"); -} - - } // end of namespace anonymous @@ -471,6 +476,10 @@ void LLInventoryModelBackgroundFetch::bulkFetch() return; } + // *TODO: These values could be tweaked at runtime to effect + // a fast/slow fetch throttle. Once login is complete and the scene + // is mostly loaded, we could turn up the throttle and fill missing + // inventory more quickly. static const S32 max_concurrent_fetches(12); // Outstanding requests, not connections static const F32 new_min_time(0.5f); // *HACK: Clean this up when old code goes away entirely. static const U32 max_batch_size(10); @@ -482,7 +491,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() if (mFetchCount) { - // Process completed HTTP requests + // Process completed background HTTP requests gInventory.handleResponses(false); } @@ -497,6 +506,8 @@ void LLInventoryModelBackgroundFetch::bulkFetch() const U32 sort_order(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1); + // *TODO: Think I'd like to get a shared pointer to this and share it + // among all the folder requests. uuid_vec_t recursive_cats; LLSD folder_request_body; @@ -673,7 +684,9 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL } +// =============================== // Anonymous Namespace Definitions +// =============================== namespace { @@ -683,30 +696,53 @@ namespace void BGFolderHttpHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) { LLCore::HttpStatus status(response->getStatus()); + // status = LLCore::HttpStatus(404); // Dev tool to force error handling if (! status) { processFailure(status, response); } else { + // Response body should be present. LLCore::BufferArray * body(response->getBody()); + // body = NULL; // Dev tool to force error handling if (! body || ! body->size()) { LL_WARNS(LOG_INV) << "Missing data in inventory folder query." << LL_ENDL; processFailure("HTTP response missing expected body", response); goto only_exit; } - - LLCore::BufferArrayStream bas(body); + + // Could test 'Content-Type' header but probably unreliable. + + // Convert response to LLSD + // body->write(0, "Garbage Response", 16); // Dev tool to force error handling LLSD body_llsd; - S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas)); - if (LLSDParser::PARSE_FAILURE == parse_status) + if (! LLCoreHttpUtil::responseToLLSD(response, true, body_llsd)) { // INFOS-level logging will occur on the parsed failure processFailure("HTTP response contained malformed LLSD", response); goto only_exit; } + // Expect top-level structure to be a map + // body_llsd = LLSD::emptyArray(); // Dev tool to force error handling + if (! body_llsd.isMap()) + { + processFailure("LLSD response not a map", response); + goto only_exit; + } + + // Check for 200-with-error failures + // body_llsd["error"] = LLSD::emptyMap(); // Dev tool to force error handling + // body_llsd["error"]["identifier"] = "Development"; + // body_llsd["error"]["message"] = "You left development code in the viewer"; + if (body_llsd.has("error")) + { + processFailure("Inventory application error (200-with-error)", response); + goto only_exit; + } + // Okay, process data if possible processData(body_llsd, response); } @@ -719,13 +755,12 @@ only_exit: void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * response) { - if (! content.isMap()) - { - processFailure("LLSD response not a map", response); - return; - } - LLInventoryModelBackgroundFetch * fetcher(LLInventoryModelBackgroundFetch::getInstance()); + + // API V2 and earlier should probably be testing for "error" map + // in response as an application-level error. + + // Instead, we assume success and attempt to extract information. if (content.has("folders")) { LLSD folders(content["folders"]); @@ -836,7 +871,7 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res folder_it != bad_folders.endArray(); ++folder_it) { - // *TODO: Stop copying data + // *TODO: Stop copying data [ed: this isn't copying data] LLSD folder_sd(*folder_it); // These folders failed on the dataserver. We probably don't want to retry them. @@ -857,14 +892,26 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::HttpResponse * response) { - LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + const std::string & ct(response->getContentType()); + LL_WARNS(LOG_INV) << "Inventory folder fetch failure\n" + << "[Status: " << status.toTerseString() << "]\n" + << "[Reason: " << status.toString() << "]\n" + << "[Content-type: " << ct << "]\n" + << "[Content (abridged): " + << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL; + + // Could use a 404 test here to try to detect revoked caps... + + // This was originally the request retry logic for the inventory + // request which tested on HTTP_INTERNAL_ERROR status. This + // retry logic was unbounded and lacked discrimination as to the + // cause of the retry. The new http library should be doing + // adquately on retries but I want to keep the structure of a + // retry for reference. LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - - LL_INFOS(LOG_INV) << dumpResponse() << LL_ENDL; - - // *FIX: Not the correct test here... - if (status == LLCore::HttpStatus(408)) // timed out or curl failure + if (false) { + // timed out or curl failure for (LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); folder_it != mRequestSD["folders"].endArray(); ++folder_it) @@ -888,12 +935,20 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http void BGFolderHttpHandler::processFailure(const char * const reason, LLCore::HttpResponse * response) { - LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL; + LL_WARNS(LOG_INV) << "Inventory folder fetch failure\n" + << "[Status: internal error]\n" + << "[Reason: " << reason << "]\n" + << "[Content (abridged): " + << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL; + + // Reverse of previous processFailure() method, this is invoked + // when response structure is found to be invalid. Original + // always re-issued the request (without limit). This does + // the same but be aware that this may be a source of problems. + // Philosophy is that inventory folders are so essential to + // operation that this is a reasonable action. LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - - LL_INFOS(LOG_INV) << dumpResponse() << LL_ENDL; - - if (true /* status == LLCore::HttpStatus(408)*/) // timed out or curl failure + if (true) { for (LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); folder_it != mRequestSD["folders"].endArray(); -- cgit v1.2.3 From 19ce74567954d5b234cb931f7faa5fe58037c513 Mon Sep 17 00:00:00 2001 From: MNikolenko ProductEngine Date: Tue, 9 Sep 2014 20:54:05 +0300 Subject: MAINT-4432 FIXED Packets Lost under Help -> About Second Life does not display correctly --- indra/newview/skins/default/xui/fr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 46fcbe005f..bca134eef3 100755 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -71,7 +71,7 @@ Version Qt Webkit : [QT_WEBKIT_VERSION] Version serveur vocal : [VOICE_VERSION] - Paquets perdus : [PACKETS_LOST,nombre,0]/[PACKETS_IN,nombre,0] ([PACKETS_PCT,nombre,1]%) + Paquets perdus : [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) Erreur lors de la récupération de l'URL des notes de version du serveur. -- cgit v1.2.3 From 7982ae6b911b8e0400aa593c476b8a634174a6a5 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 28 Aug 2014 19:36:47 +0300 Subject: MAINT-3967 FIXED Up arrow key does not move the cursor up in chat field. Reverted previous two fixes and modified LLTextBase::changeLine() --- indra/llui/lltextbase.cpp | 34 +++++++----------------- indra/llui/lltextbase.h | 1 - indra/llui/lltexteditor.cpp | 64 ++------------------------------------------- 3 files changed, 11 insertions(+), 88 deletions(-) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2d7062e71d..9b125a85b9 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -218,8 +218,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mParseHighlights(p.parse_highlights), mBGVisible(p.bg_visible), mScroller(NULL), - mStyleDirty(true), - mDrawRightmostCursor(false) + mStyleDirty(true) { if(p.allow_scroll) { @@ -1505,11 +1504,6 @@ void LLTextBase::reflow() // find and erase line info structs starting at start_index and going to end of document if (!mLineInfoList.empty()) { - if (mDrawRightmostCursor) - { - start_index--; - } - // find first element whose end comes after start_index line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare()); line_start_index = iter->mDocIndexStart; @@ -1698,11 +1692,6 @@ S32 LLTextBase::getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap) co } else { - if (mDrawRightmostCursor) - { - doc_index--; - } - line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), doc_index, line_end_compare()); if (include_wordwrap) { @@ -1731,11 +1720,6 @@ S32 LLTextBase::getLineOffsetFromDocIndex( S32 startpos, bool include_wordwrap) } else { - if (mDrawRightmostCursor) - { - startpos--; - } - line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), startpos, line_end_compare()); return startpos - iter->mDocIndexStart; } @@ -2456,7 +2440,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, } else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd) { - if (getLineNumFromDocIndex(line_iter->mDocIndexEnd - 1) == line_iter->mLineNum && !mDrawRightmostCursor) + if (getLineNumFromDocIndex(line_iter->mDocIndexEnd - 1) == line_iter->mLineNum) { // if segment wraps to the next line we should step one char back // to compensate for the space char between words @@ -2489,13 +2473,7 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const // clamp pos to valid values pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1); - S32 corrected_pos = pos; - if (mDrawRightmostCursor && pos > 0) - { - corrected_pos--; - } - - line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), corrected_pos, line_end_compare()); + line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare()); doc_rect.mLeft = line_iter->mRect.mLeft; doc_rect.mBottom = line_iter->mRect.mBottom; @@ -2670,6 +2648,12 @@ void LLTextBase::changeLine( S32 delta ) LLRect visible_region = getVisibleDocumentRect(); S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE); + S32 actual_line = getLineNumFromDocIndex(new_cursor_pos); + if (actual_line != new_line) + { + // line edge, correcting position by 1 to move onto proper line + new_cursor_pos += new_line - actual_line; + } setCursorPos(new_cursor_pos, true); } } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 9c3bc3ed98..738b4d5b8e 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -618,7 +618,6 @@ protected: // cursor S32 mCursorPos; // I-beam is just after the mCursorPos-th character. - bool mDrawRightmostCursor; // When cursor is on the rightmost position on the line S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be LLFrameTimer mCursorBlinkTimer; // timer that controls cursor blinking diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 9219490bf2..cf5fdef539 100755 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1124,13 +1124,6 @@ void LLTextEditor::addChar(llwchar wc) setCursorPos(new_cursor_pos); } } - - if (mCursorPos > 0) - { - LLRect current_cursor_rect = getDocRectFromDocIndex(mCursorPos); - LLRect prev_cursor_rect = getDocRectFromDocIndex(mCursorPos - 1); - mDrawRightmostCursor = current_cursor_rect.mBottom < prev_cursor_rect.mBottom; - } } void LLTextEditor::addLineBreakChar(BOOL group_together) @@ -1277,12 +1270,6 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) break; case KEY_HOME: - if(mDrawRightmostCursor && mCursorPos > 0) - { - mCursorPos--; - mDrawRightmostCursor = false; - } - startOfLine(); break; @@ -1297,23 +1284,6 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) case KEY_END: endOfLine(); - { - S32 last_line_index = mLineInfoList.size() - 1; - if (getLineNumFromDocIndex(mCursorPos, true) < last_line_index) - { - mDrawRightmostCursor = true; - setCursorPos(mCursorPos + 1); - } - else if (last_line_index > 0) // only for two and more lines - { - S32 prev_line_width = mLineInfoList[last_line_index - 1].mRect.getWidth(); - S32 last_line_width = mLineInfoList[last_line_index].mRect.getWidth(); - if (prev_line_width <= last_line_width) - { - mDrawRightmostCursor = true; - } - } - } break; case KEY_LEFT: @@ -1325,18 +1295,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) { if( 0 < mCursorPos ) { - LLRect current_cursor_rect = getDocRectFromDocIndex(mCursorPos); - LLRect next_cursor_rect = getDocRectFromDocIndex(mCursorPos - 1); - - if (current_cursor_rect.mBottom < next_cursor_rect.mBottom) - { - mDrawRightmostCursor = true; - } - else - { - mDrawRightmostCursor = false; - setCursorPos(mCursorPos - 1); - } + setCursorPos(mCursorPos - 1); } else { @@ -1354,26 +1313,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) { if( mCursorPos < getLength() ) { - LLRect current_cursor_rect = getDocRectFromDocIndex(mCursorPos); - LLRect next_cursor_rect = getDocRectFromDocIndex(mCursorPos + 1); - - if (current_cursor_rect.mBottom > next_cursor_rect.mBottom) - { - if (mDrawRightmostCursor) - { - mDrawRightmostCursor = false; - } - else - { - mDrawRightmostCursor = true; - setCursorPos(mCursorPos + 1); - } - } - else - { - mDrawRightmostCursor = false; - setCursorPos(mCursorPos + 1); - } + setCursorPos(mCursorPos + 1); } else { -- cgit v1.2.3 From 0c20beda6800149ee71a307ca4e943b5bba56908 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Thu, 4 Sep 2014 16:57:44 -0400 Subject: Pipelining work. Extend transfer timeout by the pipeline depth as transfers can appear delayed with deep pipelining and more requests in the pool. Added bad HTTP status error (typically getting a 0 back as HTTP status from libcurl) to the list of retryable errors. There's a response stream problem with libcurl and pipelining that induces this problem. Retrying helps but may not be entirely safe. Watch bug 1420 on the libcurl sourceforge bug tracker. Extend options of test/example program to include un-ranged requests. Document the excessive data transfer induced when ranged requests are disabled. This is an abnormal mode for very rare users so we'll just eat that for now. --- indra/llcorehttp/_httplibcurl.cpp | 15 +++++++---- indra/llcorehttp/_httpoprequest.cpp | 34 ++++++++++++++++++------- indra/llcorehttp/examples/http_texture_load.cpp | 21 ++++++++++++--- indra/llcorehttp/httpcommon.cpp | 13 ++++++++-- indra/newview/app_settings/settings.xml | 4 +-- indra/newview/llmeshrepository.cpp | 13 +++++++++- 6 files changed, 78 insertions(+), 22 deletions(-) diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index b46833a1f3..cfbe0fd2bb 100755 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -217,8 +217,17 @@ void HttpLibcurl::addOp(HttpOpRequest * op) } // Make the request live - curl_multi_add_handle(mMultiHandles[op->mReqPolicy], op->mCurlHandle); + CURLMcode code; + code = curl_multi_add_handle(mMultiHandles[op->mReqPolicy], op->mCurlHandle); + if (CURLM_OK != code) + { + // *TODO: Better cleanup and recovery but not much we can do here. + check_curl_multi_code(code); + return; + } op->mCurlActive = true; + mActiveOps.insert(op); + ++mActiveHandles[op->mReqPolicy]; if (op->mTracing > HTTP_TRACE_OFF) { @@ -230,10 +239,6 @@ void HttpLibcurl::addOp(HttpOpRequest * op) << ", Readies: " << policy.getReadyCount(op->mReqPolicy) << LL_ENDL; } - - // On success, make operation active - mActiveOps.insert(op); - ++mActiveHandles[op->mReqPolicy]; } diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index eb664fdced..38c1f1e78a 100755 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -378,6 +378,7 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id, // Junk may be left around from a failed request and that // needs to be cleaned out. // +// *TODO: Move this to _httplibcurl where it belongs. HttpStatus HttpOpRequest::prepareRequest(HttpService * service) { CURLcode code; @@ -411,8 +412,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // *FIXME: better error handling later HttpStatus status; - // Get global policy options - HttpPolicyGlobal & policy(service->getPolicy().getGlobalOptions()); + // Get global and class policy options + HttpPolicyGlobal & gpolicy(service->getPolicy().getGlobalOptions()); + HttpPolicyClass & cpolicy(service->getPolicy().getClassOptions(mReqPolicy)); mCurlHandle = LLCurl::createStandardCurlHandle(); if (! mCurlHandle) @@ -462,30 +464,30 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0); check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST); - if (policy.mUseLLProxy) + if (gpolicy.mUseLLProxy) { // Use the viewer-based thread-safe API which has a // fast/safe check for proxy enable. Would like to // encapsulate this someway... LLProxy::getInstance()->applyProxySettings(mCurlHandle); } - else if (policy.mHttpProxy.size()) + else if (gpolicy.mHttpProxy.size()) { // *TODO: This is fine for now but get fuller socks5/ // authentication thing going later.... - code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, policy.mHttpProxy.c_str()); + code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, gpolicy.mHttpProxy.c_str()); check_curl_easy_code(code, CURLOPT_PROXY); code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); check_curl_easy_code(code, CURLOPT_PROXYTYPE); } - if (policy.mCAPath.size()) + if (gpolicy.mCAPath.size()) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, policy.mCAPath.c_str()); + code = curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, gpolicy.mCAPath.c_str()); check_curl_easy_code(code, CURLOPT_CAPATH); } - if (policy.mCAFile.size()) + if (gpolicy.mCAFile.size()) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, policy.mCAFile.c_str()); + code = curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, gpolicy.mCAFile.c_str()); check_curl_easy_code(code, CURLOPT_CAINFO); } @@ -594,6 +596,20 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) { xfer_timeout = timeout; } + if (cpolicy.mPipelining > 1L) + { + // Pipelining affects both connection and transfer timeout values. + // Requests that are added to a pipeling immediately have completed + // their connection so the connection delay tends to be less than + // the non-pipelined value. Transfers are the opposite. Transfer + // timeout starts once the connection is established and completion + // can be delayed due to the pipelined requests ahead. So, it's + // a handwave but bump the transfer timeout up by the pipelining + // depth to give some room. + // + // *TODO: Find a better scheme than timeouts to guarantee liveness. + xfer_timeout *= cpolicy.mPipelining; + } code = curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout); check_curl_easy_code(code, CURLOPT_TIMEOUT); code = curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout); diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp index 88692c3f69..b76c874557 100755 --- a/indra/llcorehttp/examples/http_texture_load.cpp +++ b/indra/llcorehttp/examples/http_texture_load.cpp @@ -102,6 +102,7 @@ public: public: bool mVerbose; bool mRandomRange; + bool mNoRange; int mRequestLowWater; int mRequestHighWater; handle_set_t mHandles; @@ -162,10 +163,11 @@ int main(int argc, char** argv) { LLCore::HttpStatus status; bool do_random(false); + bool do_whole(false); bool do_verbose(false); int option(-1); - while (-1 != (option = getopt(argc, argv, "u:c:h?RvH:p:t:"))) + while (-1 != (option = getopt(argc, argv, "u:c:h?RwvH:p:t:"))) { switch (option) { @@ -236,6 +238,12 @@ int main(int argc, char** argv) case 'R': do_random = true; + do_whole = false; + break; + + case 'w': + do_whole = true; + do_random = false; break; case 'v': @@ -307,6 +315,7 @@ int main(int argc, char** argv) ws.mUrl = url_format; ws.loadAssetUuids(uuids); ws.mRandomRange = do_random; + ws.mNoRange = do_whole; ws.mVerbose = do_verbose; ws.mRequestHighWater = highwater; ws.mRequestLowWater = ws.mRequestHighWater / 2; @@ -381,6 +390,7 @@ void usage(std::ostream & out) " -u printf-style format string for URL generation\n" " Default: " << url_format << "\n" " -R Issue GETs with random Range: headers\n" + " -w Issue GETs without Range: headers to get whole object\n" " -c Maximum connection concurrency. Range: [1..100]\n" " Default: " << concurrency_limit << "\n" " -H HTTP request highwater (requests fed to llcorehttp).\n" @@ -400,6 +410,7 @@ WorkingSet::WorkingSet() : LLCore::HttpHandler(), mVerbose(false), mRandomRange(false), + mNoRange(false), mRemaining(200), mLimit(200), mAt(0), @@ -449,8 +460,12 @@ bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions * opt) #else snprintf(buffer, sizeof(buffer), mUrl.c_str(), mAssets[mAt].mUuid.c_str()); #endif - int offset(mRandomRange ? ((unsigned long) rand()) % 1000000UL : mAssets[mAt].mOffset); - int length(mRandomRange ? ((unsigned long) rand()) % 1000000UL : mAssets[mAt].mLength); + int offset(mNoRange + ? 0 + : (mRandomRange ? ((unsigned long) rand()) % 1000000UL : mAssets[mAt].mOffset)); + int length(mNoRange + ? 0 + : (mRandomRange ? ((unsigned long) rand()) % 1000000UL : mAssets[mAt].mLength)); LLCore::HttpHandle handle; if (offset || length) diff --git a/indra/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp index c2f15155ac..9bcf7ac5e3 100755 --- a/indra/llcorehttp/httpcommon.cpp +++ b/indra/llcorehttp/httpcommon.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012-2013, Linden Research, Inc. + * Copyright (C) 2012-2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -219,6 +219,13 @@ std::string HttpStatus::toTerseString() const // Pass true on statuses that might actually be cleared by a // retry. Library failures, calling problems, etc. aren't // going to be fixed by squirting bits all over the Net. +// +// HE_INVALID_HTTP_STATUS is special. As of 7.37.0, there are +// some scenarios where response processing in libcurl appear +// to go wrong and response data is corrupted. A side-effect +// of this is that the HTTP status is read as 0 from the library. +// See libcurl bug report 1420 (https://sourceforge.net/p/curl/bugs/1420/) +// for details. bool HttpStatus::isRetryable() const { static const HttpStatus cant_connect(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT); @@ -231,6 +238,7 @@ bool HttpStatus::isRetryable() const static const HttpStatus post_error(HttpStatus::EXT_CURL_EASY, CURLE_HTTP_POST_ERROR); static const HttpStatus partial_file(HttpStatus::EXT_CURL_EASY, CURLE_PARTIAL_FILE); static const HttpStatus inv_cont_range(HttpStatus::LLCORE, HE_INV_CONTENT_RANGE_HDR); + static const HttpStatus inv_status(HttpStatus::LLCORE, HE_INVALID_HTTP_STATUS); return ((isHttpStatus() && mType >= 499 && mType <= 599) || // Include special 499 in retryables *this == cant_connect || // Connection reset/endpoint problems @@ -242,7 +250,8 @@ bool HttpStatus::isRetryable() const *this == op_timedout || // Timer expired *this == post_error || // Transport problem *this == partial_file || // Data inconsistency in response - *this == inv_cont_range); // Short data read disagrees with content-range + *this == inv_cont_range || // Short data read disagrees with content-range + *this == inv_status); // Inv status can reflect internal state problem in libcurl } } // end namespace LLCore diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0607579a08..ab15a03229 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4459,7 +4459,7 @@ HttpPipelining Comment - If true, viewer will pipeline HTTP requests to servers. + If true, viewer will attempt to pipeline HTTP requests. Persist 1 Type @@ -4470,7 +4470,7 @@ HttpRangeRequestsDisable Comment - If true, viewer will not issued range GET requests for meshes and textures. May resolve problems with certain ISPs and networking gear. + If true, viewer will not issue GET requests with 'Range:' headers for meshes and textures. May resolve problems with certain ISPs and networking gear. Persist 1 Type diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 6477389d4c..a6707392fe 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -2644,6 +2644,17 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) } +// Handle failed or successful requests for mesh assets. +// +// Support for 200 responses was added for several reasons. One, +// a service or cache can ignore range headers and give us a +// 200 with full asset should it elect to. We also support +// a debug flag which disables range requests for those very +// few users that have some sort of problem with their networking +// services. But the 200 response handling is suboptimal: rather +// than cache the whole asset, we just extract the part that would +// have been sent in a 206 and process that. Inefficient but these +// are cases far off the norm. void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) { mProcessed = true; @@ -2685,7 +2696,7 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo if (par_status == status) { - // 216 case + // 206 case response->getRange(&offset, &length, &full_length); if (! offset && ! length) { -- cgit v1.2.3 From ef9bee5098bc1adcb9054bba6f4bc24f184e445a Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 8 Sep 2014 14:52:59 -0400 Subject: Added tag 3.7.15-release for changeset 3f11f57f2b4d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index bd574ec656..dd0dc4499a 100755 --- a/.hgtags +++ b/.hgtags @@ -487,3 +487,4 @@ a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release 3b44ea8988cb902f0dda8429e8d5e4569e304532 3.7.12-release d86a7e1bc96d27b683f951d3701d5b7042158c68 3.7.13-release a7872554f3665588f1e8347d472cec3a299254b3 3.7.14-release +3f11f57f2b4d15a9f987d12bc70ef507eefb5018 3.7.15-release -- cgit v1.2.3 From eef4acc5367a486b0c52c6ce5e1aba995fefd99c Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 8 Sep 2014 14:52:59 -0400 Subject: increment viewer version to 3.7.16 --- indra/newview/VIEWER_VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 03d7b8fb9b..36f601f10e 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.7.15 +3.7.16 -- cgit v1.2.3 From bd0a9b6b4c929f640164b623f5183d371404bb96 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Tue, 9 Sep 2014 15:30:54 -0400 Subject: LLSlurl and LLViewerNetwork unit test fixes. Got tired of the TC builds failing on these tests. Appears to be a conflict/race condition on a temporary file. Changed the name of the file. Should use a tempname()-like API but this will do for a unit test. --- indra/newview/tests/llslurl_test.cpp | 23 ++++++++++++++++------- indra/newview/tests/llviewernetwork_test.cpp | 23 +++++++++++++++-------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index 86229ad636..2bc0d5a086 100755 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -6,7 +6,7 @@ * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,6 +31,15 @@ #include "../llslurl.h" #include "../../llxml/llcontrol.h" #include "llsdserialize.h" + +namespace +{ + +// Should not collide with other test programs creating temp files. +static const char * const TEST_FILENAME("llslurl_test.xml"); + +} + //---------------------------------------------------------------------------- // Mock objects for the dependencies of the code we're testing @@ -143,11 +152,11 @@ namespace tut template<> template<> void slurlTestObject::test<1>() { - llofstream gridfile("grid_test.xml"); + llofstream gridfile(TEST_FILENAME); gridfile << gSampleGridFile; gridfile.close(); - LLGridManager::getInstance()->initialize("grid_test.xml"); + LLGridManager::getInstance()->initialize(TEST_FILENAME); LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); @@ -260,11 +269,11 @@ namespace tut template<> template<> void slurlTestObject::test<2>() { - llofstream gridfile("grid_test.xml"); + llofstream gridfile(TEST_FILENAME); gridfile << gSampleGridFile; gridfile.close(); - LLGridManager::getInstance()->initialize("grid_test.xml"); + LLGridManager::getInstance()->initialize(TEST_FILENAME); LLSLURL slurl = LLSLURL("my.grid.com", "my region"); ensure_equals("grid/region - type", slurl.getType(), LLSLURL::LOCATION); @@ -293,11 +302,11 @@ namespace tut template<> template<> void slurlTestObject::test<3>() { - llofstream gridfile("grid_test.xml"); + llofstream gridfile(TEST_FILENAME); gridfile << gSampleGridFile; gridfile.close(); - LLGridManager::getInstance()->initialize("grid_test.xml"); + LLGridManager::getInstance()->initialize(TEST_FILENAME); LLGridManager::getInstance()->setGridChoice("my.grid.com"); LLSLURL slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3"); diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index 7ad7947ca4..0eb0ab6500 100755 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -6,7 +6,7 @@ * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,6 +31,13 @@ #include "../../llxml/llcontrol.h" #include "llfile.h" +namespace +{ + +// Should not collide with other test programs creating temp files. +static const char * const TEST_FILENAME("llviewernetwork_test.xml"); + +} //---------------------------------------------------------------------------- // Mock objects for the dependencies of the code we're testing @@ -143,7 +150,7 @@ namespace tut { viewerNetworkTest() { - LLFile::remove("grid_test.xml"); + LLFile::remove(TEST_FILENAME); gCmdLineLoginURI.clear(); gCmdLineGridChoice.clear(); gCmdLineHelperURI.clear(); @@ -152,7 +159,7 @@ namespace tut } ~viewerNetworkTest() { - LLFile::remove("grid_test.xml"); + LLFile::remove(TEST_FILENAME); } }; @@ -170,7 +177,7 @@ namespace tut { LLGridManager *manager = LLGridManager::getInstance(); // grid file doesn't exist - manager->initialize("grid_test.xml"); + manager->initialize(TEST_FILENAME); // validate that some of the defaults are available. std::map known_grids = manager->getKnownGrids(); ensure_equals("Known grids is a string-string map of size 2", known_grids.size(), 2); @@ -238,11 +245,11 @@ namespace tut template<> template<> void viewerNetworkTestObject::test<2>() { - llofstream gridfile("grid_test.xml"); + llofstream gridfile(TEST_FILENAME); gridfile << gSampleGridFile; gridfile.close(); - LLGridManager::getInstance()->initialize("grid_test.xml"); + LLGridManager::getInstance()->initialize(TEST_FILENAME); std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); ensure_equals("adding a grid via a grid file increases known grid size",4, known_grids.size()); @@ -369,11 +376,11 @@ namespace tut void viewerNetworkTestObject::test<7>() { // adding a grid with simply a name will populate the values. - llofstream gridfile("grid_test.xml"); + llofstream gridfile(TEST_FILENAME); gridfile << gSampleGridFile; gridfile.close(); - LLGridManager::getInstance()->initialize("grid_test.xml"); + LLGridManager::getInstance()->initialize(TEST_FILENAME); LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); ensure_equals("getGridLabel", -- cgit v1.2.3 From f71c6c745bc390fadc571801a0d7c043249ade24 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Tue, 9 Sep 2014 15:36:35 -0400 Subject: Cleanup pass. Documentation. Get older llcorehttp-using code to use utils for any LLSD interfaces. --- indra/llmessage/llcorehttputil.cpp | 4 +- indra/newview/llinventorymodel.cpp | 14 ++++- indra/newview/llinventorymodelbackgroundfetch.cpp | 28 +++++++--- indra/newview/llmeshrepository.cpp | 64 +++++++++-------------- indra/newview/lltexturefetch.cpp | 34 ++++++------ 5 files changed, 78 insertions(+), 66 deletions(-) diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 8d09aac971..ee80b0fd94 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -39,7 +39,9 @@ using namespace LLCore; namespace LLCoreHttpUtil { - +// *TODO: Currently converts only from XML content. A mode +// to convert using fromBinary() might be useful as well. Mesh +// headers could use it. bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd) { // Convert response to LLSD diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5273fb6d96..1625ae0d1b 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3958,7 +3958,10 @@ BOOL decompress_file(const char* src_filename, const char* dst_filename) } #endif -// ==== FetchItemHttpHandler ==== + +///---------------------------------------------------------------------------- +/// Class LLInventoryModel::FetchItemHttpHandler +///---------------------------------------------------------------------------- LLInventoryModel::FetchItemHttpHandler::FetchItemHttpHandler(const LLSD & request_sd) : LLCore::HttpHandler(), @@ -4006,6 +4009,15 @@ void LLInventoryModel::FetchItemHttpHandler::onCompleted(LLCore::HttpHandle hand } // Check for 200-with-error failures + // + // Original Responder-based serivce model didn't check for these errors. + // It may be more robust to ignore this condition. With aggregated requests, + // an error in one inventory item might take down the entire request. + // So if this instead broke up the aggregated items into single requests, + // maybe that would make progress. Or perhaps there's structured information + // that can tell us what went wrong. Need to dig into this and firm up + // the API. + // // body_llsd["error"] = LLSD::emptyMap(); // Dev tool to force error handling // body_llsd["error"]["identifier"] = "Development"; // body_llsd["error"]["message"] = "You left development code in the viewer"; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 0c04a9c039..013134843a 100755 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -45,6 +45,10 @@ namespace { +///---------------------------------------------------------------------------- +/// Class ::BGItemHttpHandler +///---------------------------------------------------------------------------- + // // Http request handler class for single inventory item requests. // @@ -80,6 +84,10 @@ protected: }; +///---------------------------------------------------------------------------- +/// Class ::BGFolderHttpHandler +///---------------------------------------------------------------------------- + // Http request handler class for folders. // // Handler for FetchInventoryDescendents2 and FetchLibDescendents2 @@ -130,6 +138,10 @@ const char * const LOG_INV("Inventory"); } // end of namespace anonymous +///---------------------------------------------------------------------------- +/// Class LLInventoryModelBackgroundFetch +///---------------------------------------------------------------------------- + LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch(): mBackgroundFetchActive(FALSE), mFolderFetchActive(false), @@ -684,14 +696,12 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL } -// =============================== -// Anonymous Namespace Definitions -// =============================== - namespace { -// ==== BGFolderHttpHandler ==== +///---------------------------------------------------------------------------- +/// Class ::BGFolderHttpHandler +///---------------------------------------------------------------------------- void BGFolderHttpHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) { @@ -734,6 +744,9 @@ void BGFolderHttpHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRes } // Check for 200-with-error failures + // + // See comments in llinventorymodel.cpp about this mode of error. + // // body_llsd["error"] = LLSD::emptyMap(); // Dev tool to force error handling // body_llsd["error"]["identifier"] = "Development"; // body_llsd["error"]["message"] = "You left development code in the viewer"; @@ -976,8 +989,9 @@ bool BGFolderHttpHandler::getIsRecursive(const LLUUID & cat_id) const return std::find(mRecursiveCatUUIDs.begin(), mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end(); } - -// ==== BGItemHttpHandler ==== +///---------------------------------------------------------------------------- +/// Class ::BGItemHttpHandler +///---------------------------------------------------------------------------- // Nothing to implement here. All ctor/dtor changes. diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a6707392fe..2b044c6916 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -71,6 +71,7 @@ #include "bufferarray.h" #include "bufferstream.h" #include "llfasttimer.h" +#include "llcorehttputil.h" #include "boost/lexical_cast.hpp" @@ -2236,21 +2237,17 @@ void LLMeshUploadThread::doWholeModelUpload() mModelData = LLSD::emptyMap(); wholeModelToLLSD(mModelData, true); LLSD body = mModelData["asset_resources"]; - dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num)); - - LLCore::BufferArray * ba = new LLCore::BufferArray; - LLCore::BufferArrayStream bas(ba); - LLSDSerialize::toXML(body, bas); - // LLSDSerialize::toXML(mModelData, bas); // <- Enabling this will generate a convenient upload error - LLCore::HttpHandle handle = mHttpRequest->requestPost(mHttpPolicyClass, - mHttpPriority, - mWholeModelUploadURL, - ba, - mHttpOptions, - mHttpHeaders, - this); - ba->release(); - + + dump_llsd_to_file(body, make_dump_name("whole_model_body_", dump_num)); + + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, + mHttpPolicyClass, + mHttpPriority, + mWholeModelUploadURL, + body, + mHttpOptions, + mHttpHeaders, + this); if (LLCORE_HTTP_HANDLE_INVALID == handle) { mHttpStatus = mHttpRequest->getStatus(); @@ -2294,19 +2291,14 @@ void LLMeshUploadThread::requestWholeModelFee() mModelData = LLSD::emptyMap(); wholeModelToLLSD(mModelData, false); dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num)); - - LLCore::BufferArray * ba = new LLCore::BufferArray; - LLCore::BufferArrayStream bas(ba); - LLSDSerialize::toXML(mModelData, bas); - - LLCore::HttpHandle handle = mHttpRequest->requestPost(mHttpPolicyClass, - mHttpPriority, - mWholeModelFeeCapability, - ba, - mHttpOptions, - mHttpHeaders, - this); - ba->release(); + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, + mHttpPolicyClass, + mHttpPriority, + mWholeModelFeeCapability, + mModelData, + mHttpOptions, + mHttpHeaders, + this); if (LLCORE_HTTP_HANDLE_INVALID == handle) { mHttpStatus = mHttpRequest->getStatus(); @@ -2379,12 +2371,8 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp } else { - LLCore::BufferArray * ba(response->getBody()); - if (ba && ba->size()) - { - LLCore::BufferArrayStream bas(ba); - LLSDSerialize::fromXML(body, bas); - } + // *TODO: handle error in conversion process + LLCoreHttpUtil::responseToLLSD(response, true, body); } dump_llsd_to_file(body, make_dump_name("whole_model_upload_response_", dump_num)); @@ -2443,12 +2431,8 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp } else { - LLCore::BufferArray * ba(response->getBody()); - if (ba && ba->size()) - { - LLCore::BufferArrayStream bas(ba); - LLSDSerialize::fromXML(body, bas); - } + // *TODO: handle error in conversion process + LLCoreHttpUtil::responseToLLSD(response, true, body); } dump_llsd_to_file(body, make_dump_name("whole_model_fee_response_", dump_num)); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index a64a6ee091..a955b907d4 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -56,13 +56,13 @@ #include "llsdparam.h" #include "llsdutil.h" #include "llstartup.h" -#include "llsdserialize.h" #include "httprequest.h" #include "httphandler.h" #include "httpresponse.h" #include "bufferarray.h" #include "bufferstream.h" +#include "llcorehttputil.h" #include "llhttpretrypolicy.h" @@ -1349,20 +1349,20 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_WARNS(LOG_TXT) << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL; } setUrl(http_url + "/?texture_id=" + mID.asString().c_str()); - LL_DEBUGS("Texture") << "Texture URL " << mUrl << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Texture URL: " << mUrl << LL_ENDL; mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. } else { mCanUseHTTP = false ; - LL_DEBUGS("Texture") << "Texture not available via HTTP: no URL " << mUrl << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL; } } else { // This will happen if not logged in or if a region deoes not have HTTP Texture enabled //LL_WARNS(LOG_TXT) << "Region not found for host: " << mHost << LL_ENDL; - LL_DEBUGS("Texture") << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; mCanUseHTTP = false; } } @@ -4026,7 +4026,9 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // Update sequence number if (S32_MAX == ++report_sequence) + { report_sequence = 0; + } reporting_started = true; // Limit the size of the stats report if necessary. @@ -4035,18 +4037,16 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) if (! mCapsURL.empty()) { - LLCore::BufferArray * ba = new LLCore::BufferArray; - LLCore::BufferArrayStream bas(ba); - LLSDSerialize::toXML(sd, bas); - - fetcher->getHttpRequest().requestPost(fetcher->getPolicyClass(), - report_priority, - mCapsURL, - ba, - NULL, - fetcher->getMetricsHeaders(), - handler); - ba->release(); + // *TODO: Move this to a different class that expects POSTs sometime. + // Don't care about handle, this is a fire-and-forget operation. + LLCoreHttpUtil::requestPostWithLLSD(&fetcher->getHttpRequest(), + fetcher->getPolicyClass(), + report_priority, + mCapsURL, + sd, + NULL, + fetcher->getMetricsHeaders(), + handler); LLTextureFetch::svMetricsDataBreak = false; } else @@ -4057,7 +4057,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // In QA mode, Metrics submode, log the result for ease of testing if (fetcher->isQAMode()) { - LL_INFOS("Textures") << ll_pretty_print_sd(sd) << LL_ENDL; + LL_INFOS(LOG_TXT) << ll_pretty_print_sd(sd) << LL_ENDL; } return true; -- cgit v1.2.3 From b68624da0ec4da51722e39f9adf275725ee3a29f Mon Sep 17 00:00:00 2001 From: eli Date: Mon, 15 Sep 2014 15:24:53 -0700 Subject: FIX INTL-151 translation for Viewer Set41 for viewer-release-nui-login in 9 languages --- .../skins/default/xui/de/floater_big_preview.xml | 2 + .../skins/default/xui/de/floater_facebook.xml | 20 ++++ .../skins/default/xui/de/floater_flickr.xml | 17 +++ .../skins/default/xui/de/floater_perms_default.xml | 6 ++ .../skins/default/xui/de/floater_report_abuse.xml | 10 +- .../default/xui/de/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/de/floater_snapshot.xml | 12 ++- .../newview/skins/default/xui/de/floater_stats.xml | 9 +- .../newview/skins/default/xui/de/floater_tools.xml | 2 +- .../skins/default/xui/de/floater_twitter.xml | 17 +++ .../skins/default/xui/de/menu_conversation.xml | 1 + indra/newview/skins/default/xui/de/menu_object.xml | 1 + indra/newview/skins/default/xui/de/menu_viewer.xml | 21 ++-- .../newview/skins/default/xui/de/notifications.xml | 38 ++++++- .../default/xui/de/panel_facebook_account.xml | 15 +++ .../default/xui/de/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/de/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/de/panel_facebook_place.xml | 17 +++ .../skins/default/xui/de/panel_facebook_status.xml | 14 +++ .../skins/default/xui/de/panel_flickr_account.xml | 15 +++ .../skins/default/xui/de/panel_flickr_photo.xml | 41 ++++++++ .../skins/default/xui/de/panel_group_bulk_ban.xml | 43 ++++++++ .../skins/default/xui/de/panel_group_invite.xml | 2 +- .../skins/default/xui/de/panel_group_roles.xml | 24 ++++- indra/newview/skins/default/xui/de/panel_login.xml | 51 +++------ .../skins/default/xui/de/panel_login_first.xml | 33 ++++++ .../default/xui/de/panel_preferences_advanced.xml | 1 + .../default/xui/de/panel_preferences_general.xml | 10 +- .../default/xui/de/panel_preferences_privacy.xml | 5 +- .../skins/default/xui/de/panel_script_ed.xml | 5 +- .../default/xui/de/panel_snapshot_options.xml | 12 ++- .../default/xui/de/panel_teleport_history_item.xml | 1 + .../skins/default/xui/de/panel_twitter_account.xml | 15 +++ .../skins/default/xui/de/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/de/role_actions.xml | 1 + indra/newview/skins/default/xui/de/strings.xml | 114 ++++++++++++++++++++- .../skins/default/xui/es/floater_big_preview.xml | 2 + .../skins/default/xui/es/floater_facebook.xml | 20 ++++ .../skins/default/xui/es/floater_flickr.xml | 17 +++ .../skins/default/xui/es/floater_perms_default.xml | 6 ++ .../skins/default/xui/es/floater_report_abuse.xml | 12 +-- .../default/xui/es/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/es/floater_snapshot.xml | 8 +- .../newview/skins/default/xui/es/floater_stats.xml | 9 +- .../newview/skins/default/xui/es/floater_tools.xml | 2 +- .../skins/default/xui/es/floater_twitter.xml | 17 +++ .../skins/default/xui/es/menu_conversation.xml | 1 + indra/newview/skins/default/xui/es/menu_object.xml | 1 + indra/newview/skins/default/xui/es/menu_viewer.xml | 21 ++-- .../newview/skins/default/xui/es/notifications.xml | 38 ++++++- .../default/xui/es/panel_facebook_account.xml | 15 +++ .../default/xui/es/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/es/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/es/panel_facebook_place.xml | 17 +++ .../skins/default/xui/es/panel_facebook_status.xml | 14 +++ .../skins/default/xui/es/panel_flickr_account.xml | 15 +++ .../skins/default/xui/es/panel_flickr_photo.xml | 41 ++++++++ .../skins/default/xui/es/panel_group_bulk_ban.xml | 43 ++++++++ .../skins/default/xui/es/panel_group_invite.xml | 2 +- .../skins/default/xui/es/panel_group_roles.xml | 25 ++++- indra/newview/skins/default/xui/es/panel_login.xml | 51 +++------ .../skins/default/xui/es/panel_login_first.xml | 33 ++++++ .../default/xui/es/panel_preferences_advanced.xml | 1 + .../default/xui/es/panel_preferences_general.xml | 10 +- .../default/xui/es/panel_preferences_privacy.xml | 5 +- .../skins/default/xui/es/panel_script_ed.xml | 5 +- .../default/xui/es/panel_snapshot_options.xml | 9 ++ .../default/xui/es/panel_teleport_history_item.xml | 1 + .../skins/default/xui/es/panel_twitter_account.xml | 15 +++ .../skins/default/xui/es/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/es/role_actions.xml | 1 + indra/newview/skins/default/xui/es/strings.xml | 114 ++++++++++++++++++++- .../skins/default/xui/fr/floater_big_preview.xml | 2 + .../skins/default/xui/fr/floater_facebook.xml | 20 ++++ .../skins/default/xui/fr/floater_flickr.xml | 17 +++ .../skins/default/xui/fr/floater_perms_default.xml | 6 ++ .../skins/default/xui/fr/floater_report_abuse.xml | 12 +-- .../default/xui/fr/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/fr/floater_snapshot.xml | 8 +- .../newview/skins/default/xui/fr/floater_stats.xml | 9 +- .../newview/skins/default/xui/fr/floater_tools.xml | 2 +- .../skins/default/xui/fr/floater_twitter.xml | 17 +++ .../skins/default/xui/fr/menu_conversation.xml | 1 + indra/newview/skins/default/xui/fr/menu_object.xml | 1 + indra/newview/skins/default/xui/fr/menu_viewer.xml | 21 ++-- .../newview/skins/default/xui/fr/notifications.xml | 38 ++++++- .../default/xui/fr/panel_facebook_account.xml | 15 +++ .../default/xui/fr/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/fr/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/fr/panel_facebook_place.xml | 17 +++ .../skins/default/xui/fr/panel_facebook_status.xml | 14 +++ .../skins/default/xui/fr/panel_flickr_account.xml | 15 +++ .../skins/default/xui/fr/panel_flickr_photo.xml | 41 ++++++++ .../skins/default/xui/fr/panel_group_bulk_ban.xml | 43 ++++++++ .../skins/default/xui/fr/panel_group_invite.xml | 2 +- .../skins/default/xui/fr/panel_group_roles.xml | 25 ++++- indra/newview/skins/default/xui/fr/panel_login.xml | 51 +++------ .../skins/default/xui/fr/panel_login_first.xml | 33 ++++++ .../default/xui/fr/panel_preferences_advanced.xml | 1 + .../default/xui/fr/panel_preferences_general.xml | 10 +- .../default/xui/fr/panel_preferences_privacy.xml | 4 +- .../skins/default/xui/fr/panel_script_ed.xml | 5 +- .../default/xui/fr/panel_snapshot_options.xml | 9 ++ .../default/xui/fr/panel_teleport_history_item.xml | 1 + .../skins/default/xui/fr/panel_twitter_account.xml | 15 +++ .../skins/default/xui/fr/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/fr/role_actions.xml | 1 + indra/newview/skins/default/xui/fr/strings.xml | 114 ++++++++++++++++++++- .../skins/default/xui/it/floater_big_preview.xml | 2 + .../skins/default/xui/it/floater_facebook.xml | 20 ++++ .../skins/default/xui/it/floater_flickr.xml | 17 +++ .../skins/default/xui/it/floater_perms_default.xml | 6 ++ .../skins/default/xui/it/floater_report_abuse.xml | 12 +-- .../default/xui/it/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/it/floater_snapshot.xml | 8 +- .../newview/skins/default/xui/it/floater_stats.xml | 9 +- .../newview/skins/default/xui/it/floater_tools.xml | 2 +- .../skins/default/xui/it/floater_twitter.xml | 17 +++ .../skins/default/xui/it/menu_conversation.xml | 1 + indra/newview/skins/default/xui/it/menu_object.xml | 1 + indra/newview/skins/default/xui/it/menu_viewer.xml | 21 ++-- .../newview/skins/default/xui/it/notifications.xml | 38 ++++++- .../default/xui/it/panel_facebook_account.xml | 15 +++ .../default/xui/it/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/it/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/it/panel_facebook_place.xml | 17 +++ .../skins/default/xui/it/panel_facebook_status.xml | 14 +++ .../skins/default/xui/it/panel_flickr_account.xml | 15 +++ .../skins/default/xui/it/panel_flickr_photo.xml | 41 ++++++++ .../skins/default/xui/it/panel_group_bulk_ban.xml | 43 ++++++++ .../skins/default/xui/it/panel_group_invite.xml | 2 +- .../skins/default/xui/it/panel_group_roles.xml | 26 ++++- indra/newview/skins/default/xui/it/panel_login.xml | 51 +++------ .../skins/default/xui/it/panel_login_first.xml | 33 ++++++ .../default/xui/it/panel_preferences_advanced.xml | 1 + .../default/xui/it/panel_preferences_general.xml | 10 +- .../default/xui/it/panel_preferences_privacy.xml | 2 +- .../skins/default/xui/it/panel_script_ed.xml | 5 +- .../default/xui/it/panel_snapshot_options.xml | 9 ++ .../default/xui/it/panel_teleport_history_item.xml | 1 + .../skins/default/xui/it/panel_twitter_account.xml | 15 +++ .../skins/default/xui/it/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/it/role_actions.xml | 1 + indra/newview/skins/default/xui/it/strings.xml | 114 ++++++++++++++++++++- .../skins/default/xui/ja/floater_big_preview.xml | 2 + .../skins/default/xui/ja/floater_facebook.xml | 20 ++++ .../skins/default/xui/ja/floater_flickr.xml | 17 +++ .../skins/default/xui/ja/floater_perms_default.xml | 6 ++ .../skins/default/xui/ja/floater_report_abuse.xml | 12 +-- .../default/xui/ja/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/ja/floater_snapshot.xml | 8 +- .../newview/skins/default/xui/ja/floater_stats.xml | 9 +- .../newview/skins/default/xui/ja/floater_tools.xml | 2 +- .../skins/default/xui/ja/floater_twitter.xml | 17 +++ .../skins/default/xui/ja/menu_conversation.xml | 1 + indra/newview/skins/default/xui/ja/menu_object.xml | 1 + indra/newview/skins/default/xui/ja/menu_viewer.xml | 21 ++-- .../newview/skins/default/xui/ja/notifications.xml | 38 ++++++- .../default/xui/ja/panel_facebook_account.xml | 15 +++ .../default/xui/ja/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/ja/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/ja/panel_facebook_place.xml | 17 +++ .../skins/default/xui/ja/panel_facebook_status.xml | 14 +++ .../skins/default/xui/ja/panel_flickr_account.xml | 15 +++ .../skins/default/xui/ja/panel_flickr_photo.xml | 41 ++++++++ .../skins/default/xui/ja/panel_group_bulk_ban.xml | 41 ++++++++ .../skins/default/xui/ja/panel_group_invite.xml | 2 +- .../skins/default/xui/ja/panel_group_roles.xml | 24 ++++- indra/newview/skins/default/xui/ja/panel_login.xml | 51 +++------ .../skins/default/xui/ja/panel_login_first.xml | 33 ++++++ .../default/xui/ja/panel_preferences_advanced.xml | 1 + .../default/xui/ja/panel_preferences_general.xml | 10 +- .../default/xui/ja/panel_preferences_privacy.xml | 2 +- .../skins/default/xui/ja/panel_script_ed.xml | 5 +- .../default/xui/ja/panel_snapshot_options.xml | 11 +- .../default/xui/ja/panel_teleport_history_item.xml | 1 + .../skins/default/xui/ja/panel_twitter_account.xml | 15 +++ .../skins/default/xui/ja/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/ja/role_actions.xml | 1 + indra/newview/skins/default/xui/ja/strings.xml | 114 ++++++++++++++++++++- .../skins/default/xui/ru/floater_big_preview.xml | 2 + .../skins/default/xui/ru/floater_facebook.xml | 20 ++++ .../skins/default/xui/ru/floater_flickr.xml | 17 +++ .../skins/default/xui/ru/floater_perms_default.xml | 6 ++ .../skins/default/xui/ru/floater_report_abuse.xml | 12 +-- .../default/xui/ru/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/ru/floater_snapshot.xml | 8 +- .../newview/skins/default/xui/ru/floater_stats.xml | 9 +- .../newview/skins/default/xui/ru/floater_tools.xml | 81 +-------------- .../skins/default/xui/ru/floater_twitter.xml | 17 +++ .../skins/default/xui/ru/menu_conversation.xml | 1 + indra/newview/skins/default/xui/ru/menu_object.xml | 1 + indra/newview/skins/default/xui/ru/menu_viewer.xml | 20 ++-- .../newview/skins/default/xui/ru/notifications.xml | 38 ++++++- .../default/xui/ru/panel_facebook_account.xml | 15 +++ .../default/xui/ru/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/ru/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/ru/panel_facebook_place.xml | 17 +++ .../skins/default/xui/ru/panel_facebook_status.xml | 14 +++ .../skins/default/xui/ru/panel_flickr_account.xml | 15 +++ .../skins/default/xui/ru/panel_flickr_photo.xml | 40 ++++++++ .../skins/default/xui/ru/panel_group_bulk_ban.xml | 41 ++++++++ .../skins/default/xui/ru/panel_group_invite.xml | 2 +- .../skins/default/xui/ru/panel_group_roles.xml | 24 ++++- indra/newview/skins/default/xui/ru/panel_login.xml | 51 +++------ .../skins/default/xui/ru/panel_login_first.xml | 33 ++++++ .../default/xui/ru/panel_preferences_advanced.xml | 1 + .../default/xui/ru/panel_preferences_general.xml | 10 +- .../default/xui/ru/panel_preferences_privacy.xml | 2 +- .../skins/default/xui/ru/panel_script_ed.xml | 5 +- .../default/xui/ru/panel_snapshot_options.xml | 9 ++ .../default/xui/ru/panel_teleport_history_item.xml | 1 + .../skins/default/xui/ru/panel_twitter_account.xml | 15 +++ .../skins/default/xui/ru/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/ru/role_actions.xml | 1 + indra/newview/skins/default/xui/ru/strings.xml | 114 ++++++++++++++++++++- .../skins/default/xui/tr/floater_big_preview.xml | 2 + .../skins/default/xui/tr/floater_facebook.xml | 20 ++++ .../skins/default/xui/tr/floater_flickr.xml | 17 +++ .../skins/default/xui/tr/floater_perms_default.xml | 6 ++ .../skins/default/xui/tr/floater_report_abuse.xml | 12 +-- .../default/xui/tr/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/tr/floater_snapshot.xml | 8 +- .../newview/skins/default/xui/tr/floater_stats.xml | 9 +- .../newview/skins/default/xui/tr/floater_tools.xml | 81 +-------------- .../skins/default/xui/tr/floater_twitter.xml | 17 +++ .../skins/default/xui/tr/menu_conversation.xml | 1 + indra/newview/skins/default/xui/tr/menu_object.xml | 1 + indra/newview/skins/default/xui/tr/menu_viewer.xml | 21 ++-- .../newview/skins/default/xui/tr/notifications.xml | 38 ++++++- .../default/xui/tr/panel_facebook_account.xml | 15 +++ .../default/xui/tr/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/tr/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/tr/panel_facebook_place.xml | 17 +++ .../skins/default/xui/tr/panel_facebook_status.xml | 14 +++ .../skins/default/xui/tr/panel_flickr_account.xml | 15 +++ .../skins/default/xui/tr/panel_flickr_photo.xml | 41 ++++++++ .../skins/default/xui/tr/panel_group_bulk_ban.xml | 43 ++++++++ .../skins/default/xui/tr/panel_group_invite.xml | 2 +- .../skins/default/xui/tr/panel_group_roles.xml | 22 +++- indra/newview/skins/default/xui/tr/panel_login.xml | 51 +++------ .../skins/default/xui/tr/panel_login_first.xml | 33 ++++++ .../default/xui/tr/panel_preferences_advanced.xml | 1 + .../default/xui/tr/panel_preferences_general.xml | 10 +- .../default/xui/tr/panel_preferences_privacy.xml | 2 +- .../skins/default/xui/tr/panel_script_ed.xml | 5 +- .../default/xui/tr/panel_snapshot_options.xml | 9 ++ .../default/xui/tr/panel_teleport_history_item.xml | 1 + .../skins/default/xui/tr/panel_twitter_account.xml | 15 +++ .../skins/default/xui/tr/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/tr/role_actions.xml | 1 + indra/newview/skins/default/xui/tr/strings.xml | 114 ++++++++++++++++++++- .../skins/default/xui/zh/floater_big_preview.xml | 2 + .../skins/default/xui/zh/floater_facebook.xml | 20 ++++ .../skins/default/xui/zh/floater_flickr.xml | 17 +++ .../skins/default/xui/zh/floater_perms_default.xml | 6 ++ .../skins/default/xui/zh/floater_report_abuse.xml | 12 +-- .../default/xui/zh/floater_script_ed_prefs.xml | 48 +++++++++ .../skins/default/xui/zh/floater_snapshot.xml | 8 +- .../newview/skins/default/xui/zh/floater_stats.xml | 9 +- .../newview/skins/default/xui/zh/floater_tools.xml | 81 +-------------- .../skins/default/xui/zh/floater_twitter.xml | 17 +++ .../skins/default/xui/zh/menu_conversation.xml | 1 + indra/newview/skins/default/xui/zh/menu_object.xml | 1 + indra/newview/skins/default/xui/zh/menu_viewer.xml | 21 ++-- .../newview/skins/default/xui/zh/notifications.xml | 38 ++++++- .../default/xui/zh/panel_facebook_account.xml | 15 +++ .../default/xui/zh/panel_facebook_friends.xml | 12 +++ .../skins/default/xui/zh/panel_facebook_photo.xml | 26 +++++ .../skins/default/xui/zh/panel_facebook_place.xml | 17 +++ .../skins/default/xui/zh/panel_facebook_status.xml | 14 +++ .../skins/default/xui/zh/panel_flickr_account.xml | 15 +++ .../skins/default/xui/zh/panel_flickr_photo.xml | 41 ++++++++ .../skins/default/xui/zh/panel_group_bulk_ban.xml | 43 ++++++++ .../skins/default/xui/zh/panel_group_invite.xml | 2 +- .../skins/default/xui/zh/panel_group_roles.xml | 27 ++++- indra/newview/skins/default/xui/zh/panel_login.xml | 51 +++------ .../skins/default/xui/zh/panel_login_first.xml | 33 ++++++ .../default/xui/zh/panel_preferences_advanced.xml | 1 + .../default/xui/zh/panel_preferences_general.xml | 10 +- .../default/xui/zh/panel_preferences_privacy.xml | 2 +- .../skins/default/xui/zh/panel_script_ed.xml | 5 +- .../default/xui/zh/panel_snapshot_options.xml | 9 ++ .../default/xui/zh/panel_teleport_history_item.xml | 1 + .../skins/default/xui/zh/panel_twitter_account.xml | 15 +++ .../skins/default/xui/zh/panel_twitter_photo.xml | 32 ++++++ .../newview/skins/default/xui/zh/role_actions.xml | 1 + indra/newview/skins/default/xui/zh/strings.xml | 108 ++++++++++++++++++- 288 files changed, 4811 insertions(+), 914 deletions(-) create mode 100644 indra/newview/skins/default/xui/de/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/de/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/de/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/de/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/de/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/de/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/de/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/de/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/de/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/de/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/de/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/de/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/de/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/de/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/de/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/de/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/de/panel_twitter_photo.xml create mode 100644 indra/newview/skins/default/xui/es/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/es/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/es/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/es/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/es/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/es/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/es/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/es/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/es/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/es/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/es/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/es/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/es/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/es/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/es/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/es/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/es/panel_twitter_photo.xml create mode 100644 indra/newview/skins/default/xui/fr/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/fr/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/fr/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/fr/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/fr/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/fr/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/fr/panel_twitter_photo.xml create mode 100644 indra/newview/skins/default/xui/it/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/it/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/it/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/it/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/it/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/it/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/it/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/it/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/it/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/it/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/it/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/it/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/it/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/it/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/it/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/it/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/it/panel_twitter_photo.xml create mode 100644 indra/newview/skins/default/xui/ja/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/ja/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/ja/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/ja/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/ja/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/ja/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/ja/panel_twitter_photo.xml create mode 100644 indra/newview/skins/default/xui/ru/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/ru/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/ru/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/ru/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/ru/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/ru/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/ru/panel_twitter_photo.xml create mode 100644 indra/newview/skins/default/xui/tr/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/tr/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/tr/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/tr/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/tr/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/tr/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/tr/panel_twitter_photo.xml create mode 100644 indra/newview/skins/default/xui/zh/floater_big_preview.xml create mode 100644 indra/newview/skins/default/xui/zh/floater_facebook.xml create mode 100644 indra/newview/skins/default/xui/zh/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/zh/floater_perms_default.xml create mode 100644 indra/newview/skins/default/xui/zh/floater_script_ed_prefs.xml create mode 100644 indra/newview/skins/default/xui/zh/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_facebook_friends.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_facebook_status.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_flickr_photo.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_group_bulk_ban.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_login_first.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/zh/panel_twitter_photo.xml diff --git a/indra/newview/skins/default/xui/de/floater_big_preview.xml b/indra/newview/skins/default/xui/de/floater_big_preview.xml new file mode 100644 index 0000000000..c5ce56d1d9 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_big_preview.xml @@ -0,0 +1,2 @@ + + diff --git a/indra/newview/skins/default/xui/de/floater_facebook.xml b/indra/newview/skins/default/xui/de/floater_facebook.xml new file mode 100644 index 0000000000..25b11536eb --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_facebook.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + Fehler + + + Laden... + + + + diff --git a/indra/newview/skins/default/xui/de/floater_flickr.xml b/indra/newview/skins/default/xui/de/floater_flickr.xml new file mode 100644 index 0000000000..b50fa19ec8 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_flickr.xml @@ -0,0 +1,17 @@ + + + + + + + + + + Fehler + + + Laden... + + + + diff --git a/indra/newview/skins/default/xui/de/floater_perms_default.xml b/indra/newview/skins/default/xui/de/floater_perms_default.xml new file mode 100644 index 0000000000..6d6c89172d --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_perms_default.xml @@ -0,0 +1,6 @@ + + + +