From a53d111cfab7b030a4bd603ba163b7cb66f4a35d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 21 Sep 2023 23:51:03 +0300 Subject: SL-15039 Prune unused preferences #2 List of removed preferences (usused per statistics): BottomPanelNew BrowserHomePage BlockSomeAvatarAppearanceVisualParams ButtonHPad ButtonHeight ButtonHeightSmall CacheNumberOfRegionsForObjects ChatBarStealsFocus ChatLoadGroupTimeout ChatPersistTime ChatShowTimestamps ContextConeInAlpha ContextConeOutAlpha ContextConeFadeTime ConversationHistoryPageSize ContactsTornOff CurlMaximumNumberOfHandles CurlUseMultipleThreads CustomServer DebugShowPrivateMem --- indra/newview/llstartup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1b0a814c45..dac7a1d3ff 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2215,7 +2215,7 @@ bool idle_startup() static LLFrameTimer wearables_timer; const F32 wearables_time = wearables_timer.getElapsedTimeF32(); - static LLCachedControl max_wearables_time(gSavedSettings, "ClothingLoadingDelay"); + const F32 MAX_WEARABLES_TIME = 10.f; if (!gAgent.isOutfitChosen() && isAgentAvatarValid()) { @@ -2234,7 +2234,7 @@ bool idle_startup() display_startup(); - if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time)) + if (gAgent.isOutfitChosen() && (wearables_time > MAX_WEARABLES_TIME)) { if (gInventory.isInventoryUsable()) { -- cgit v1.2.3 From d4087fce7b36625259576d5964c5a8dd8e93d707 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 21 Oct 2023 00:07:40 +0300 Subject: SL-20513 Cleanup LLAvatarPropertiesProcessor #1 --- indra/newview/llstartup.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 228483d42b..cccd16a77e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2657,15 +2657,6 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPropertiesReply", &LLAvatarPropertiesProcessor::processAvatarPropertiesReply); - msg->setHandlerFunc("AvatarInterestsReply", - &LLAvatarPropertiesProcessor::processAvatarInterestsReply); - msg->setHandlerFunc("AvatarGroupsReply", - &LLAvatarPropertiesProcessor::processAvatarGroupsReply); - // ratings deprecated - //msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply, - // LLPanelAvatar::processAvatarStatisticsReply); - msg->setHandlerFunc("AvatarNotesReply", - &LLAvatarPropertiesProcessor::processAvatarNotesReply); msg->setHandlerFunc("AvatarPicksReply", &LLAvatarPropertiesProcessor::processAvatarPicksReply); msg->setHandlerFunc("AvatarClassifiedReply", -- cgit v1.2.3 From f54d0329f32081883704cc2694871600f896006b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 24 Oct 2023 00:14:21 +0300 Subject: SL-20513 Cleanup LLAvatarPropertiesProcessor #2 --- indra/newview/llstartup.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index cccd16a77e..916848ff5f 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2656,9 +2656,7 @@ void register_viewer_callbacks(LLMessageSystem* msg) LLViewerParcelMgr::processParcelDwellReply); msg->setHandlerFunc("AvatarPropertiesReply", - &LLAvatarPropertiesProcessor::processAvatarPropertiesReply); - msg->setHandlerFunc("AvatarPicksReply", - &LLAvatarPropertiesProcessor::processAvatarPicksReply); + &LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply); msg->setHandlerFunc("AvatarClassifiedReply", &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply); -- cgit v1.2.3 From aff01e2fd4fb5475eb42ce58d1ad997341cb7a94 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 10 Nov 2023 23:36:33 +0200 Subject: SL-20575 Fix some deletion issues - Fixes 'cut' checks for gallery - Checking if large folder is deletable should be faster now - For large flat root folders eliminated delay of looking for cof Might be a good idea to start cashing isItemRemovable if category version hasn't changed. --- indra/newview/llstartup.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 916848ff5f..bb867f7b23 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1938,8 +1938,10 @@ bool idle_startup() display_startup(); return FALSE; } + LLInventoryModelBackgroundFetch::instance().start(); - LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + LLAppearanceMgr::instance().initCOFID(); + LLUUID cof_id = LLAppearanceMgr::instance().getCOF(); LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); if (cof && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) @@ -2812,6 +2814,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); // Initiate creation of COF, since we're also bypassing that. gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); + LLAppearanceMgr::getInstance()->initCOFID(); ESex gender; if (gender_name == "male") @@ -2968,6 +2971,7 @@ void reset_login() gAgent.cleanup(); gSky.cleanup(); // mVOSkyp is an inworld object. LLWorld::getInstance()->resetClass(); + LLAppearanceMgr::getInstance()->cleanup(); if ( gViewerWindow ) { // Hide menus and normal buttons -- cgit v1.2.3 From 50a70fe2f831c6d34a6f518ae040e52ac2f9f924 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 28 Mar 2024 00:45:38 +0200 Subject: viewer#1073 crash at loadSkeleton looks like file that was being parced got corrupted 'in progress' --- indra/newview/llstartup.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f30810fb81..6799f8cfdd 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2951,7 +2951,9 @@ std::string LLStartUp::startupStateToString(EStartupState state) RTNENUM( STATE_AGENT_SEND ); RTNENUM( STATE_AGENT_WAIT ); RTNENUM( STATE_INVENTORY_SEND ); - RTNENUM(STATE_INVENTORY_CALLBACKS ); + RTNENUM( STATE_INVENTORY_CALLBACKS ); + RTNENUM( STATE_INVENTORY_SKEL ); + RTNENUM( STATE_INVENTORY_SEND2 ); RTNENUM( STATE_MISC ); RTNENUM( STATE_PRECACHE ); RTNENUM( STATE_WEARABLES_WAIT ); -- cgit v1.2.3 From bc29431ab2f500ba588edaeee34ba2328db199aa Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 24 Apr 2024 21:18:14 +0300 Subject: viewer#1309 Handle deprecated avatar properties messages since server still sends those in some cases --- indra/newview/llstartup.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index e2530ed5e9..3bf6b13caa 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2713,6 +2713,14 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPropertiesReply", &LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply); + msg->setHandlerFunc("AvatarInterestsReply", + &LLAvatarPropertiesProcessor::processAvatarInterestsReply); + msg->setHandlerFunc("AvatarGroupsReply", + &LLAvatarPropertiesProcessor::processAvatarGroupsReply); + msg->setHandlerFunc("AvatarNotesReply", + &LLAvatarPropertiesProcessor::processAvatarNotesReply); + msg->setHandlerFunc("AvatarPicksReply", + &LLAvatarPropertiesProcessor::processAvatarPicksReply); msg->setHandlerFunc("AvatarClassifiedReply", &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply); -- cgit v1.2.3 From 1b68f71348ecf3983b76b40d7940da8377f049b7 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Mon, 29 Apr 2024 07:43:28 +0300 Subject: #824 Process source files in bulk: replace tabs with spaces, convert CRLF to LF, and trim trailing whitespaces as needed --- indra/newview/llstartup.cpp | 6120 +++++++++++++++++++++---------------------- 1 file changed, 3060 insertions(+), 3060 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a0324ca82a..4ad0228bd0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llstartup.cpp * @brief startup routines. * * $LicenseInfo:firstyear=2004&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$ */ @@ -31,9 +31,9 @@ #include "llcallstack.h" #if LL_WINDOWS -# include // _spawnl() +# include // _spawnl() #else -# include // mkdir() +# include // mkdir() #endif #include // std::unique_ptr @@ -84,7 +84,7 @@ #include "llversioninfo.h" #include "llviewercontrol.h" #include "llviewerhelp.h" -#include "llxorcipher.h" // saved password, MAC address +#include "llxorcipher.h" // saved password, MAC address #include "llwindow.h" #include "message.h" #include "v3math.h" @@ -121,7 +121,7 @@ #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" #include "llkeyboard.h" -#include "llloginhandler.h" // gLoginHandler, SLURL support +#include "llloginhandler.h" // gLoginHandler, SLURL support #include "lllogininstance.h" // Host the login module. #include "llpanellogin.h" #include "llmutelist.h" @@ -138,7 +138,7 @@ #include "llselectmgr.h" #include "llsky.h" #include "llstatview.h" -#include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance +#include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance #include "llsurface.h" #include "lltexturecache.h" #include "lltexturefetch.h" @@ -236,7 +236,7 @@ extern S32 gStartImageHeight; // static bool gGotUseCircuitCodeAck = false; static std::string sInitialOutfit; -static std::string sInitialOutfitGender; // "male" or "female" +static std::string sInitialOutfitGender; // "male" or "female" static bool gUseCircuitCallbackCalled = false; @@ -290,12 +290,12 @@ void transition_back_to_login_panel(const std::string& emsg); void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group) { - LLNameBox::refreshAll(id, full_name, is_group); - LLNameEditor::refreshAll(id, full_name, is_group); - - // TODO: Actually be intelligent about the refresh. - // For now, just brute force refresh the dialogs. - dialog_refresh_all(); + LLNameBox::refreshAll(id, full_name, is_group); + LLNameEditor::refreshAll(id, full_name, is_group); + + // TODO: Actually be intelligent about the refresh. + // For now, just brute force refresh the dialogs. + dialog_refresh_all(); } // @@ -320,10 +320,10 @@ void pump_idle_startup_network(void) // void update_texture_fetch() { - LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread - LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread - LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread - gTextureList.updateImages(0.10f); + LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread + LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread + LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread + gTextureList.updateImages(0.10f); if (LLImageGLThread::sEnabledTextures) { @@ -334,8 +334,8 @@ void update_texture_fetch() void set_flags_and_update_appearance() { - LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); - LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op); + LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); + LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op); LLInventoryModelBackgroundFetch::instance().start(); } @@ -344,310 +344,310 @@ void set_flags_and_update_appearance() // true when all initialization done. bool idle_startup() { - if (gViewerWindow == NULL) - { - // We expect window to be initialized - LL_WARNS_ONCE() << "gViewerWindow is not initialized" << LL_ENDL; - return false; // No world yet - } - - const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay"); - static LLTimer timeout; - - static LLTimer login_time; - - // until this is encapsulated, this little hack for the - // auth/transform loop will do. - static F32 progress = 0.10f; - - static std::string auth_desc; - static std::string auth_message; - - static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server - - // last location by default - static S32 agent_location_id = START_LOCATION_ID_LAST; - - static bool show_connect_box = true; - - //static bool stipend_since_login = false; - - // HACK: These are things from the main loop that usually aren't done - // until initialization is complete, but need to be done here for things - // to work. - gIdleCallbacks.callFunctions(); - gViewerWindow->updateUI(); - - LLMortician::updateClass(); - - const std::string delims (" "); - std::string system; - int begIdx, endIdx; - std::string osString = LLOSInfo::instance().getOSStringSimple(); - - begIdx = osString.find_first_not_of (delims); - endIdx = osString.find_first_of (delims, begIdx); - system = osString.substr (begIdx, endIdx - begIdx); - system += "Locale"; - - LLStringUtil::setLocale (LLTrans::getString(system)); - - //note: Removing this line will cause incorrect button size in the login screen. -- bao. - gTextureList.updateImages(0.01f) ; - - if ( STATE_FIRST == LLStartUp::getStartupState() ) - { - static bool first_call = true; - if (first_call) - { - // Other phases get handled when startup state changes, - // need to capture the initial state as well. - LLStartUp::getPhases().startPhase(LLStartUp::getStartupStateString()); - first_call = false; - } - - gViewerWindow->showCursor(); - gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); - - ///////////////////////////////////////////////// - // - // Initialize stuff that doesn't need data from simulators - // - std::string lastGPU = gSavedSettings.getString("LastGPUString"); - std::string thisGPU = LLFeatureManager::getInstance()->getGPUString(); - - if (LLFeatureManager::getInstance()->isSafe()) - { - LLNotificationsUtil::add("DisplaySetToSafe"); - } - else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) && - (gSavedSettings.getS32("LastFeatureVersion") != 0)) - { - LLNotificationsUtil::add("DisplaySetToRecommendedFeatureChange"); - } - else if ( ! lastGPU.empty() && (lastGPU != thisGPU)) - { - LLSD subs; - subs["LAST_GPU"] = lastGPU; - subs["THIS_GPU"] = thisGPU; - LLNotificationsUtil::add("DisplaySetToRecommendedGPUChange", subs); - } - else if (!gViewerWindow->getInitAlert().empty()) - { - LLNotificationsUtil::add(gViewerWindow->getInitAlert()); - } - - //------------------------------------------------- - // Init the SOCKS 5 proxy if the user has configured - // one. We need to do this early in case the user - // is using SOCKS for HTTP so we get the login - // screen and HTTP tables via SOCKS. - //------------------------------------------------- - LLStartUp::startLLProxy(); - - gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion()); - gSavedSettings.setString("LastGPUString", thisGPU); - - - std::string xml_file = LLUI::locateSkin("xui_version.xml"); - LLXMLNodePtr root; - bool xml_ok = false; - if (LLXMLNode::parseFile(xml_file, root, NULL)) - { - if( (root->hasName("xui_version") ) ) - { - std::string value = root->getValue(); - F32 version = 0.0f; - LLStringUtil::convertToF32(value, version); - if (version >= 1.0f) - { - xml_ok = true; - } - } - } - if (!xml_ok) - { - // If XML is bad, there's a good possibility that notifications.xml is ALSO bad. - // If that's so, then we'll get a fatal error on attempting to load it, - // which will display a nontranslatable error message that says so. - // Otherwise, we'll display a reasonable error message that IS translatable. - LLAppViewer::instance()->earlyExit("BadInstallation"); - } - // - // Statistics stuff - // - - // Load autopilot and stats stuff - gAgentPilot.load(); - - //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps")); - - // Load the throttle settings - gViewerThrottle.load(); - - // - // Initialize messaging system - // - LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL; - - std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); - - LLFILE* found_template = NULL; - found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */ - - #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message_template.msg - // file will be located in: - // build-vc**/newview//app_settings - if (!found_template) - { - message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg"); - found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ - } - #elif LL_DARWIN - // On Mac dev builds, message_template.msg lives in: - // indra/build-*/newview//Second Life/Contents/Resources/app_settings - if (!found_template) - { - message_template_path = - gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, - "message_template.msg"); - found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ - } - #endif - - if (found_template) - { - fclose(found_template); - - U32 port = gSavedSettings.getU32("UserConnectionPort"); - - if ((NET_USE_OS_ASSIGNED_PORT == port) && // if nothing specified on command line (-port) - (gSavedSettings.getBOOL("ConnectionPortEnabled"))) - { - port = gSavedSettings.getU32("ConnectionPort"); - } - - // TODO parameterize - const F32 circuit_heartbeat_interval = 5; - const F32 circuit_timeout = 100; - - const LLUseCircuitCodeResponder* responder = NULL; - bool failure_is_fatal = true; - - if(!start_messaging_system( - message_template_path, - port, - LLVersionInfo::instance().getMajor(), - LLVersionInfo::instance().getMinor(), - LLVersionInfo::instance().getPatch(), - FALSE, - std::string(), - responder, - failure_is_fatal, - circuit_heartbeat_interval, - circuit_timeout)) - { - std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode()); - LL_WARNS("AppInit") << diagnostic << LL_ENDL; - LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic)); - } - - #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message.xml file will - // be located in indra/build-vc**/newview//app_settings. - std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml"); - - if (!LLFile::isfile(message_path.c_str())) - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "")); - } - else - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - } - #else - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - #endif - - } - else - { - LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path)); - } - - if(gMessageSystem && gMessageSystem->isOK()) - { - // Initialize all of the callbacks in case of bad message - // system data - LLMessageSystem* msg = gMessageSystem; - msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE, - invalid_message_callback, - NULL); - msg->setExceptionFunc(MX_PACKET_TOO_SHORT, - invalid_message_callback, - NULL); - - // running off end of a packet is now valid in the case - // when a reader has a newer message template than - // the sender - /*msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET, - invalid_message_callback, - NULL);*/ - msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE, - invalid_message_callback, - NULL); - - if (gSavedSettings.getBOOL("LogMessages")) - { - LL_DEBUGS("AppInit") << "Message logging activated!" << LL_ENDL; - msg->startLogging(); - } - - // start the xfer system. by default, choke the downloads - // a lot... - const S32 VIEWER_MAX_XFER = 3; - start_xfer_manager(); - gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER); - F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle"); - if (xfer_throttle_bps > 1.f) - { - gXferManager->setUseAckThrottling(TRUE); - gXferManager->setAckThrottleBPS(xfer_throttle_bps); - } - gAssetStorage = new LLViewerAssetStorage(msg, gXferManager); - - - F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage"); - msg->mPacketRing.setDropPercentage(dropPercent); - - F32 inBandwidth = gSavedSettings.getF32("InBandwidth"); - F32 outBandwidth = gSavedSettings.getF32("OutBandwidth"); - if (inBandwidth != 0.f) - { - LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL; - msg->mPacketRing.setUseInThrottle(TRUE); - msg->mPacketRing.setInBandwidth(inBandwidth); - } - if (outBandwidth != 0.f) - { - LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL; - msg->mPacketRing.setUseOutThrottle(TRUE); - msg->mPacketRing.setOutBandwidth(outBandwidth); - } - } - - LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; - - //------------------------------------------------- - // Init audio, which may be needed for prefs dialog - // or audio cues in connection UI. - //------------------------------------------------- - - if (FALSE == gSavedSettings.getBOOL("NoAudio")) - { - delete gAudiop; - gAudiop = NULL; + if (gViewerWindow == NULL) + { + // We expect window to be initialized + LL_WARNS_ONCE() << "gViewerWindow is not initialized" << LL_ENDL; + return false; // No world yet + } + + const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay"); + static LLTimer timeout; + + static LLTimer login_time; + + // until this is encapsulated, this little hack for the + // auth/transform loop will do. + static F32 progress = 0.10f; + + static std::string auth_desc; + static std::string auth_message; + + static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server + + // last location by default + static S32 agent_location_id = START_LOCATION_ID_LAST; + + static bool show_connect_box = true; + + //static bool stipend_since_login = false; + + // HACK: These are things from the main loop that usually aren't done + // until initialization is complete, but need to be done here for things + // to work. + gIdleCallbacks.callFunctions(); + gViewerWindow->updateUI(); + + LLMortician::updateClass(); + + const std::string delims (" "); + std::string system; + int begIdx, endIdx; + std::string osString = LLOSInfo::instance().getOSStringSimple(); + + begIdx = osString.find_first_not_of (delims); + endIdx = osString.find_first_of (delims, begIdx); + system = osString.substr (begIdx, endIdx - begIdx); + system += "Locale"; + + LLStringUtil::setLocale (LLTrans::getString(system)); + + //note: Removing this line will cause incorrect button size in the login screen. -- bao. + gTextureList.updateImages(0.01f) ; + + if ( STATE_FIRST == LLStartUp::getStartupState() ) + { + static bool first_call = true; + if (first_call) + { + // Other phases get handled when startup state changes, + // need to capture the initial state as well. + LLStartUp::getPhases().startPhase(LLStartUp::getStartupStateString()); + first_call = false; + } + + gViewerWindow->showCursor(); + gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); + + ///////////////////////////////////////////////// + // + // Initialize stuff that doesn't need data from simulators + // + std::string lastGPU = gSavedSettings.getString("LastGPUString"); + std::string thisGPU = LLFeatureManager::getInstance()->getGPUString(); + + if (LLFeatureManager::getInstance()->isSafe()) + { + LLNotificationsUtil::add("DisplaySetToSafe"); + } + else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) && + (gSavedSettings.getS32("LastFeatureVersion") != 0)) + { + LLNotificationsUtil::add("DisplaySetToRecommendedFeatureChange"); + } + else if ( ! lastGPU.empty() && (lastGPU != thisGPU)) + { + LLSD subs; + subs["LAST_GPU"] = lastGPU; + subs["THIS_GPU"] = thisGPU; + LLNotificationsUtil::add("DisplaySetToRecommendedGPUChange", subs); + } + else if (!gViewerWindow->getInitAlert().empty()) + { + LLNotificationsUtil::add(gViewerWindow->getInitAlert()); + } + + //------------------------------------------------- + // Init the SOCKS 5 proxy if the user has configured + // one. We need to do this early in case the user + // is using SOCKS for HTTP so we get the login + // screen and HTTP tables via SOCKS. + //------------------------------------------------- + LLStartUp::startLLProxy(); + + gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion()); + gSavedSettings.setString("LastGPUString", thisGPU); + + + std::string xml_file = LLUI::locateSkin("xui_version.xml"); + LLXMLNodePtr root; + bool xml_ok = false; + if (LLXMLNode::parseFile(xml_file, root, NULL)) + { + if( (root->hasName("xui_version") ) ) + { + std::string value = root->getValue(); + F32 version = 0.0f; + LLStringUtil::convertToF32(value, version); + if (version >= 1.0f) + { + xml_ok = true; + } + } + } + if (!xml_ok) + { + // If XML is bad, there's a good possibility that notifications.xml is ALSO bad. + // If that's so, then we'll get a fatal error on attempting to load it, + // which will display a nontranslatable error message that says so. + // Otherwise, we'll display a reasonable error message that IS translatable. + LLAppViewer::instance()->earlyExit("BadInstallation"); + } + // + // Statistics stuff + // + + // Load autopilot and stats stuff + gAgentPilot.load(); + + //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps")); + + // Load the throttle settings + gViewerThrottle.load(); + + // + // Initialize messaging system + // + LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL; + + std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); + + LLFILE* found_template = NULL; + found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */ + + #if LL_WINDOWS + // On the windows dev builds, unpackaged, the message_template.msg + // file will be located in: + // build-vc**/newview//app_settings + if (!found_template) + { + message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg"); + found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + } + #elif LL_DARWIN + // On Mac dev builds, message_template.msg lives in: + // indra/build-*/newview//Second Life/Contents/Resources/app_settings + if (!found_template) + { + message_template_path = + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, + "message_template.msg"); + found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + } + #endif + + if (found_template) + { + fclose(found_template); + + U32 port = gSavedSettings.getU32("UserConnectionPort"); + + if ((NET_USE_OS_ASSIGNED_PORT == port) && // if nothing specified on command line (-port) + (gSavedSettings.getBOOL("ConnectionPortEnabled"))) + { + port = gSavedSettings.getU32("ConnectionPort"); + } + + // TODO parameterize + const F32 circuit_heartbeat_interval = 5; + const F32 circuit_timeout = 100; + + const LLUseCircuitCodeResponder* responder = NULL; + bool failure_is_fatal = true; + + if(!start_messaging_system( + message_template_path, + port, + LLVersionInfo::instance().getMajor(), + LLVersionInfo::instance().getMinor(), + LLVersionInfo::instance().getPatch(), + FALSE, + std::string(), + responder, + failure_is_fatal, + circuit_heartbeat_interval, + circuit_timeout)) + { + std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode()); + LL_WARNS("AppInit") << diagnostic << LL_ENDL; + LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic)); + } + + #if LL_WINDOWS + // On the windows dev builds, unpackaged, the message.xml file will + // be located in indra/build-vc**/newview//app_settings. + std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml"); + + if (!LLFile::isfile(message_path.c_str())) + { + LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "")); + } + else + { + LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + } + #else + LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + #endif + + } + else + { + LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path)); + } + + if(gMessageSystem && gMessageSystem->isOK()) + { + // Initialize all of the callbacks in case of bad message + // system data + LLMessageSystem* msg = gMessageSystem; + msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE, + invalid_message_callback, + NULL); + msg->setExceptionFunc(MX_PACKET_TOO_SHORT, + invalid_message_callback, + NULL); + + // running off end of a packet is now valid in the case + // when a reader has a newer message template than + // the sender + /*msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET, + invalid_message_callback, + NULL);*/ + msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE, + invalid_message_callback, + NULL); + + if (gSavedSettings.getBOOL("LogMessages")) + { + LL_DEBUGS("AppInit") << "Message logging activated!" << LL_ENDL; + msg->startLogging(); + } + + // start the xfer system. by default, choke the downloads + // a lot... + const S32 VIEWER_MAX_XFER = 3; + start_xfer_manager(); + gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER); + F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle"); + if (xfer_throttle_bps > 1.f) + { + gXferManager->setUseAckThrottling(TRUE); + gXferManager->setAckThrottleBPS(xfer_throttle_bps); + } + gAssetStorage = new LLViewerAssetStorage(msg, gXferManager); + + + F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage"); + msg->mPacketRing.setDropPercentage(dropPercent); + + F32 inBandwidth = gSavedSettings.getF32("InBandwidth"); + F32 outBandwidth = gSavedSettings.getF32("OutBandwidth"); + if (inBandwidth != 0.f) + { + LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL; + msg->mPacketRing.setUseInThrottle(TRUE); + msg->mPacketRing.setInBandwidth(inBandwidth); + } + if (outBandwidth != 0.f) + { + LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL; + msg->mPacketRing.setUseOutThrottle(TRUE); + msg->mPacketRing.setOutBandwidth(outBandwidth); + } + } + + LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; + + //------------------------------------------------- + // Init audio, which may be needed for prefs dialog + // or audio cues in connection UI. + //------------------------------------------------- + + if (FALSE == gSavedSettings.getBOOL("NoAudio")) + { + delete gAudiop; + gAudiop = NULL; #ifdef LL_FMODSTUDIO #if !LL_WINDOWS @@ -660,262 +660,262 @@ bool idle_startup() #ifdef LL_OPENAL #if !LL_WINDOWS - if (NULL == getenv("LL_BAD_OPENAL_DRIVER")) + if (NULL == getenv("LL_BAD_OPENAL_DRIVER")) #endif // !LL_WINDOWS - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); - } + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); + } #endif - - if (gAudiop) - { + + if (gAudiop) + { #if LL_WINDOWS - // FMOD Ex on Windows needs the window handle to stop playing audio - // when window is minimized. JC - void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); + // FMOD Ex on Windows needs the window handle to stop playing audio + // when window is minimized. JC + void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); #else - void* window_handle = NULL; + void* window_handle = NULL; #endif - if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle())) - { - if (FALSE == gSavedSettings.getBOOL("UseMediaPluginsForStreamingAudio")) - { - LL_INFOS("AppInit") << "Using default impl to render streaming audio" << LL_ENDL; - gAudiop->setStreamingAudioImpl(gAudiop->createDefaultStreamingAudioImpl()); - } - - // if the audio engine hasn't set up its own preferred handler for streaming audio - // then set up the generic streaming audio implementation which uses media plugins - if (NULL == gAudiop->getStreamingAudioImpl()) - { - LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; - gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); - } - - gAudiop->setMuted(TRUE); - } - else - { - LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; - delete gAudiop; - gAudiop = NULL; - } - } - } - - LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; - - if (LLTimer::knownBadTimer()) - { - LL_WARNS("AppInit") << "Unreliable timers detected (may be bad PCI chipset)!!" << LL_ENDL; - } - - // - // Log on to system - // - if (gUserCredential.isNull()) - { - gUserCredential = gLoginHandler.initializeLoginInfo(); - } - // Previous initializeLoginInfo may have generated user credentials. Re-check them. - if (gUserCredential.isNull()) - { - show_connect_box = TRUE; - } - else if (gSavedSettings.getBOOL("AutoLogin")) - { - // Log into last account - gRememberPassword = true; - gRememberUser = true; - gSavedSettings.setBOOL("RememberPassword", TRUE); - gSavedSettings.setBOOL("RememberUser", TRUE); - show_connect_box = false; - } - else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3) - { - // Console provided login&password - gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); - gRememberUser = gSavedSettings.getBOOL("RememberUser"); - show_connect_box = false; - } - else - { - gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); - gRememberUser = gSavedSettings.getBOOL("RememberUser"); - show_connect_box = TRUE; - } - - //setup map of datetime strings to codes and slt & local time offset from utc - // *TODO: Does this need to be here? - LLStringOps::setupDatetimeInfo(false); - - // Go to the next startup state - LLStartUp::setStartupState( STATE_BROWSER_INIT ); - return FALSE; - } - - - if (STATE_BROWSER_INIT == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL; - std::string msg = LLTrans::getString("LoginInitializingBrowser"); - set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); - // LLViewerMedia::initBrowser(); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - return FALSE; - } - - - if (STATE_LOGIN_SHOW == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "Initializing Window, show_connect_box = " - << show_connect_box << LL_ENDL; - - // if we've gone backwards in the login state machine, to this state where we show the UI - // AND the debug setting to exit in this case is true, then go ahead and bail quickly - if ( mLoginStatePastUI && gSavedSettings.getBOOL("QuitOnLoginActivated") ) - { - LL_DEBUGS("AppInit") << "taking QuitOnLoginActivated exit" << LL_ENDL; - // no requirement for notification here - just exit - LLAppViewer::instance()->earlyExitNoNotify(); - } - - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - - // Login screen needs menus for preferences, but we can enter - // this startup phase more than once. - if (gLoginMenuBarView == NULL) - { - LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL; - initialize_spellcheck_menu(); - init_menus(); - } - show_release_notes_if_required(); - - if (show_connect_box) - { - LL_DEBUGS("AppInit") << "show_connect_box on" << LL_ENDL; - // Load all the name information out of the login view - // NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't - // show the login view until login_show() is called below. - if (gUserCredential.isNull()) - { - LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL; - gUserCredential = gLoginHandler.initializeLoginInfo(); - } - // Make sure the process dialog doesn't hide things - gViewerWindow->setShowProgress(FALSE); - // Show the login dialog - login_show(); - // connect dialog is already shown, so fill in the names - LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword); - LLPanelLogin::giveFocus(); - - // MAINT-3231 Show first run dialog only for Desura viewer - if (gSavedSettings.getString("sourceid") == "1208_desura") - { - if (gSavedSettings.getBOOL("FirstLoginThisInstall")) - { - LL_INFOS("AppInit") << "FirstLoginThisInstall, calling show_first_run_dialog()" << LL_ENDL; - show_first_run_dialog(); - } - else - { - LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; - } - } - display_startup(); - LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input - } - else - { - LL_DEBUGS("AppInit") << "show_connect_box off, skipping to STATE_LOGIN_CLEANUP" << LL_ENDL; - // skip directly to message template verification - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - } - - gViewerWindow->setNormalControlsVisible( FALSE ); - gLoginMenuBarView->setVisible( TRUE ); - gLoginMenuBarView->setEnabled( TRUE ); - show_debug_menus(); - - // Hide the splash screen - LL_DEBUGS("AppInit") << "Hide the splash screen and show window" << LL_ENDL; - LLSplashScreen::hide(); - // Push our window frontmost - gViewerWindow->getWindow()->show(); - - // DEV-16927. The following code removes errant keystrokes that happen while the window is being - // first made visible. + if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle())) + { + if (FALSE == gSavedSettings.getBOOL("UseMediaPluginsForStreamingAudio")) + { + LL_INFOS("AppInit") << "Using default impl to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(gAudiop->createDefaultStreamingAudioImpl()); + } + + // if the audio engine hasn't set up its own preferred handler for streaming audio + // then set up the generic streaming audio implementation which uses media plugins + if (NULL == gAudiop->getStreamingAudioImpl()) + { + LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); + } + + gAudiop->setMuted(TRUE); + } + else + { + LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; + delete gAudiop; + gAudiop = NULL; + } + } + } + + LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; + + if (LLTimer::knownBadTimer()) + { + LL_WARNS("AppInit") << "Unreliable timers detected (may be bad PCI chipset)!!" << LL_ENDL; + } + + // + // Log on to system + // + if (gUserCredential.isNull()) + { + gUserCredential = gLoginHandler.initializeLoginInfo(); + } + // Previous initializeLoginInfo may have generated user credentials. Re-check them. + if (gUserCredential.isNull()) + { + show_connect_box = TRUE; + } + else if (gSavedSettings.getBOOL("AutoLogin")) + { + // Log into last account + gRememberPassword = true; + gRememberUser = true; + gSavedSettings.setBOOL("RememberPassword", TRUE); + gSavedSettings.setBOOL("RememberUser", TRUE); + show_connect_box = false; + } + else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3) + { + // Console provided login&password + gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); + gRememberUser = gSavedSettings.getBOOL("RememberUser"); + show_connect_box = false; + } + else + { + gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); + gRememberUser = gSavedSettings.getBOOL("RememberUser"); + show_connect_box = TRUE; + } + + //setup map of datetime strings to codes and slt & local time offset from utc + // *TODO: Does this need to be here? + LLStringOps::setupDatetimeInfo(false); + + // Go to the next startup state + LLStartUp::setStartupState( STATE_BROWSER_INIT ); + return FALSE; + } + + + if (STATE_BROWSER_INIT == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingBrowser"); + set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); + display_startup(); + // LLViewerMedia::initBrowser(); + LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + return FALSE; + } + + + if (STATE_LOGIN_SHOW == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "Initializing Window, show_connect_box = " + << show_connect_box << LL_ENDL; + + // if we've gone backwards in the login state machine, to this state where we show the UI + // AND the debug setting to exit in this case is true, then go ahead and bail quickly + if ( mLoginStatePastUI && gSavedSettings.getBOOL("QuitOnLoginActivated") ) + { + LL_DEBUGS("AppInit") << "taking QuitOnLoginActivated exit" << LL_ENDL; + // no requirement for notification here - just exit + LLAppViewer::instance()->earlyExitNoNotify(); + } + + gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + + // Login screen needs menus for preferences, but we can enter + // this startup phase more than once. + if (gLoginMenuBarView == NULL) + { + LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL; + initialize_spellcheck_menu(); + init_menus(); + } + show_release_notes_if_required(); + + if (show_connect_box) + { + LL_DEBUGS("AppInit") << "show_connect_box on" << LL_ENDL; + // Load all the name information out of the login view + // NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't + // show the login view until login_show() is called below. + if (gUserCredential.isNull()) + { + LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL; + gUserCredential = gLoginHandler.initializeLoginInfo(); + } + // Make sure the process dialog doesn't hide things + gViewerWindow->setShowProgress(FALSE); + // Show the login dialog + login_show(); + // connect dialog is already shown, so fill in the names + LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword); + LLPanelLogin::giveFocus(); + + // MAINT-3231 Show first run dialog only for Desura viewer + if (gSavedSettings.getString("sourceid") == "1208_desura") + { + if (gSavedSettings.getBOOL("FirstLoginThisInstall")) + { + LL_INFOS("AppInit") << "FirstLoginThisInstall, calling show_first_run_dialog()" << LL_ENDL; + show_first_run_dialog(); + } + else + { + LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; + } + } + display_startup(); + LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input + } + else + { + LL_DEBUGS("AppInit") << "show_connect_box off, skipping to STATE_LOGIN_CLEANUP" << LL_ENDL; + // skip directly to message template verification + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + } + + gViewerWindow->setNormalControlsVisible( FALSE ); + gLoginMenuBarView->setVisible( TRUE ); + gLoginMenuBarView->setEnabled( TRUE ); + show_debug_menus(); + + // Hide the splash screen + LL_DEBUGS("AppInit") << "Hide the splash screen and show window" << LL_ENDL; + LLSplashScreen::hide(); + // Push our window frontmost + gViewerWindow->getWindow()->show(); + + // DEV-16927. The following code removes errant keystrokes that happen while the window is being + // first made visible. #ifdef _WIN32 LL_DEBUGS("AppInit") << "Processing PeekMessage" << LL_ENDL; - MSG msg; - while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ) + MSG msg; + while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ) { } LL_DEBUGS("AppInit") << "PeekMessage processed" << LL_ENDL; #endif display_startup(); timeout.reset(); - return FALSE; - } - - if (STATE_LOGIN_WAIT == LLStartUp::getStartupState()) - { - // when we get to this state, we've already been past the login UI - // (possiblely automatically) - flag this so we can test in the - // STATE_LOGIN_SHOW state if we've gone backwards - mLoginStatePastUI = true; - - // Don't do anything. Wait for the login view to call the login_callback, - // which will push us to the next state. - - // display() function will be the one to run display_startup() - // Sleep so we don't spin the CPU - ms_sleep(1); - return FALSE; - } - - if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) - { - // Post login screen, we should see if any settings have changed that may - // require us to either start/stop or change the socks proxy. As various communications - // past this point may require the proxy to be up. - if (!LLStartUp::startLLProxy()) - { - // Proxy start up failed, we should now bail the state machine - // startLLProxy() will have reported an error to the user - // already, so we just go back to the login screen. The user - // could then change the preferences to fix the issue. - - LLStartUp::setStartupState(STATE_LOGIN_SHOW); - return FALSE; - } - - // reset the values that could have come in from a slurl - // DEV-42215: Make sure they're not empty -- gUserCredential - // might already have been set from gSavedSettings, and it's too bad - // to overwrite valid values with empty strings. - - if (show_connect_box) - { - // TODO if not use viewer auth - // Load all the name information out of the login view - LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword); - // end TODO - - // HACK: Try to make not jump on login - gKeyboard->resetKeys(); - } - - // when we get to this state, we've already been past the login UI - // (possiblely automatically) - flag this so we can test in the - // STATE_LOGIN_SHOW state if we've gone backwards - mLoginStatePastUI = true; - - // save the credentials - std::string userid = "unknown"; + return FALSE; + } + + if (STATE_LOGIN_WAIT == LLStartUp::getStartupState()) + { + // when we get to this state, we've already been past the login UI + // (possiblely automatically) - flag this so we can test in the + // STATE_LOGIN_SHOW state if we've gone backwards + mLoginStatePastUI = true; + + // Don't do anything. Wait for the login view to call the login_callback, + // which will push us to the next state. + + // display() function will be the one to run display_startup() + // Sleep so we don't spin the CPU + ms_sleep(1); + return FALSE; + } + + if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) + { + // Post login screen, we should see if any settings have changed that may + // require us to either start/stop or change the socks proxy. As various communications + // past this point may require the proxy to be up. + if (!LLStartUp::startLLProxy()) + { + // Proxy start up failed, we should now bail the state machine + // startLLProxy() will have reported an error to the user + // already, so we just go back to the login screen. The user + // could then change the preferences to fix the issue. + + LLStartUp::setStartupState(STATE_LOGIN_SHOW); + return FALSE; + } + + // reset the values that could have come in from a slurl + // DEV-42215: Make sure they're not empty -- gUserCredential + // might already have been set from gSavedSettings, and it's too bad + // to overwrite valid values with empty strings. + + if (show_connect_box) + { + // TODO if not use viewer auth + // Load all the name information out of the login view + LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword); + // end TODO + + // HACK: Try to make not jump on login + gKeyboard->resetKeys(); + } + + // when we get to this state, we've already been past the login UI + // (possiblely automatically) - flag this so we can test in the + // STATE_LOGIN_SHOW state if we've gone backwards + mLoginStatePastUI = true; + + // save the credentials + std::string userid = "unknown"; if (gUserCredential.notNull()) { userid = gUserCredential->userID(); @@ -927,24 +927,24 @@ bool idle_startup() gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword); } } - gSavedSettings.setBOOL("RememberPassword", gRememberPassword); - gSavedSettings.setBOOL("RememberUser", gRememberUser); - LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL; - gDebugInfo["LoginName"] = userid; - - // create necessary directories - // *FIX: these mkdir's should error check - gDirUtilp->setLindenUserDir(userid); - LLFile::mkdir(gDirUtilp->getLindenUserDir()); - - // As soon as directories are ready initialize notification storages - if (!LLPersistentNotificationStorage::instanceExists()) - { - // check existance since this part of code can be reached - // twice due to login failures - LLPersistentNotificationStorage::initParamSingleton(); - LLDoNotDisturbNotificationStorage::initParamSingleton(); - } + gSavedSettings.setBOOL("RememberPassword", gRememberPassword); + gSavedSettings.setBOOL("RememberUser", gRememberUser); + LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL; + gDebugInfo["LoginName"] = userid; + + // create necessary directories + // *FIX: these mkdir's should error check + gDirUtilp->setLindenUserDir(userid); + LLFile::mkdir(gDirUtilp->getLindenUserDir()); + + // As soon as directories are ready initialize notification storages + if (!LLPersistentNotificationStorage::instanceExists()) + { + // check existance since this part of code can be reached + // twice due to login failures + LLPersistentNotificationStorage::initParamSingleton(); + LLDoNotDisturbNotificationStorage::initParamSingleton(); + } else { // reinitialize paths in case user switched grids or accounts @@ -952,152 +952,152 @@ bool idle_startup() LLDoNotDisturbNotificationStorage::getInstance()->reset(); } - // Set PerAccountSettingsFile to the default value. - std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")); - gSavedSettings.setString("PerAccountSettingsFile", settings_per_account); - gDebugInfo["PerAccountSettingsFilename"] = settings_per_account; - - // Note: can't store warnings files per account because some come up before login - - // Overwrite default user settings with user settings - LLAppViewer::instance()->loadSettingsFromDirectory("Account"); - - // Convert 'LogInstantMessages' into 'KeepConversationLogTranscripts' for backward compatibility (CHUI-743). - LLControlVariablePtr logInstantMessagesControl = gSavedPerAccountSettings.getControl("LogInstantMessages"); - if (logInstantMessagesControl.notNull()) - { - gSavedPerAccountSettings.setS32("KeepConversationLogTranscripts", logInstantMessagesControl->getValue() ? 2 : 1); - } - - // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation - // and startup time is close enough if we don't have a real value. - if (gSavedPerAccountSettings.getU32("LastLogoff") == 0) - { - gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); - } - - //Default the path if one isn't set. - // *NOTE: unable to check variable differ from "InstantMessageLogPath" because it was - // provided in pre 2.0 viewer. See EXT-6661 - if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty()) - { - gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir()); - gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir()); - } - else - { - gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - } - gDirUtilp->setPerAccountChatLogsDir(userid); - - LLFile::mkdir(gDirUtilp->getChatLogsDir()); - LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); - - if (show_connect_box) - { - LLSLURL slurl; - //LLPanelLogin::closePanel(); - } - - - // Load URL History File - LLURLHistory::loadFile("url_history.xml"); - // Load location history - LLLocationHistory::getInstance()->load(); - - // Load Avatars icons cache - LLAvatarIconIDCache::getInstance()->load(); - - LLRenderMuteList::getInstance()->loadFromFile(); - - //------------------------------------------------- - // Handle startup progress screen - //------------------------------------------------- - - // on startup the user can request to go to their home, - // their last location, or some URL "-url //sim/x/y[/z]" - // All accounts have both a home and a last location, and we don't support - // more locations than that. Choose the appropriate one. JC - switch (LLStartUp::getStartSLURL().getType()) - { - case LLSLURL::LOCATION: - agent_location_id = START_LOCATION_ID_URL; - break; - case LLSLURL::LAST_LOCATION: - agent_location_id = START_LOCATION_ID_LAST; - break; - default: - agent_location_id = START_LOCATION_ID_HOME; - break; - } - - gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); - - // Display the startup progress bar. - gViewerWindow->initTextures(agent_location_id); - gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit")); - - gViewerWindow->revealIntroPanel(); - - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); - - return FALSE; - } - - if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState()) - { - gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId(); - - // Update progress status and the display loop. - auth_desc = LLTrans::getString("LoginInProgress"); - set_startup_status(progress, auth_desc, auth_message); - progress += 0.02f; - display_startup(); - - // Setting initial values... - LLLoginInstance* login = LLLoginInstance::getInstance(); - login->setNotificationsInterface(LLNotifications::getInstance()); - - login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); - login->setLastExecEvent(gLastExecEvent); - login->setLastExecDuration(gLastExecDuration); - - // This call to LLLoginInstance::connect() starts the - // authentication process. - login->connect(gUserCredential); - - LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK ); - return FALSE; - } - - if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState()) - { - // If we get here we have gotten past the potential stall - // in curl, so take "may appear frozen" out of progress bar. JC - auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); - set_startup_status(progress, auth_desc, auth_message); - - LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); - return FALSE; - } - - if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) - { - // Generic failure message - std::ostringstream emsg; - emsg << LLTrans::getString("LoginFailedHeader") << "\n"; - if(LLLoginInstance::getInstance()->authFailure()) - { - LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): " - << LLLoginInstance::getInstance()->getResponse() << LL_ENDL; - LLSD response = LLLoginInstance::getInstance()->getResponse(); - // Still have error conditions that may need some - // sort of handling - dig up specific message - std::string reason_response = response["reason"]; - std::string message_response = response["message"]; - std::string message_id = response["message_id"]; - std::string message; // actual string to show the user + // Set PerAccountSettingsFile to the default value. + std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")); + gSavedSettings.setString("PerAccountSettingsFile", settings_per_account); + gDebugInfo["PerAccountSettingsFilename"] = settings_per_account; + + // Note: can't store warnings files per account because some come up before login + + // Overwrite default user settings with user settings + LLAppViewer::instance()->loadSettingsFromDirectory("Account"); + + // Convert 'LogInstantMessages' into 'KeepConversationLogTranscripts' for backward compatibility (CHUI-743). + LLControlVariablePtr logInstantMessagesControl = gSavedPerAccountSettings.getControl("LogInstantMessages"); + if (logInstantMessagesControl.notNull()) + { + gSavedPerAccountSettings.setS32("KeepConversationLogTranscripts", logInstantMessagesControl->getValue() ? 2 : 1); + } + + // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation + // and startup time is close enough if we don't have a real value. + if (gSavedPerAccountSettings.getU32("LastLogoff") == 0) + { + gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); + } + + //Default the path if one isn't set. + // *NOTE: unable to check variable differ from "InstantMessageLogPath" because it was + // provided in pre 2.0 viewer. See EXT-6661 + if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty()) + { + gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir()); + gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir()); + } + else + { + gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + } + gDirUtilp->setPerAccountChatLogsDir(userid); + + LLFile::mkdir(gDirUtilp->getChatLogsDir()); + LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); + + if (show_connect_box) + { + LLSLURL slurl; + //LLPanelLogin::closePanel(); + } + + + // Load URL History File + LLURLHistory::loadFile("url_history.xml"); + // Load location history + LLLocationHistory::getInstance()->load(); + + // Load Avatars icons cache + LLAvatarIconIDCache::getInstance()->load(); + + LLRenderMuteList::getInstance()->loadFromFile(); + + //------------------------------------------------- + // Handle startup progress screen + //------------------------------------------------- + + // on startup the user can request to go to their home, + // their last location, or some URL "-url //sim/x/y[/z]" + // All accounts have both a home and a last location, and we don't support + // more locations than that. Choose the appropriate one. JC + switch (LLStartUp::getStartSLURL().getType()) + { + case LLSLURL::LOCATION: + agent_location_id = START_LOCATION_ID_URL; + break; + case LLSLURL::LAST_LOCATION: + agent_location_id = START_LOCATION_ID_LAST; + break; + default: + agent_location_id = START_LOCATION_ID_HOME; + break; + } + + gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); + + // Display the startup progress bar. + gViewerWindow->initTextures(agent_location_id); + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit")); + + gViewerWindow->revealIntroPanel(); + + LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); + + return FALSE; + } + + if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState()) + { + gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId(); + + // Update progress status and the display loop. + auth_desc = LLTrans::getString("LoginInProgress"); + set_startup_status(progress, auth_desc, auth_message); + progress += 0.02f; + display_startup(); + + // Setting initial values... + LLLoginInstance* login = LLLoginInstance::getInstance(); + login->setNotificationsInterface(LLNotifications::getInstance()); + + login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); + login->setLastExecEvent(gLastExecEvent); + login->setLastExecDuration(gLastExecDuration); + + // This call to LLLoginInstance::connect() starts the + // authentication process. + login->connect(gUserCredential); + + LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK ); + return FALSE; + } + + if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState()) + { + // If we get here we have gotten past the potential stall + // in curl, so take "may appear frozen" out of progress bar. JC + auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); + set_startup_status(progress, auth_desc, auth_message); + + LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); + return FALSE; + } + + if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) + { + // Generic failure message + std::ostringstream emsg; + emsg << LLTrans::getString("LoginFailedHeader") << "\n"; + if(LLLoginInstance::getInstance()->authFailure()) + { + LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): " + << LLLoginInstance::getInstance()->getResponse() << LL_ENDL; + LLSD response = LLLoginInstance::getInstance()->getResponse(); + // Still have error conditions that may need some + // sort of handling - dig up specific message + std::string reason_response = response["reason"]; + std::string message_response = response["message"]; + std::string message_id = response["message_id"]; + std::string message; // actual string to show the user bool localized_by_id = false; if(!message_id.empty()) @@ -1130,63 +1130,63 @@ bool idle_startup() } if(!localized_by_id && !message_response.empty()) - { - // *HACK: "no_inventory_host" sent as the message itself. - // Remove this clause when server is sending message_id as well. - message = LLAgent::sTeleportErrorMessages[ message_response ]; - } - - if (message.empty()) - { - // Fallback to server-supplied string; necessary since server - // may add strings that this viewer is not yet aware of - message = message_response; - } - - emsg << message; - - - if(reason_response == "key") - { - // Couldn't login because user/password is wrong - // Clear the credential - gUserCredential->clearAuthenticator(); - } - - if(reason_response == "update" - || reason_response == "optional") - { - // In the case of a needed update, quit. - // Its either downloading or declined. - // If optional was skipped this case shouldn't - // be reached. - - LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL; - LLLoginInstance::getInstance()->disconnect(); - LLAppViewer::instance()->forceQuit(); - } - else - { - if (reason_response != "tos" && reason_response != "mfa_challenge") - { - // Don't pop up a notification in the TOS or MFA cases because - // the specialized floater has already scolded the user. - std::string error_code; - if(response.has("errorcode")) - { - error_code = response["errorcode"].asString(); - } - if ((reason_response == "CURLError") && - (error_code == "SSL_CACERT" || error_code == "SSL_PEER_CERTIFICATE") && - response.has("certificate")) - { - // This was a certificate error, so grab the certificate - // and throw up the appropriate dialog. - LLPointer certificate; - try - { - certificate = gSecAPIHandler->getCertificate(response["certificate"]); - } + { + // *HACK: "no_inventory_host" sent as the message itself. + // Remove this clause when server is sending message_id as well. + message = LLAgent::sTeleportErrorMessages[ message_response ]; + } + + if (message.empty()) + { + // Fallback to server-supplied string; necessary since server + // may add strings that this viewer is not yet aware of + message = message_response; + } + + emsg << message; + + + if(reason_response == "key") + { + // Couldn't login because user/password is wrong + // Clear the credential + gUserCredential->clearAuthenticator(); + } + + if(reason_response == "update" + || reason_response == "optional") + { + // In the case of a needed update, quit. + // Its either downloading or declined. + // If optional was skipped this case shouldn't + // be reached. + + LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL; + LLLoginInstance::getInstance()->disconnect(); + LLAppViewer::instance()->forceQuit(); + } + else + { + if (reason_response != "tos" && reason_response != "mfa_challenge") + { + // Don't pop up a notification in the TOS or MFA cases because + // the specialized floater has already scolded the user. + std::string error_code; + if(response.has("errorcode")) + { + error_code = response["errorcode"].asString(); + } + if ((reason_response == "CURLError") && + (error_code == "SSL_CACERT" || error_code == "SSL_PEER_CERTIFICATE") && + response.has("certificate")) + { + // This was a certificate error, so grab the certificate + // and throw up the appropriate dialog. + LLPointer certificate; + try + { + certificate = gSecAPIHandler->getCertificate(response["certificate"]); + } catch (LLCertException &cert_exception) { LL_WARNS("LLStartup", "SECAPI") << "Caught " << cert_exception.what() << " certificate expception on getCertificate("<< response["certificate"] << ")" << LL_ENDL; @@ -1200,1229 +1200,1229 @@ bool idle_startup() gSavedSettings.setBOOL("AutoLogin", FALSE); show_connect_box = true; } - if(certificate) - { - LLSD args = transform_cert_args(certificate); - - if(error_code == "SSL_CACERT") - { - // if we are handling an untrusted CA, throw up the dialog - // with the 'trust this CA' button. - LLNotificationsUtil::add("TrustCertificateError", args, response, - trust_cert_done); - - show_connect_box = true; - } - else - { - // the certificate exception returns a unique string for each type of exception. - // we grab this string via the LLUserAuth object, and use that to grab the localized - // string. - args["REASON"] = LLTrans::getString(message_response); - - LLNotificationsUtil::add("GeneralCertificateError", args, response, - general_cert_done); - - reset_login(); - gSavedSettings.setBOOL("AutoLogin", FALSE); - show_connect_box = true; - - } - - } - } + if(certificate) + { + LLSD args = transform_cert_args(certificate); + + if(error_code == "SSL_CACERT") + { + // if we are handling an untrusted CA, throw up the dialog + // with the 'trust this CA' button. + LLNotificationsUtil::add("TrustCertificateError", args, response, + trust_cert_done); + + show_connect_box = true; + } + else + { + // the certificate exception returns a unique string for each type of exception. + // we grab this string via the LLUserAuth object, and use that to grab the localized + // string. + args["REASON"] = LLTrans::getString(message_response); + + LLNotificationsUtil::add("GeneralCertificateError", args, response, + general_cert_done); + + reset_login(); + gSavedSettings.setBOOL("AutoLogin", FALSE); + show_connect_box = true; + + } + + } + } else if (reason_response == "BadType") { LLNotificationsUtil::add("LoginFailedToParse", LLSD(), LLSD(), login_alert_done); } - else if (!message.empty()) - { - // This wasn't a certificate error, so throw up the normal - // notificatioin message. - LLSD args; - args["ERROR_MESSAGE"] = emsg.str(); - LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; - LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); - } - } - transition_back_to_login_panel(emsg.str()); - show_connect_box = true; - } - } - else if(LLLoginInstance::getInstance()->authSuccess()) - { - if(process_login_success_response()) - { - // Pass the user information to the voice chat server interface. - LLVoiceClient::getInstance()->userAuthorized(gUserCredential->userID(), gAgentID); - // create the default proximal channel - LLVoiceChannel::initClass(); - LLStartUp::setStartupState( STATE_WORLD_INIT); - LLTrace::get_frame_recording().reset(); - } - else - { - LLSD args; - args["ERROR_MESSAGE"] = emsg.str(); - LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; - LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); - transition_back_to_login_panel(emsg.str()); - show_connect_box = true; - return FALSE; - } - } - return FALSE; - } - - //--------------------------------------------------------------------- - // World Init - //--------------------------------------------------------------------- - if (STATE_WORLD_INIT == LLStartUp::getStartupState()) - { - set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); - display_startup(); - // We should have an agent id by this point. - llassert(!(gAgentID == LLUUID::null)); - - // Finish agent initialization. (Requires gSavedSettings, builds camera) - gAgent.init(); - display_startup(); - gAgentCamera.init(); - display_startup(); - display_startup(); - - // Since we connected, save off the settings so the user doesn't have to - // type the name/password again if we crash. - gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - LLUIColorTable::instance().saveUserSettings(); - - display_startup(); - - // - // Initialize classes w/graphics stuff. - // - LLViewerStatsRecorder::instance(); // Since textures work in threads - LLSurface::initClasses(); - display_startup(); - - display_startup(); - - LLDrawable::initClass(); - display_startup(); - - // init the shader managers - LLPostProcess::initClass(); - display_startup(); + else if (!message.empty()) + { + // This wasn't a certificate error, so throw up the normal + // notificatioin message. + LLSD args; + args["ERROR_MESSAGE"] = emsg.str(); + LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); + } + } + transition_back_to_login_panel(emsg.str()); + show_connect_box = true; + } + } + else if(LLLoginInstance::getInstance()->authSuccess()) + { + if(process_login_success_response()) + { + // Pass the user information to the voice chat server interface. + LLVoiceClient::getInstance()->userAuthorized(gUserCredential->userID(), gAgentID); + // create the default proximal channel + LLVoiceChannel::initClass(); + LLStartUp::setStartupState( STATE_WORLD_INIT); + LLTrace::get_frame_recording().reset(); + } + else + { + LLSD args; + args["ERROR_MESSAGE"] = emsg.str(); + LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); + transition_back_to_login_panel(emsg.str()); + show_connect_box = true; + return FALSE; + } + } + return FALSE; + } + + //--------------------------------------------------------------------- + // World Init + //--------------------------------------------------------------------- + if (STATE_WORLD_INIT == LLStartUp::getStartupState()) + { + set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); + display_startup(); + // We should have an agent id by this point. + llassert(!(gAgentID == LLUUID::null)); + + // Finish agent initialization. (Requires gSavedSettings, builds camera) + gAgent.init(); + display_startup(); + gAgentCamera.init(); + display_startup(); + display_startup(); + + // Since we connected, save off the settings so the user doesn't have to + // type the name/password again if we crash. + gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); + LLUIColorTable::instance().saveUserSettings(); + + display_startup(); + + // + // Initialize classes w/graphics stuff. + // + LLViewerStatsRecorder::instance(); // Since textures work in threads + LLSurface::initClasses(); + display_startup(); + + display_startup(); + + LLDrawable::initClass(); + display_startup(); + + // init the shader managers + LLPostProcess::initClass(); + display_startup(); + + LLAvatarAppearance::initClass("avatar_lad.xml","avatar_skeleton.xml"); + display_startup(); + + LLViewerObject::initVOClasses(); + display_startup(); + + // Initialize all our tools. Must be done after saved settings loaded. + // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton. + LLToolMgr::getInstance()->initTools(); + display_startup(); + + // Pre-load floaters, like the world map, that are slow to spawn + // due to XML complexity. + gViewerWindow->initWorldUI(); + + display_startup(); + + // This is where we used to initialize gWorldp. Original comment said: + // World initialization must be done after above window init + + // User might have overridden far clip + LLWorld::getInstance()->setLandFarClip(gAgentCamera.mDrawDistance); + display_startup(); + // Before we create the first region, we need to set the agent's mOriginGlobal + // This is necessary because creating objects before this is set will result in a + // bad mPositionAgent cache. + + gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); + display_startup(); + + LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); + display_startup(); + + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); + LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; + + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == " + << gFirstSimSeedCap << LL_ENDL; + regionp->setSeedCapability(gFirstSimSeedCap); + LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; + display_startup(); + // Set agent's initial region to be the one we just created. + gAgent.setRegion(regionp); + display_startup(); + // Set agent's initial position, which will be read by LLVOAvatar when the avatar + // object is created. I think this must be done after setting the region. JC + gAgent.setPositionAgent(agent_start_position_region); + + display_startup(); + LLStartUp::initExperiences(); + + display_startup(); + + // If logging should be enebled, turns it on and loads history from disk + // Note: does not happen on init of singleton because preferences can use + // this instance without logging in + LLConversationLog::getInstance()->initLoggingState(); + + LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); + + return FALSE; + } + + + //--------------------------------------------------------------------- + // Load QuickTime/GStreamer and other multimedia engines, can be slow. + // Do it while we're waiting on the network for our seed capability. JC + //--------------------------------------------------------------------- + if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState()) + { + LLStartUp::multimediaInit(); + LLStartUp::setStartupState( STATE_FONT_INIT ); + display_startup(); + return FALSE; + } + + // Loading fonts takes several seconds + if (STATE_FONT_INIT == LLStartUp::getStartupState()) + { + LLStartUp::fontInit(); + LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT ); + display_startup(); + return FALSE; + } + + //--------------------------------------------------------------------- + // Wait for Seed Cap Grant + //--------------------------------------------------------------------- + if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); + if (regionp->capabilitiesReceived()) + { + LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); + } + else if (regionp->capabilitiesError()) + { + LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + else + { + U32 num_retries = regionp->getNumSeedCapRetries(); + if (num_retries > MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT) + { + LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + else if (num_retries > 0) + { + LLStringUtil::format_map_t args; + args["[NUMBER]"] = llformat("%d", num_retries + 1); + set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD.c_str()); + } + else + { + set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str()); + } + } + display_startup(); + return FALSE; + } + + + //--------------------------------------------------------------------- + // Seed Capability Granted + // no newMessage calls should happen before this point + //--------------------------------------------------------------------- + if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState()) + { + display_startup(); + + // These textures are not warrantied to be cached, so needs + // to hapen with caps granted + gTextureList.doPrefetchImages(); + + // will init images, should be done with caps, but before gSky.init() + LLEnvironment::getInstance()->initSingleton(); + + display_startup(); + update_texture_fetch(); + display_startup(); + + if ( gViewerWindow != NULL) + { // This isn't the first logon attempt, so show the UI + gViewerWindow->setNormalControlsVisible( TRUE ); + } + gLoginMenuBarView->setVisible( FALSE ); + gLoginMenuBarView->setEnabled( FALSE ); + display_startup(); + + // direct logging to the debug console's line buffer + LLError::logToFixedBuffer(gDebugView->mDebugConsolep); + display_startup(); + + // set initial visibility of debug console + gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); + display_startup(); + + // + // Set message handlers + // + LL_INFOS("AppInit") << "Initializing communications..." << LL_ENDL; + + // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted + register_viewer_callbacks(gMessageSystem); + display_startup(); + + // Debugging info parameters + gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms + display_startup(); + + #ifndef LL_RELEASE_FOR_DOWNLOAD + gMessageSystem->setTimeDecodes( TRUE ); // Time the decode of each msg + gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode + #endif + display_startup(); + + gXferManager->registerCallbacks(gMessageSystem); + display_startup(); + + LLStartUp::initNameCache(); + display_startup(); + + // update the voice settings *after* gCacheName initialization + // so that we can construct voice UI that relies on the name cache + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->updateSettings(); + } + display_startup(); + + // create a container's instance for start a controlling conversation windows + // by the voice's events + LLFloaterIMContainer::getInstance(); + if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2) + { + LLViewerParcelAskPlay::getInstance()->loadSettings(); + } + + gAgent.addRegionChangedCallback(boost::bind(&LLPerfStats::StatsRecorder::clearStats)); + + // *Note: this is where gWorldMap used to be initialized. + + // register null callbacks for audio until the audio system is initialized + gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL); + gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL); + display_startup(); + + //reset statistics + LLViewerStats::instance().resetStats(); + + display_startup(); + // + // Set up region and surface defaults + // + + + // Sets up the parameters for the first simulator + + LL_DEBUGS("AppInit") << "Initializing camera..." << LL_ENDL; + gFrameTime = totalTime(); + F32Seconds last_time = gFrameTimeSeconds; + gFrameTimeSeconds = (gFrameTime - gStartTime); + + gFrameIntervalSeconds = gFrameTimeSeconds - last_time; + if (gFrameIntervalSeconds < 0.f) + { + gFrameIntervalSeconds = 0.f; + } + + // Make sure agent knows correct aspect ratio + // FOV limits depend upon aspect ratio so this needs to happen before initializing the FOV below + LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWorldViewHeightRaw()); + LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio()); + // Initialize FOV + LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle")); + display_startup(); + + // Move agent to starting location. The position handed to us by + // the space server is in global coordinates, but the agent frame + // is in region local coordinates. Therefore, we need to adjust + // the coordinates handed to us to fit in the local region. + + gAgent.setPositionAgent(agent_start_position_region); + gAgent.resetAxes(gAgentStartLookAt); + gAgentCamera.stopCameraAnimation(); + gAgentCamera.resetCamera(); + display_startup(); + + // Initialize global class data needed for surfaces (i.e. textures) + LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; + // Initialize all of the viewer object classes for the first time (doing things like texture fetches. + LLGLState::checkStates(); + + gSky.init(); + + LLGLState::checkStates(); + + display_startup(); + + LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL; + // For all images pre-loaded into viewer cache, init + // priorities and fetching using decodeAllImages. + // Most of the fetching and decoding likely to be done + // by update_texture_fetch() later, while viewer waits. + // + // Need to do this AFTER we init the sky + const S32 DECODE_TIME_SEC = 2; + for (int i = 0; i < DECODE_TIME_SEC; i++) + { + F32 frac = (F32)i / (F32)DECODE_TIME_SEC; + set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD); + display_startup(); + gTextureList.decodeAllImages(1.f); + } + LLStartUp::setStartupState( STATE_WORLD_WAIT ); + + display_startup(); + + // JC - Do this as late as possible to increase likelihood Purify + // will run. + LLMessageSystem* msg = gMessageSystem; + if (!msg->mOurCircuitCode) + { + LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL; + } + + gUseCircuitCallbackCalled = false; + + msg->enableCircuit(gFirstSim, TRUE); + // now, use the circuit info to tell simulator about us! + LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL; + msg->newMessageFast(_PREHASH_UseCircuitCode); + msg->nextBlockFast(_PREHASH_CircuitCode); + msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); + msg->sendReliable( + gFirstSim, + gSavedSettings.getS32("UseCircuitCodeMaxRetries"), + FALSE, + (F32Seconds)gSavedSettings.getF32("UseCircuitCodeTimeout"), + use_circuit_callback, + NULL); + + timeout.reset(); + display_startup(); + + return FALSE; + } + + //--------------------------------------------------------------------- + // World Wait + //--------------------------------------------------------------------- + if(STATE_WORLD_WAIT == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "Waiting for simulator ack...." << LL_ENDL; + set_startup_status(0.59f, LLTrans::getString("LoginWaitingForRegionHandshake"), gAgent.mMOTD); + if(gGotUseCircuitCodeAck) + { + LLStartUp::setStartupState( STATE_AGENT_SEND ); + } + pump_idle_startup_network(); + return FALSE; + } + + //--------------------------------------------------------------------- + // Agent Send + //--------------------------------------------------------------------- + if (STATE_AGENT_SEND == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "Connecting to region..." << LL_ENDL; + set_startup_status(0.60f, LLTrans::getString("LoginConnectingToRegion"), gAgent.mMOTD); + display_startup(); + // register with the message system so it knows we're + // expecting this message + LLMessageSystem* msg = gMessageSystem; + msg->setHandlerFuncFast( + _PREHASH_AgentMovementComplete, + process_agent_movement_complete); + LLViewerRegion* regionp = gAgent.getRegion(); + if(regionp) + { + send_complete_agent_movement(regionp->getHost()); + gAssetStorage->setUpstream(regionp->getHost()); + gCacheName->setUpstream(regionp->getHost()); + } + display_startup(); + + // Create login effect + // But not on first login, because you can't see your avatar then + if (!gAgent.isFirstLogin()) + { + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal(gAgent.getPositionGlobal()); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + LLHUDManager::getInstance()->sendEffects(); + } + + LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT + + timeout.reset(); + display_startup(); + return FALSE; + } + + //--------------------------------------------------------------------- + // Agent Wait + //--------------------------------------------------------------------- + if (STATE_AGENT_WAIT == LLStartUp::getStartupState()) + { + { + LockMessageChecker lmc(gMessageSystem); + while (lmc.checkAllMessages(gFrameCount, gServicePump)) + { + if (gAgentMovementCompleted) + { + // Sometimes we have more than one message in the + // queue. break out of this loop and continue + // processing. If we don't, then this could skip one + // or more login steps. + break; + } + else + { + LL_DEBUGS("AppInit") << "Awaiting AvatarInitComplete, got " + << gMessageSystem->getMessageName() << LL_ENDL; + } + display_startup(); + } + lmc.processAcks(); + } + + display_startup(); + + if (gAgentMovementCompleted) + { + LLStartUp::setStartupState( STATE_INVENTORY_SEND ); + } + display_startup(); + + if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) + { + LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + return FALSE; + } + + //--------------------------------------------------------------------- + // Inventory Send + //--------------------------------------------------------------------- + if (STATE_INVENTORY_SEND == LLStartUp::getStartupState()) + { + LL_PROFILE_ZONE_NAMED("State inventory send") + display_startup(); + + // request mute list + LL_INFOS() << "Requesting Mute List" << LL_ENDL; + LLMuteList::getInstance()->requestFromServer(gAgent.getID()); + + // Get L$ and ownership credit information + LL_INFOS() << "Requesting Money Balance" << LL_ENDL; + LLStatusBar::sendMoneyBalanceRequest(); + + display_startup(); + + // Inform simulator of our language preference + LLAgentLanguage::update(); + + display_startup(); + // unpack thin inventory + LLSD response = LLLoginInstance::getInstance()->getResponse(); + //bool dump_buffer = false; + + LLSD inv_lib_root = response["inventory-lib-root"]; + if(inv_lib_root.isDefined()) + { + // should only be one + LLSD id = inv_lib_root[0]["folder_id"]; + if(id.isDefined()) + { + gInventory.setLibraryRootFolderID(id.asUUID()); + } + } + display_startup(); + + LLSD inv_lib_owner = response["inventory-lib-owner"]; + if(inv_lib_owner.isDefined()) + { + // should only be one + LLSD id = inv_lib_owner[0]["agent_id"]; + if(id.isDefined()) + { + gInventory.setLibraryOwnerID(LLUUID(id.asUUID())); + } + } + display_startup(); + LLStartUp::setStartupState(STATE_INVENTORY_SKEL); + display_startup(); + return FALSE; + } + + if (STATE_INVENTORY_SKEL == LLStartUp::getStartupState()) + { + LL_PROFILE_ZONE_NAMED("State inventory load skeleton") + + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + LLSD inv_skel_lib = response["inventory-skel-lib"]; + if (inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull()) + { + LL_PROFILE_ZONE_NAMED("load library inv") + if (!gInventory.loadSkeleton(inv_skel_lib, gInventory.getLibraryOwnerID())) + { + LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; + } + } + display_startup(); + + LLSD inv_skeleton = response["inventory-skeleton"]; + if (inv_skeleton.isDefined()) + { + LL_PROFILE_ZONE_NAMED("load personal inv") + if (!gInventory.loadSkeleton(inv_skeleton, gAgent.getID())) + { + LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL; + } + } + display_startup(); + LLStartUp::setStartupState(STATE_INVENTORY_SEND2); + display_startup(); + return FALSE; + } + + if (STATE_INVENTORY_SEND2 == LLStartUp::getStartupState()) + { + LL_PROFILE_ZONE_NAMED("State inventory send2") + + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + LLSD inv_basic = response["inventory-basic"]; + if(inv_basic.isDefined()) + { + LL_INFOS() << "Basic inventory root folder id is " << inv_basic["folder_id"] << LL_ENDL; + } + + LLSD buddy_list = response["buddy-list"]; + if(buddy_list.isDefined()) + { + LLAvatarTracker::buddy_map_t list; + LLUUID agent_id; + S32 has_rights = 0, given_rights = 0; + for(LLSD::array_const_iterator it = buddy_list.beginArray(), + end = buddy_list.endArray(); it != end; ++it) + { + LLSD buddy_id = (*it)["buddy_id"]; + if(buddy_id.isDefined()) + { + agent_id = buddy_id.asUUID(); + } + + LLSD buddy_rights_has = (*it)["buddy_rights_has"]; + if(buddy_rights_has.isDefined()) + { + has_rights = buddy_rights_has.asInteger(); + } + + LLSD buddy_rights_given = (*it)["buddy_rights_given"]; + if(buddy_rights_given.isDefined()) + { + given_rights = buddy_rights_given.asInteger(); + } + + list[agent_id] = new LLRelationship(given_rights, has_rights, false); + } + LLAvatarTracker::instance().addBuddyList(list); + display_startup(); + } + + bool show_hud = false; + LLSD tutorial_setting = response["tutorial_setting"]; + if(tutorial_setting.isDefined()) + { + for(LLSD::array_const_iterator it = tutorial_setting.beginArray(), + end = tutorial_setting.endArray(); it != end; ++it) + { + LLSD tutorial_url = (*it)["tutorial_url"]; + if(tutorial_url.isDefined()) + { + // Tutorial floater will append language code + gSavedSettings.setString("TutorialURL", tutorial_url.asString()); + } + + // For Viewer 2.0 we are not using the web-based tutorial + // If we reverse that decision, put this code back and use + // login.cgi to send a different URL with content that matches + // the Viewer 2.0 UI. + //LLSD use_tutorial = (*it)["use_tutorial"]; + //if(use_tutorial.asString() == "true") + //{ + // show_hud = true; + //} + } + } + display_startup(); + + // Either we want to show tutorial because this is the first login + // to a Linden Help Island or the user quit with the tutorial + // visible. JC + if (show_hud || gSavedSettings.getBOOL("ShowTutorial")) + { + LLFloaterReg::showInstance("hud", LLSD(), FALSE); + } + display_startup(); + + LLSD event_notifications = response["event_notifications"]; + if(event_notifications.isDefined()) + { + gEventNotifier.load(event_notifications); + } + display_startup(); + + LLSD classified_categories = response["classified_categories"]; + if(classified_categories.isDefined()) + { + LLClassifiedInfo::loadCategories(classified_categories); + } + display_startup(); + + // This method MUST be called before gInventory.findCategoryUUIDForType because of + // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap. + gInventory.buildParentChildMap(); + + // If buildParentChildMap succeeded, inventory will now be in + // a usable state and gInventory.isInventoryUsable() will be + // true. + + // if inventory is unusable, show warning. + if (!gInventory.isInventoryUsable()) + { + LLNotificationsUtil::add("InventoryUnusable"); + } + + LLInventoryModelBackgroundFetch::instance().start(); + gInventory.createCommonSystemCategories(); + LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS ); + display_startup(); + + return FALSE; + } + + //--------------------------------------------------------------------- + // STATE_INVENTORY_CALLBACKS + //--------------------------------------------------------------------- + if (STATE_INVENTORY_CALLBACKS == LLStartUp::getStartupState()) + { + if (!LLInventoryModel::isSysFoldersReady()) + { + display_startup(); + return FALSE; + } + LLInventoryModelBackgroundFetch::instance().start(); + LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); + if (cof + && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // Special case, dupplicate request prevention. + // Cof folder will be requested via FetchCOF + // in appearance manager, prevent recursive fetch + cof->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + } + + + // It's debatable whether this flag is a good idea - sets all + // bits, and in general it isn't true that inventory + // initialization generates all types of changes. Maybe add an + // INITIALIZE mask bit instead? + gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); + gInventory.notifyObservers(); + + display_startup(); + + // set up callbacks + LL_INFOS() << "Registering Callbacks" << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + LL_INFOS() << " Inventory" << LL_ENDL; + LLInventoryModel::registerCallbacks(msg); + LL_INFOS() << " AvatarTracker" << LL_ENDL; + LLAvatarTracker::instance().registerCallbacks(msg); + LL_INFOS() << " Landmark" << LL_ENDL; + LLLandmark::registerCallbacks(msg); + display_startup(); + + // request all group information + LL_INFOS() << "Requesting Agent Data" << LL_ENDL; + gAgent.sendAgentDataUpdateRequest(); + display_startup(); + // Create the inventory views + LL_INFOS() << "Creating Inventory Views" << LL_ENDL; + LLFloaterReg::getInstance("inventory"); + display_startup(); + LLStartUp::setStartupState( STATE_MISC ); + display_startup(); + + return FALSE; + } + - LLAvatarAppearance::initClass("avatar_lad.xml","avatar_skeleton.xml"); - display_startup(); - - LLViewerObject::initVOClasses(); - display_startup(); - - // Initialize all our tools. Must be done after saved settings loaded. - // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton. - LLToolMgr::getInstance()->initTools(); - display_startup(); - - // Pre-load floaters, like the world map, that are slow to spawn - // due to XML complexity. - gViewerWindow->initWorldUI(); - - display_startup(); - - // This is where we used to initialize gWorldp. Original comment said: - // World initialization must be done after above window init - - // User might have overridden far clip - LLWorld::getInstance()->setLandFarClip(gAgentCamera.mDrawDistance); - display_startup(); - // Before we create the first region, we need to set the agent's mOriginGlobal - // This is necessary because creating objects before this is set will result in a - // bad mPositionAgent cache. - - gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); - display_startup(); - - LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); - display_startup(); - - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); - LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; - - LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == " - << gFirstSimSeedCap << LL_ENDL; - regionp->setSeedCapability(gFirstSimSeedCap); - LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; - display_startup(); - // Set agent's initial region to be the one we just created. - gAgent.setRegion(regionp); - display_startup(); - // Set agent's initial position, which will be read by LLVOAvatar when the avatar - // object is created. I think this must be done after setting the region. JC - gAgent.setPositionAgent(agent_start_position_region); - - display_startup(); - LLStartUp::initExperiences(); - - display_startup(); - - // If logging should be enebled, turns it on and loads history from disk - // Note: does not happen on init of singleton because preferences can use - // this instance without logging in - LLConversationLog::getInstance()->initLoggingState(); - - LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); - - return FALSE; - } - - - //--------------------------------------------------------------------- - // Load QuickTime/GStreamer and other multimedia engines, can be slow. - // Do it while we're waiting on the network for our seed capability. JC - //--------------------------------------------------------------------- - if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState()) - { - LLStartUp::multimediaInit(); - LLStartUp::setStartupState( STATE_FONT_INIT ); - display_startup(); - return FALSE; - } - - // Loading fonts takes several seconds - if (STATE_FONT_INIT == LLStartUp::getStartupState()) - { - LLStartUp::fontInit(); - LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT ); - display_startup(); - return FALSE; - } - - //--------------------------------------------------------------------- - // Wait for Seed Cap Grant - //--------------------------------------------------------------------- - if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); - if (regionp->capabilitiesReceived()) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - else if (regionp->capabilitiesError()) + //--------------------------------------------------------------------- + // Misc + //--------------------------------------------------------------------- + if (STATE_MISC == LLStartUp::getStartupState()) + { + // We have a region, and just did a big inventory download. + // We can estimate the user's connection speed, and set their + // max bandwidth accordingly. JC + if (gSavedSettings.getBOOL("FirstLoginThisInstall")) { - LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) + // This is actually a pessimistic computation, because TCP may not have enough + // time to ramp up on the (small) default inventory file to truly measure max + // bandwidth. JC + F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS(); + const F32 FAST_RATE_BPS = 600.f * 1024.f; + const F32 FASTER_RATE_BPS = 750.f * 1024.f; + F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); + if (rate_bps > FASTER_RATE_BPS + && rate_bps > max_bandwidth) { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " + << FASTER_RATE_BPS/1024.f + << " kbps" << LL_ENDL; + gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f); } - else + else if (rate_bps > FAST_RATE_BPS + && rate_bps > max_bandwidth) { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " + << FAST_RATE_BPS/1024.f + << " kbps" << LL_ENDL; + gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f); } - reset_login(); - } - else - { - U32 num_retries = regionp->getNumSeedCapRetries(); - if (num_retries > MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT) + + if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin")) { - LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) - { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); - } - else - { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); - } - reset_login(); + gSavedSettings.setBOOL("HelpFloaterOpen", TRUE); } - else if (num_retries > 0) - { - LLStringUtil::format_map_t args; - args["[NUMBER]"] = llformat("%d", num_retries + 1); - set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD.c_str()); - } - else - { - set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str()); - } - } - display_startup(); - return FALSE; - } - - - //--------------------------------------------------------------------- - // Seed Capability Granted - // no newMessage calls should happen before this point - //--------------------------------------------------------------------- - if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState()) - { - display_startup(); - // These textures are not warrantied to be cached, so needs - // to hapen with caps granted - gTextureList.doPrefetchImages(); - - // will init images, should be done with caps, but before gSky.init() - LLEnvironment::getInstance()->initSingleton(); + // Set the show start location to true, now that the user has logged + // on with this install. + gSavedSettings.setBOOL("ShowStartLocation", TRUE); + } display_startup(); - update_texture_fetch(); - display_startup(); - - if ( gViewerWindow != NULL) - { // This isn't the first logon attempt, so show the UI - gViewerWindow->setNormalControlsVisible( TRUE ); - } - gLoginMenuBarView->setVisible( FALSE ); - gLoginMenuBarView->setEnabled( FALSE ); - display_startup(); - - // direct logging to the debug console's line buffer - LLError::logToFixedBuffer(gDebugView->mDebugConsolep); - display_startup(); - - // set initial visibility of debug console - gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); - display_startup(); - - // - // Set message handlers - // - LL_INFOS("AppInit") << "Initializing communications..." << LL_ENDL; - - // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted - register_viewer_callbacks(gMessageSystem); - display_startup(); - - // Debugging info parameters - gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms - display_startup(); - - #ifndef LL_RELEASE_FOR_DOWNLOAD - gMessageSystem->setTimeDecodes( TRUE ); // Time the decode of each msg - gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode - #endif - display_startup(); - - gXferManager->registerCallbacks(gMessageSystem); - display_startup(); - - LLStartUp::initNameCache(); - display_startup(); - - // update the voice settings *after* gCacheName initialization - // so that we can construct voice UI that relies on the name cache - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->updateSettings(); - } - display_startup(); - - // create a container's instance for start a controlling conversation windows - // by the voice's events - LLFloaterIMContainer::getInstance(); - if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2) - { - LLViewerParcelAskPlay::getInstance()->loadSettings(); - } - - gAgent.addRegionChangedCallback(boost::bind(&LLPerfStats::StatsRecorder::clearStats)); - - // *Note: this is where gWorldMap used to be initialized. - - // register null callbacks for audio until the audio system is initialized - gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL); - gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL); - display_startup(); - - //reset statistics - LLViewerStats::instance().resetStats(); - - display_startup(); - // - // Set up region and surface defaults - // - - - // Sets up the parameters for the first simulator - - LL_DEBUGS("AppInit") << "Initializing camera..." << LL_ENDL; - gFrameTime = totalTime(); - F32Seconds last_time = gFrameTimeSeconds; - gFrameTimeSeconds = (gFrameTime - gStartTime); - - gFrameIntervalSeconds = gFrameTimeSeconds - last_time; - if (gFrameIntervalSeconds < 0.f) - { - gFrameIntervalSeconds = 0.f; - } - - // Make sure agent knows correct aspect ratio - // FOV limits depend upon aspect ratio so this needs to happen before initializing the FOV below - LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWorldViewHeightRaw()); - LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio()); - // Initialize FOV - LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle")); - display_startup(); - - // Move agent to starting location. The position handed to us by - // the space server is in global coordinates, but the agent frame - // is in region local coordinates. Therefore, we need to adjust - // the coordinates handed to us to fit in the local region. - - gAgent.setPositionAgent(agent_start_position_region); - gAgent.resetAxes(gAgentStartLookAt); - gAgentCamera.stopCameraAnimation(); - gAgentCamera.resetCamera(); - display_startup(); - - // Initialize global class data needed for surfaces (i.e. textures) - LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; - // Initialize all of the viewer object classes for the first time (doing things like texture fetches. - LLGLState::checkStates(); - - gSky.init(); - - LLGLState::checkStates(); - - display_startup(); - - LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL; - // For all images pre-loaded into viewer cache, init - // priorities and fetching using decodeAllImages. - // Most of the fetching and decoding likely to be done - // by update_texture_fetch() later, while viewer waits. - // - // Need to do this AFTER we init the sky - const S32 DECODE_TIME_SEC = 2; - for (int i = 0; i < DECODE_TIME_SEC; i++) - { - F32 frac = (F32)i / (F32)DECODE_TIME_SEC; - set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD); - display_startup(); - gTextureList.decodeAllImages(1.f); - } - LLStartUp::setStartupState( STATE_WORLD_WAIT ); - - display_startup(); - - // JC - Do this as late as possible to increase likelihood Purify - // will run. - LLMessageSystem* msg = gMessageSystem; - if (!msg->mOurCircuitCode) - { - LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL; - } - - gUseCircuitCallbackCalled = false; - - msg->enableCircuit(gFirstSim, TRUE); - // now, use the circuit info to tell simulator about us! - LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL; - msg->newMessageFast(_PREHASH_UseCircuitCode); - msg->nextBlockFast(_PREHASH_CircuitCode); - msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); - msg->sendReliable( - gFirstSim, - gSavedSettings.getS32("UseCircuitCodeMaxRetries"), - FALSE, - (F32Seconds)gSavedSettings.getF32("UseCircuitCodeTimeout"), - use_circuit_callback, - NULL); - - timeout.reset(); - display_startup(); - - return FALSE; - } - - //--------------------------------------------------------------------- - // World Wait - //--------------------------------------------------------------------- - if(STATE_WORLD_WAIT == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "Waiting for simulator ack...." << LL_ENDL; - set_startup_status(0.59f, LLTrans::getString("LoginWaitingForRegionHandshake"), gAgent.mMOTD); - if(gGotUseCircuitCodeAck) - { - LLStartUp::setStartupState( STATE_AGENT_SEND ); - } - pump_idle_startup_network(); - return FALSE; - } - - //--------------------------------------------------------------------- - // Agent Send - //--------------------------------------------------------------------- - if (STATE_AGENT_SEND == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "Connecting to region..." << LL_ENDL; - set_startup_status(0.60f, LLTrans::getString("LoginConnectingToRegion"), gAgent.mMOTD); - display_startup(); - // register with the message system so it knows we're - // expecting this message - LLMessageSystem* msg = gMessageSystem; - msg->setHandlerFuncFast( - _PREHASH_AgentMovementComplete, - process_agent_movement_complete); - LLViewerRegion* regionp = gAgent.getRegion(); - if(regionp) - { - send_complete_agent_movement(regionp->getHost()); - gAssetStorage->setUpstream(regionp->getHost()); - gCacheName->setUpstream(regionp->getHost()); - } - display_startup(); - - // Create login effect - // But not on first login, because you can't see your avatar then - if (!gAgent.isFirstLogin()) - { - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal(gAgent.getPositionGlobal()); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - LLHUDManager::getInstance()->sendEffects(); - } - - LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT - - timeout.reset(); - display_startup(); - return FALSE; - } - - //--------------------------------------------------------------------- - // Agent Wait - //--------------------------------------------------------------------- - if (STATE_AGENT_WAIT == LLStartUp::getStartupState()) - { - { - LockMessageChecker lmc(gMessageSystem); - while (lmc.checkAllMessages(gFrameCount, gServicePump)) - { - if (gAgentMovementCompleted) - { - // Sometimes we have more than one message in the - // queue. break out of this loop and continue - // processing. If we don't, then this could skip one - // or more login steps. - break; - } - else - { - LL_DEBUGS("AppInit") << "Awaiting AvatarInitComplete, got " - << gMessageSystem->getMessageName() << LL_ENDL; - } - display_startup(); - } - lmc.processAcks(); - } - - display_startup(); - - if (gAgentMovementCompleted) - { - LLStartUp::setStartupState( STATE_INVENTORY_SEND ); - } - display_startup(); - - if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) - { - LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) - { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); - } - else - { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); - } - reset_login(); - } - return FALSE; - } - - //--------------------------------------------------------------------- - // Inventory Send - //--------------------------------------------------------------------- - if (STATE_INVENTORY_SEND == LLStartUp::getStartupState()) - { - LL_PROFILE_ZONE_NAMED("State inventory send") - display_startup(); - // request mute list - LL_INFOS() << "Requesting Mute List" << LL_ENDL; - LLMuteList::getInstance()->requestFromServer(gAgent.getID()); + // Load stored local environment if needed. + LLEnvironment::instance().loadFromSettings(); - // Get L$ and ownership credit information - LL_INFOS() << "Requesting Money Balance" << LL_ENDL; - LLStatusBar::sendMoneyBalanceRequest(); + // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp) + //check_merchant_status(); display_startup(); - // Inform simulator of our language preference - LLAgentLanguage::update(); - - display_startup(); - // unpack thin inventory - LLSD response = LLLoginInstance::getInstance()->getResponse(); - //bool dump_buffer = false; - - LLSD inv_lib_root = response["inventory-lib-root"]; - if(inv_lib_root.isDefined()) - { - // should only be one - LLSD id = inv_lib_root[0]["folder_id"]; - if(id.isDefined()) - { - gInventory.setLibraryRootFolderID(id.asUUID()); - } - } - display_startup(); - - LLSD inv_lib_owner = response["inventory-lib-owner"]; - if(inv_lib_owner.isDefined()) - { - // should only be one - LLSD id = inv_lib_owner[0]["agent_id"]; - if(id.isDefined()) - { - gInventory.setLibraryOwnerID(LLUUID(id.asUUID())); - } - } - display_startup(); - LLStartUp::setStartupState(STATE_INVENTORY_SKEL); - display_startup(); - return FALSE; - } + if (gSavedSettings.getBOOL("HelpFloaterOpen")) + { + // show default topic + LLViewerHelp::instance().showTopic(""); + } - if (STATE_INVENTORY_SKEL == LLStartUp::getStartupState()) - { - LL_PROFILE_ZONE_NAMED("State inventory load skeleton") + display_startup(); - LLSD response = LLLoginInstance::getInstance()->getResponse(); + // We're successfully logged in. + gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE); - LLSD inv_skel_lib = response["inventory-skel-lib"]; - if (inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull()) + LLFloaterReg::showInitialVisibleInstances(); + + LLFloaterGridStatus::getInstance()->startGridStatusTimer(); + + display_startup(); + + display_startup(); + // JC: Initializing audio requests many sounds for download. + init_audio(); + display_startup(); + + // JC: Initialize "active" gestures. This may also trigger + // many gesture downloads, if this is the user's first + // time on this machine or -purge has been run. + LLSD gesture_options + = LLLoginInstance::getInstance()->getResponse("gestures"); + if (gesture_options.isDefined()) { - LL_PROFILE_ZONE_NAMED("load library inv") - if (!gInventory.loadSkeleton(inv_skel_lib, gInventory.getLibraryOwnerID())) + LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size() + << LL_ENDL; + uuid_vec_t item_ids; + for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(), + end = gesture_options.endArray(); resp_it != end; ++resp_it) { - LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; + // If the id is not specifed in the LLSD, + // the LLSD operator[]() will return a null LLUUID. + LLUUID item_id = (*resp_it)["item_id"]; + LLUUID asset_id = (*resp_it)["asset_id"]; + + if (item_id.notNull() && asset_id.notNull()) + { + // Could schedule and delay these for later. + const BOOL no_inform_server = FALSE; + const BOOL no_deactivate_similar = FALSE; + LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id, + no_inform_server, + no_deactivate_similar); + // We need to fetch the inventory items for these gestures + // so we have the names to populate the UI. + item_ids.push_back(item_id); + } } + // no need to add gesture to inventory observer, it's already made in constructor + LLGestureMgr::instance().setFetchIDs(item_ids); + LLGestureMgr::instance().startFetch(); } + gDisplaySwapBuffers = TRUE; display_startup(); - LLSD inv_skeleton = response["inventory-skeleton"]; - if (inv_skeleton.isDefined()) + LLMessageSystem* msg = gMessageSystem; + msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger); + msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound); + msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound); + msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change); + + LL_DEBUGS("AppInit") << "Initialization complete" << LL_ENDL; + + LL_DEBUGS("SceneLoadTiming", "Start") << "Scene Load Started " << LL_ENDL; + gRenderStartTime.reset(); + gForegroundTime.reset(); + + // HACK: Inform simulator of window size. + // Do this here so it's less likely to race with RegisterNewAgent. + // TODO: Put this into RegisterNewAgent + // JC - 7/20/2002 + gViewerWindow->sendShapeToSim(); + + LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA); + + // The reason we show the alert is because we want to + // reduce confusion for when you log in and your provided + // location is not your expected location. So, if this is + // your first login, then you do not have an expectation, + // thus, do not show this alert. + if (!gAgent.isFirstLogin()) { - LL_PROFILE_ZONE_NAMED("load personal inv") - if (!gInventory.loadSkeleton(inv_skeleton, gAgent.getID())) + LL_INFOS() << "gAgentStartLocation : " << gAgentStartLocation << LL_ENDL; + LLSLURL start_slurl = LLStartUp::getStartSLURL(); + LL_DEBUGS("AppInit") << "start slurl "<getResponse(); - - LLSD inv_basic = response["inventory-basic"]; - if(inv_basic.isDefined()) - { - LL_INFOS() << "Basic inventory root folder id is " << inv_basic["folder_id"] << LL_ENDL; - } - - LLSD buddy_list = response["buddy-list"]; - if(buddy_list.isDefined()) - { - LLAvatarTracker::buddy_map_t list; - LLUUID agent_id; - S32 has_rights = 0, given_rights = 0; - for(LLSD::array_const_iterator it = buddy_list.beginArray(), - end = buddy_list.endArray(); it != end; ++it) - { - LLSD buddy_id = (*it)["buddy_id"]; - if(buddy_id.isDefined()) - { - agent_id = buddy_id.asUUID(); - } - - LLSD buddy_rights_has = (*it)["buddy_rights_has"]; - if(buddy_rights_has.isDefined()) - { - has_rights = buddy_rights_has.asInteger(); - } - - LLSD buddy_rights_given = (*it)["buddy_rights_given"]; - if(buddy_rights_given.isDefined()) - { - given_rights = buddy_rights_given.asInteger(); - } - - list[agent_id] = new LLRelationship(given_rights, has_rights, false); - } - LLAvatarTracker::instance().addBuddyList(list); - display_startup(); - } - - bool show_hud = false; - LLSD tutorial_setting = response["tutorial_setting"]; - if(tutorial_setting.isDefined()) - { - for(LLSD::array_const_iterator it = tutorial_setting.beginArray(), - end = tutorial_setting.endArray(); it != end; ++it) - { - LLSD tutorial_url = (*it)["tutorial_url"]; - if(tutorial_url.isDefined()) - { - // Tutorial floater will append language code - gSavedSettings.setString("TutorialURL", tutorial_url.asString()); - } - - // For Viewer 2.0 we are not using the web-based tutorial - // If we reverse that decision, put this code back and use - // login.cgi to send a different URL with content that matches - // the Viewer 2.0 UI. - //LLSD use_tutorial = (*it)["use_tutorial"]; - //if(use_tutorial.asString() == "true") - //{ - // show_hud = true; - //} - } - } - display_startup(); - - // Either we want to show tutorial because this is the first login - // to a Linden Help Island or the user quit with the tutorial - // visible. JC - if (show_hud || gSavedSettings.getBOOL("ShowTutorial")) - { - LLFloaterReg::showInstance("hud", LLSD(), FALSE); - } - display_startup(); - - LLSD event_notifications = response["event_notifications"]; - if(event_notifications.isDefined()) - { - gEventNotifier.load(event_notifications); - } - display_startup(); - - LLSD classified_categories = response["classified_categories"]; - if(classified_categories.isDefined()) - { - LLClassifiedInfo::loadCategories(classified_categories); - } - display_startup(); - - // This method MUST be called before gInventory.findCategoryUUIDForType because of - // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap. - gInventory.buildParentChildMap(); - - // If buildParentChildMap succeeded, inventory will now be in - // a usable state and gInventory.isInventoryUsable() will be - // true. - - // if inventory is unusable, show warning. - if (!gInventory.isInventoryUsable()) - { - LLNotificationsUtil::add("InventoryUnusable"); - } - - LLInventoryModelBackgroundFetch::instance().start(); - gInventory.createCommonSystemCategories(); - LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS ); display_startup(); - return FALSE; + // wait precache-delay and for agent's avatar or a lot longer. + if ((timeout_frac > 1.f) && isAgentAvatarValid()) + { + LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); + } + else if (timeout_frac > 10.f) + { + // If we exceed the wait above while isAgentAvatarValid is + // not true yet, we will change startup state and + // eventually (once avatar does get created) wind up at + // the gender chooser. This should occur only in very + // unusual circumstances, so set the timeout fairly high + // to minimize mistaken hits here. + LL_WARNS() << "Wait for valid avatar state exceeded " + << timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL; + LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); + } + else + { + update_texture_fetch(); + set_startup_status(0.60f + 0.30f * timeout_frac, + LLTrans::getString("LoginPrecaching"), + gAgent.mMOTD.c_str()); + display_startup(); + } + + return TRUE; } - //--------------------------------------------------------------------- - // STATE_INVENTORY_CALLBACKS - //--------------------------------------------------------------------- - if (STATE_INVENTORY_CALLBACKS == LLStartUp::getStartupState()) + if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState()) { - if (!LLInventoryModel::isSysFoldersReady()) + static LLFrameTimer wearables_timer; + + const F32 wearables_time = wearables_timer.getElapsedTimeF32(); + static LLCachedControl max_wearables_time(gSavedSettings, "ClothingLoadingDelay"); + + if (!gAgent.isOutfitChosen() && isAgentAvatarValid()) { - display_startup(); - return FALSE; + // No point in waiting for clothing, we don't even know + // what outfit we want. Pop up a gender chooser dialog to + // ask and proceed to draw the world. JC + // + // *NOTE: We might hit this case even if we have an + // initial outfit, but if the load hasn't started + // already then something is wrong so fall back + // to generic outfits. JC + LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(), + callback_choose_gender); + LLStartUp::setStartupState( STATE_CLEANUP ); } - LLInventoryModelBackgroundFetch::instance().start(); - LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); - if (cof - && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + + display_startup(); + + if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time)) { - // Special case, dupplicate request prevention. - // Cof folder will be requested via FetchCOF - // in appearance manager, prevent recursive fetch - cof->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + if (gInventory.isInventoryUsable()) + { + LLNotificationsUtil::add("ClothingLoading"); + } + record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time); + LLStartUp::setStartupState( STATE_CLEANUP ); + } + else if (gAgent.isFirstLogin() + && isAgentAvatarValid() + && gAgentAvatarp->isFullyLoaded()) + { + // wait for avatar to be completely loaded + if (isAgentAvatarValid() + && gAgentAvatarp->isFullyLoaded()) + { + LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL; + LLStartUp::setStartupState( STATE_CLEANUP ); + return TRUE; + } + } + else + { + // OK to just get the wearables + if ( gAgentWearables.areWearablesLoaded() ) + { + // We have our clothing, proceed. + LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL; + LLStartUp::setStartupState( STATE_CLEANUP ); + return TRUE; + } } + //fall through this frame to STATE_CLEANUP + } + if (STATE_CLEANUP == LLStartUp::getStartupState()) + { + set_startup_status(1.0, "", ""); + display_startup(); - // It's debatable whether this flag is a good idea - sets all - // bits, and in general it isn't true that inventory - // initialization generates all types of changes. Maybe add an - // INITIALIZE mask bit instead? - gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); - gInventory.notifyObservers(); - - display_startup(); - - // set up callbacks - LL_INFOS() << "Registering Callbacks" << LL_ENDL; - LLMessageSystem* msg = gMessageSystem; - LL_INFOS() << " Inventory" << LL_ENDL; - LLInventoryModel::registerCallbacks(msg); - LL_INFOS() << " AvatarTracker" << LL_ENDL; - LLAvatarTracker::instance().registerCallbacks(msg); - LL_INFOS() << " Landmark" << LL_ENDL; - LLLandmark::registerCallbacks(msg); - display_startup(); - - // request all group information - LL_INFOS() << "Requesting Agent Data" << LL_ENDL; - gAgent.sendAgentDataUpdateRequest(); - display_startup(); - // Create the inventory views - LL_INFOS() << "Creating Inventory Views" << LL_ENDL; - LLFloaterReg::getInstance("inventory"); - display_startup(); - LLStartUp::setStartupState( STATE_MISC ); - display_startup(); - - return FALSE; - } - - - //--------------------------------------------------------------------- - // Misc - //--------------------------------------------------------------------- - if (STATE_MISC == LLStartUp::getStartupState()) - { - // We have a region, and just did a big inventory download. - // We can estimate the user's connection speed, and set their - // max bandwidth accordingly. JC - if (gSavedSettings.getBOOL("FirstLoginThisInstall")) - { - // This is actually a pessimistic computation, because TCP may not have enough - // time to ramp up on the (small) default inventory file to truly measure max - // bandwidth. JC - F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS(); - const F32 FAST_RATE_BPS = 600.f * 1024.f; - const F32 FASTER_RATE_BPS = 750.f * 1024.f; - F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); - if (rate_bps > FASTER_RATE_BPS - && rate_bps > max_bandwidth) - { - LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " - << FASTER_RATE_BPS/1024.f - << " kbps" << LL_ENDL; - gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f); - } - else if (rate_bps > FAST_RATE_BPS - && rate_bps > max_bandwidth) - { - LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " - << FAST_RATE_BPS/1024.f - << " kbps" << LL_ENDL; - gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f); - } - - if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin")) - { - gSavedSettings.setBOOL("HelpFloaterOpen", TRUE); - } - - // Set the show start location to true, now that the user has logged - // on with this install. - gSavedSettings.setBOOL("ShowStartLocation", TRUE); - } - - display_startup(); + if (!mBenefitsSuccessfullyInit) + { + LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2)); + } - // Load stored local environment if needed. - LLEnvironment::instance().loadFromSettings(); + // Let the map know about the inventory. + LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); + if(floater_world_map) + { + floater_world_map->observeInventory(&gInventory); + floater_world_map->observeFriends(); + } + gViewerWindow->showCursor(); + gViewerWindow->getWindow()->resetBusyCount(); + gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL; + //gViewerWindow->revealIntroPanel(); + gViewerWindow->setStartupComplete(); + gViewerWindow->setProgressCancelButtonVisible(FALSE); + display_startup(); - // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp) - //check_merchant_status(); + // We're not away from keyboard, even though login might have taken + // a while. JC + gAgent.clearAFK(); - display_startup(); - - if (gSavedSettings.getBOOL("HelpFloaterOpen")) - { - // show default topic - LLViewerHelp::instance().showTopic(""); - } - - display_startup(); - - // We're successfully logged in. - gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE); - - LLFloaterReg::showInitialVisibleInstances(); - - LLFloaterGridStatus::getInstance()->startGridStatusTimer(); - - display_startup(); - - display_startup(); - // JC: Initializing audio requests many sounds for download. - init_audio(); - display_startup(); - - // JC: Initialize "active" gestures. This may also trigger - // many gesture downloads, if this is the user's first - // time on this machine or -purge has been run. - LLSD gesture_options - = LLLoginInstance::getInstance()->getResponse("gestures"); - if (gesture_options.isDefined()) - { - LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size() - << LL_ENDL; - uuid_vec_t item_ids; - for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(), - end = gesture_options.endArray(); resp_it != end; ++resp_it) - { - // If the id is not specifed in the LLSD, - // the LLSD operator[]() will return a null LLUUID. - LLUUID item_id = (*resp_it)["item_id"]; - LLUUID asset_id = (*resp_it)["asset_id"]; - - if (item_id.notNull() && asset_id.notNull()) - { - // Could schedule and delay these for later. - const BOOL no_inform_server = FALSE; - const BOOL no_deactivate_similar = FALSE; - LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id, - no_inform_server, - no_deactivate_similar); - // We need to fetch the inventory items for these gestures - // so we have the names to populate the UI. - item_ids.push_back(item_id); - } - } - // no need to add gesture to inventory observer, it's already made in constructor - LLGestureMgr::instance().setFetchIDs(item_ids); - LLGestureMgr::instance().startFetch(); - } - gDisplaySwapBuffers = TRUE; - display_startup(); - - LLMessageSystem* msg = gMessageSystem; - msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger); - msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound); - msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound); - msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change); - - LL_DEBUGS("AppInit") << "Initialization complete" << LL_ENDL; - - LL_DEBUGS("SceneLoadTiming", "Start") << "Scene Load Started " << LL_ENDL; - gRenderStartTime.reset(); - gForegroundTime.reset(); - - // HACK: Inform simulator of window size. - // Do this here so it's less likely to race with RegisterNewAgent. - // TODO: Put this into RegisterNewAgent - // JC - 7/20/2002 - gViewerWindow->sendShapeToSim(); - - LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA); - - // The reason we show the alert is because we want to - // reduce confusion for when you log in and your provided - // location is not your expected location. So, if this is - // your first login, then you do not have an expectation, - // thus, do not show this alert. - if (!gAgent.isFirstLogin()) - { - LL_INFOS() << "gAgentStartLocation : " << gAgentStartLocation << LL_ENDL; - LLSLURL start_slurl = LLStartUp::getStartSLURL(); - LL_DEBUGS("AppInit") << "start slurl "< 1.f) && isAgentAvatarValid()) - { - LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); - } - else if (timeout_frac > 10.f) - { - // If we exceed the wait above while isAgentAvatarValid is - // not true yet, we will change startup state and - // eventually (once avatar does get created) wind up at - // the gender chooser. This should occur only in very - // unusual circumstances, so set the timeout fairly high - // to minimize mistaken hits here. - LL_WARNS() << "Wait for valid avatar state exceeded " - << timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL; - LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); - } - else - { - update_texture_fetch(); - set_startup_status(0.60f + 0.30f * timeout_frac, - LLTrans::getString("LoginPrecaching"), - gAgent.mMOTD.c_str()); - display_startup(); - } - - return TRUE; - } - - if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState()) - { - static LLFrameTimer wearables_timer; - - const F32 wearables_time = wearables_timer.getElapsedTimeF32(); - static LLCachedControl max_wearables_time(gSavedSettings, "ClothingLoadingDelay"); - - if (!gAgent.isOutfitChosen() && isAgentAvatarValid()) - { - // No point in waiting for clothing, we don't even know - // what outfit we want. Pop up a gender chooser dialog to - // ask and proceed to draw the world. JC - // - // *NOTE: We might hit this case even if we have an - // initial outfit, but if the load hasn't started - // already then something is wrong so fall back - // to generic outfits. JC - LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(), - callback_choose_gender); - LLStartUp::setStartupState( STATE_CLEANUP ); - } - - display_startup(); - - if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time)) - { - if (gInventory.isInventoryUsable()) - { - LLNotificationsUtil::add("ClothingLoading"); - } - record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time); - LLStartUp::setStartupState( STATE_CLEANUP ); - } - else if (gAgent.isFirstLogin() - && isAgentAvatarValid() - && gAgentAvatarp->isFullyLoaded()) - { - // wait for avatar to be completely loaded - if (isAgentAvatarValid() - && gAgentAvatarp->isFullyLoaded()) - { - LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL; - LLStartUp::setStartupState( STATE_CLEANUP ); - return TRUE; - } - } - else - { - // OK to just get the wearables - if ( gAgentWearables.areWearablesLoaded() ) - { - // We have our clothing, proceed. - LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL; - LLStartUp::setStartupState( STATE_CLEANUP ); - return TRUE; - } - } - //fall through this frame to STATE_CLEANUP - } - - if (STATE_CLEANUP == LLStartUp::getStartupState()) - { - set_startup_status(1.0, "", ""); - display_startup(); - - if (!mBenefitsSuccessfullyInit) - { - LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2)); - } - - // Let the map know about the inventory. - LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); - if(floater_world_map) - { - floater_world_map->observeInventory(&gInventory); - floater_world_map->observeFriends(); - } - gViewerWindow->showCursor(); - gViewerWindow->getWindow()->resetBusyCount(); - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL; - //gViewerWindow->revealIntroPanel(); - gViewerWindow->setStartupComplete(); - gViewerWindow->setProgressCancelButtonVisible(FALSE); - display_startup(); - - // We're not away from keyboard, even though login might have taken - // a while. JC - gAgent.clearAFK(); - - // Have the agent start watching the friends list so we can update proxies - gAgent.observeFriends(); - - // Start automatic replay if the flag is set. - if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession()) - { - LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL; - gAgentPilot.startPlayback(); - } - - show_debug_menus(); // Debug menu visiblity and First Use trigger - - // If we've got a startup URL, dispatch it - //LLStartUp::dispatchURL(); - - // Retrieve information about the land data - // (just accessing this the first time will fetch it, - // then the data is cached for the viewer's lifetime) - LLProductInfoRequestManager::instance(); - - // *FIX:Mani - What do I do here? - // Need we really clear the Auth response data? - // Clean up the userauth stuff. - // LLUserAuth::getInstance()->reset(); - - LLStartUp::setStartupState( STATE_STARTED ); - display_startup(); - - // Unmute audio if desired and setup volumes. - // This is a not-uncommon crash site, so surround it with - // LL_INFOS() output to aid diagnosis. - LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL; - audio_update_volume(); - LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL; - - // reset keyboard focus to sane state of pointing at world - gFocusMgr.setKeyboardFocus(NULL); - - LLAppViewer::instance()->handleLoginComplete(); - - LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); - - display_startup(); - - llassert(LLPathfindingManager::getInstance() != NULL); - LLPathfindingManager::getInstance()->initSystem(); - - gAgentAvatarp->sendHoverHeight(); - - // look for parcels we own - send_places_query(LLUUID::null, - LLUUID::null, - "", - DFQ_AGENT_OWNED, - LLParcel::C_ANY, - ""); - - LLUIUsage::instance().clear(); + // Have the agent start watching the friends list so we can update proxies + gAgent.observeFriends(); + + // Start automatic replay if the flag is set. + if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession()) + { + LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL; + gAgentPilot.startPlayback(); + } + + show_debug_menus(); // Debug menu visiblity and First Use trigger + + // If we've got a startup URL, dispatch it + //LLStartUp::dispatchURL(); + + // Retrieve information about the land data + // (just accessing this the first time will fetch it, + // then the data is cached for the viewer's lifetime) + LLProductInfoRequestManager::instance(); + + // *FIX:Mani - What do I do here? + // Need we really clear the Auth response data? + // Clean up the userauth stuff. + // LLUserAuth::getInstance()->reset(); + + LLStartUp::setStartupState( STATE_STARTED ); + display_startup(); + + // Unmute audio if desired and setup volumes. + // This is a not-uncommon crash site, so surround it with + // LL_INFOS() output to aid diagnosis. + LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL; + audio_update_volume(); + LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL; + + // reset keyboard focus to sane state of pointing at world + gFocusMgr.setKeyboardFocus(NULL); + + LLAppViewer::instance()->handleLoginComplete(); + + LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); + + display_startup(); + + llassert(LLPathfindingManager::getInstance() != NULL); + LLPathfindingManager::getInstance()->initSystem(); + + gAgentAvatarp->sendHoverHeight(); + + // look for parcels we own + send_places_query(LLUUID::null, + LLUUID::null, + "", + DFQ_AGENT_OWNED, + LLParcel::C_ANY, + ""); + + LLUIUsage::instance().clear(); LLPerfStats::StatsRecorder::setAutotuneInit(); - return TRUE; - } + return TRUE; + } - return TRUE; + return TRUE; } // @@ -2431,50 +2431,50 @@ bool idle_startup() void login_show() { - LL_INFOS("AppInit") << "Initializing Login Screen" << LL_ENDL; - - // Hide the toolbars: may happen to come back here if login fails after login agent but before login in region - if (gToolBarView) - { - gToolBarView->setVisible(FALSE); - } - - LLPanelLogin::show( gViewerWindow->getWindowRectScaled(), login_callback, NULL ); + LL_INFOS("AppInit") << "Initializing Login Screen" << LL_ENDL; + + // Hide the toolbars: may happen to come back here if login fails after login agent but before login in region + if (gToolBarView) + { + gToolBarView->setVisible(FALSE); + } + + LLPanelLogin::show( gViewerWindow->getWindowRectScaled(), login_callback, NULL ); } // Callback for when login screen is closed. Option 0 = connect, option 1 = quit. void login_callback(S32 option, void *userdata) { - const S32 CONNECT_OPTION = 0; - const S32 QUIT_OPTION = 1; - - if (CONNECT_OPTION == option) - { - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - return; - } - else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION - { - if (!gSavedSettings.getBOOL("RememberPassword")) - { - // turn off the setting and write out to disk - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , TRUE ); - LLUIColorTable::instance().saveUserSettings(); - } - - // Next iteration through main loop should shut down the app cleanly. - LLAppViewer::instance()->userQuit(); - - if (LLAppViewer::instance()->quitRequested()) - { - LLPanelLogin::closePanel(); - } - return; - } - else - { - LL_WARNS("AppInit") << "Unknown login button clicked" << LL_ENDL; - } + const S32 CONNECT_OPTION = 0; + const S32 QUIT_OPTION = 1; + + if (CONNECT_OPTION == option) + { + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + return; + } + else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION + { + if (!gSavedSettings.getBOOL("RememberPassword")) + { + // turn off the setting and write out to disk + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , TRUE ); + LLUIColorTable::instance().saveUserSettings(); + } + + // Next iteration through main loop should shut down the app cleanly. + LLAppViewer::instance()->userQuit(); + + if (LLAppViewer::instance()->quitRequested()) + { + LLPanelLogin::closePanel(); + } + return; + } + else + { + LL_WARNS("AppInit") << "Unknown login button clicked" << LL_ENDL; + } } void release_notes_coro(const std::string url) @@ -2556,35 +2556,35 @@ void show_release_notes_if_required() void show_first_run_dialog() { - LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); + LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); } bool first_run_dialog_callback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) - { - LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL; - LLWeb::loadURLExternal(LLTrans::getString("create_account_url") ); - } - - LLPanelLogin::giveFocus(); - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL; + LLWeb::loadURLExternal(LLTrans::getString("create_account_url") ); + } + + LLPanelLogin::giveFocus(); + return false; } void set_startup_status(const F32 frac, const std::string& string, const std::string& msg) { - gViewerWindow->setProgressPercent(frac*100); - gViewerWindow->setProgressString(string); + gViewerWindow->setProgressPercent(frac*100); + gViewerWindow->setProgressString(string); - gViewerWindow->setProgressMessage(msg); + gViewerWindow->setProgressMessage(msg); } bool login_alert_status(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); // Buttons switch( option ) { @@ -2595,222 +2595,222 @@ bool login_alert_status(const LLSD& notification, const LLSD& response) // break; case 2: // Teleport // Restart the login process, starting at our home locaton - LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); + LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); break; default: LL_WARNS("AppInit") << "Missing case in login_alert_status switch" << LL_ENDL; } - LLPanelLogin::giveFocus(); - return false; + LLPanelLogin::giveFocus(); + return false; } void use_circuit_callback(void**, S32 result) { - // bail if we're quitting. - if(LLApp::isExiting()) return; - if( !gUseCircuitCallbackCalled ) - { - gUseCircuitCallbackCalled = true; - if (result) - { - // Make sure user knows something bad happened. JC - LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) - { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); - } - else - { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); - } - reset_login(); - } - else - { - gGotUseCircuitCodeAck = true; - } - } + // bail if we're quitting. + if(LLApp::isExiting()) return; + if( !gUseCircuitCallbackCalled ) + { + gUseCircuitCallbackCalled = true; + if (result) + { + // Make sure user knows something bad happened. JC + LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + else + { + gGotUseCircuitCodeAck = true; + } + } } void register_viewer_callbacks(LLMessageSystem* msg) { - msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data ); - msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update ); - msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update ); - msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update ); - msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved ); - msg->setHandlerFunc("SimStats", process_sim_stats); - msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message ); - msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data); - msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo); - - msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator); - msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL); - msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL); - msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator); - msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator); - msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL); - - msg->setHandlerFunc("CrossedRegion", process_crossed_region); - msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish); - - msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message); - msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message); - msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL); - msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message); - - msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value); - msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value); - msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation); - msg->setHandlerFuncFast(_PREHASH_ObjectAnimation, process_object_animation); - msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance); - msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint); - msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response); - msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties); - msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties); - - msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im); - msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question); - msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL); - msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL); - msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect); - - msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL); - msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL); - msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL); - msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL); - msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply, - &LLLiveLSLEditor::processScriptRunningReply); - - msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack); - - msg->setHandlerFunc("LogoutReply", process_logout_reply); - - //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility, - // &LLAgent::processAddModifyAbility); - //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility, - // &LLAgent::processRemoveModifyAbility); - msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate, - &LLAgent::processAgentDataUpdate); - msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate, - &LLAgent::processAgentGroupDataUpdate); - msg->setHandlerFunc("AgentDropGroup", - &LLAgent::processAgentDropGroup); - // land ownership messages - msg->setHandlerFuncFast(_PREHASH_ParcelOverlay, - LLViewerParcelMgr::processParcelOverlay); - msg->setHandlerFuncFast(_PREHASH_ParcelProperties, - LLViewerParcelMgr::processParcelProperties); - msg->setHandlerFunc("ParcelAccessListReply", - LLViewerParcelMgr::processParcelAccessListReply); - msg->setHandlerFunc("ParcelDwellReply", - LLViewerParcelMgr::processParcelDwellReply); - - msg->setHandlerFunc("AvatarPropertiesReply", - &LLAvatarPropertiesProcessor::processAvatarPropertiesReply); - msg->setHandlerFunc("AvatarInterestsReply", - &LLAvatarPropertiesProcessor::processAvatarInterestsReply); - msg->setHandlerFunc("AvatarGroupsReply", - &LLAvatarPropertiesProcessor::processAvatarGroupsReply); - // ratings deprecated - //msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply, - // LLPanelAvatar::processAvatarStatisticsReply); - msg->setHandlerFunc("AvatarNotesReply", - &LLAvatarPropertiesProcessor::processAvatarNotesReply); - msg->setHandlerFunc("AvatarPicksReply", - &LLAvatarPropertiesProcessor::processAvatarPicksReply); - msg->setHandlerFunc("AvatarClassifiedReply", - &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply); - - msg->setHandlerFuncFast(_PREHASH_CreateGroupReply, - LLGroupMgr::processCreateGroupReply); - msg->setHandlerFuncFast(_PREHASH_JoinGroupReply, - LLGroupMgr::processJoinGroupReply); - msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply, - LLGroupMgr::processEjectGroupMemberReply); - msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply, - LLGroupMgr::processLeaveGroupReply); - msg->setHandlerFuncFast(_PREHASH_GroupProfileReply, - LLGroupMgr::processGroupPropertiesReply); - - // ratings deprecated - // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, - // LLFloaterRate::processReputationIndividualReply); - - msg->setHandlerFunc("ScriptControlChange", - LLAgent::processScriptControlChange ); - - msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect); - - msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers); - - msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply, - LLPanelGroupLandMoney::processGroupAccountSummaryReply); - msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply, - LLPanelGroupLandMoney::processGroupAccountDetailsReply); - msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply, - LLPanelGroupLandMoney::processGroupAccountTransactionsReply); - - msg->setHandlerFuncFast(_PREHASH_UserInfoReply, - process_user_info_reply); - - msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL); - - msg->setHandlerFunc("TeleportStart", process_teleport_start ); - msg->setHandlerFunc("TeleportProgress", process_teleport_progress); - msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL); - msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL); - - msg->setHandlerFunc("ImageNotInDatabase", LLViewerTextureList::processImageNotInDatabase, NULL); - - msg->setHandlerFuncFast(_PREHASH_GroupMembersReply, - LLGroupMgr::processGroupMembersReply); - msg->setHandlerFunc("GroupRoleDataReply", - LLGroupMgr::processGroupRoleDataReply); - msg->setHandlerFunc("GroupRoleMembersReply", - LLGroupMgr::processGroupRoleMembersReply); - msg->setHandlerFunc("GroupTitlesReply", - LLGroupMgr::processGroupTitlesReply); - // Special handler as this message is sometimes used for group land. - msg->setHandlerFunc("PlacesReply", process_places_reply); - msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply); - - msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); - - msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); - msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); - msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply); - - msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); - msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply); - msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply); - msg->setHandlerFunc("ScriptDialog", process_script_dialog); - msg->setHandlerFunc("LoadURL", process_load_url); - msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request); - msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply); - - // calling cards - msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard); - msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard); - msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard); - - msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply); - - msg->setHandlerFunc("InitiateDownload", process_initiate_download); - msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply); + msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data ); + msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update ); + msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update ); + msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update ); + msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved ); + msg->setHandlerFunc("SimStats", process_sim_stats); + msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message ); + msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data); + msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo); + + msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator); + msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL); + msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL); + msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator); + msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator); + msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL); + + msg->setHandlerFunc("CrossedRegion", process_crossed_region); + msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish); + + msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message); + msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message); + msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL); + msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message); + + msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value); + msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value); + msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation); + msg->setHandlerFuncFast(_PREHASH_ObjectAnimation, process_object_animation); + msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance); + msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint); + msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response); + msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties); + msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties); + + msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im); + msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question); + msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL); + msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL); + msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect); + + msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL); + msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL); + msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL); + msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL); + msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply, + &LLLiveLSLEditor::processScriptRunningReply); + + msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack); + + msg->setHandlerFunc("LogoutReply", process_logout_reply); + + //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility, + // &LLAgent::processAddModifyAbility); + //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility, + // &LLAgent::processRemoveModifyAbility); + msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate, + &LLAgent::processAgentDataUpdate); + msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate, + &LLAgent::processAgentGroupDataUpdate); + msg->setHandlerFunc("AgentDropGroup", + &LLAgent::processAgentDropGroup); + // land ownership messages + msg->setHandlerFuncFast(_PREHASH_ParcelOverlay, + LLViewerParcelMgr::processParcelOverlay); + msg->setHandlerFuncFast(_PREHASH_ParcelProperties, + LLViewerParcelMgr::processParcelProperties); + msg->setHandlerFunc("ParcelAccessListReply", + LLViewerParcelMgr::processParcelAccessListReply); + msg->setHandlerFunc("ParcelDwellReply", + LLViewerParcelMgr::processParcelDwellReply); + + msg->setHandlerFunc("AvatarPropertiesReply", + &LLAvatarPropertiesProcessor::processAvatarPropertiesReply); + msg->setHandlerFunc("AvatarInterestsReply", + &LLAvatarPropertiesProcessor::processAvatarInterestsReply); + msg->setHandlerFunc("AvatarGroupsReply", + &LLAvatarPropertiesProcessor::processAvatarGroupsReply); + // ratings deprecated + //msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply, + // LLPanelAvatar::processAvatarStatisticsReply); + msg->setHandlerFunc("AvatarNotesReply", + &LLAvatarPropertiesProcessor::processAvatarNotesReply); + msg->setHandlerFunc("AvatarPicksReply", + &LLAvatarPropertiesProcessor::processAvatarPicksReply); + msg->setHandlerFunc("AvatarClassifiedReply", + &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply); + + msg->setHandlerFuncFast(_PREHASH_CreateGroupReply, + LLGroupMgr::processCreateGroupReply); + msg->setHandlerFuncFast(_PREHASH_JoinGroupReply, + LLGroupMgr::processJoinGroupReply); + msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply, + LLGroupMgr::processEjectGroupMemberReply); + msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply, + LLGroupMgr::processLeaveGroupReply); + msg->setHandlerFuncFast(_PREHASH_GroupProfileReply, + LLGroupMgr::processGroupPropertiesReply); + + // ratings deprecated + // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, + // LLFloaterRate::processReputationIndividualReply); + + msg->setHandlerFunc("ScriptControlChange", + LLAgent::processScriptControlChange ); + + msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect); + + msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers); + + msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply, + LLPanelGroupLandMoney::processGroupAccountSummaryReply); + msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply, + LLPanelGroupLandMoney::processGroupAccountDetailsReply); + msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply, + LLPanelGroupLandMoney::processGroupAccountTransactionsReply); + + msg->setHandlerFuncFast(_PREHASH_UserInfoReply, + process_user_info_reply); + + msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL); + + msg->setHandlerFunc("TeleportStart", process_teleport_start ); + msg->setHandlerFunc("TeleportProgress", process_teleport_progress); + msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL); + msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL); + + msg->setHandlerFunc("ImageNotInDatabase", LLViewerTextureList::processImageNotInDatabase, NULL); + + msg->setHandlerFuncFast(_PREHASH_GroupMembersReply, + LLGroupMgr::processGroupMembersReply); + msg->setHandlerFunc("GroupRoleDataReply", + LLGroupMgr::processGroupRoleDataReply); + msg->setHandlerFunc("GroupRoleMembersReply", + LLGroupMgr::processGroupRoleMembersReply); + msg->setHandlerFunc("GroupTitlesReply", + LLGroupMgr::processGroupTitlesReply); + // Special handler as this message is sometimes used for group land. + msg->setHandlerFunc("PlacesReply", process_places_reply); + msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply); + + msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); + + msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); + msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); + msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply); + + msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); + msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply); + msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply); + msg->setHandlerFunc("ScriptDialog", process_script_dialog); + msg->setHandlerFunc("LoadURL", process_load_url); + msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request); + msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply); + + // calling cards + msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard); + msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard); + msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard); + + msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply); + + msg->setHandlerFunc("InitiateDownload", process_initiate_download); + msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply); msg->setHandlerFunc("GenericMessage", process_generic_message); msg->setHandlerFunc("GenericStreamingMessage", process_generic_streaming_message); msg->setHandlerFunc("LargeGenericMessage", process_large_generic_message); - msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message); + msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message); } void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32) { - // nothing + // nothing } const S32 OPT_CLOSED_WINDOW = -1; @@ -2818,27 +2818,27 @@ const S32 OPT_MALE = 0; const S32 OPT_FEMALE = 1; const S32 OPT_TRUST_CERT = 0; const S32 OPT_CANCEL_TRUST = 1; - + bool callback_choose_gender(const LLSD& notification, const LLSD& response) { - - // These defaults are returned from the server on login. They are set in login.xml. - // If no default is returned from the server, they are retrieved from settings.xml. - - S32 option = LLNotification::getSelectedOption(notification, response); - switch(option) - { - case OPT_MALE: - LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultMaleAvatar"), "male" ); - break; - + + // These defaults are returned from the server on login. They are set in login.xml. + // If no default is returned from the server, they are retrieved from settings.xml. + + S32 option = LLNotification::getSelectedOption(notification, response); + switch(option) + { + case OPT_MALE: + LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultMaleAvatar"), "male" ); + break; + case OPT_FEMALE: case OPT_CLOSED_WINDOW: default: - LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultFemaleAvatar"), "female" ); - break; - } - return false; + LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultFemaleAvatar"), "female" ); + break; + } + return false; } std::string get_screen_filename(const std::string& pattern) @@ -2870,66 +2870,66 @@ std::string LLStartUp::getScreenHomeFilename() //static void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, - const std::string& gender_name ) + const std::string& gender_name ) { - LL_DEBUGS() << "starting" << LL_ENDL; - - // Not going through the processAgentInitialWearables path, so need to set this here. - LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); - // Initiate creation of COF, since we're also bypassing that. - gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); - - ESex gender; - if (gender_name == "male") - { - LL_DEBUGS() << "male" << LL_ENDL; - gender = SEX_MALE; - } - else - { - LL_DEBUGS() << "female" << LL_ENDL; - gender = SEX_FEMALE; - } - - if (!isAgentAvatarValid()) - { - LL_WARNS() << "Trying to load an initial outfit for an invalid agent avatar" << LL_ENDL; - return; - } - - gAgentAvatarp->setSex(gender); - - // try to find the requested outfit or folder - - // -- check for existing outfit in My Outfits - bool do_copy = false; - LLUUID cat_id = findDescendentCategoryIDByName( - gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS), - outfit_folder_name); - - // -- check for existing folder in Library - if (cat_id.isNull()) - { - cat_id = findDescendentCategoryIDByName( - gInventory.getLibraryRootFolderID(), - outfit_folder_name); - if (!cat_id.isNull()) - { - do_copy = true; - } - } - - if (cat_id.isNull()) - { - // -- final fallback: create standard wearables - LL_DEBUGS() << "standard wearables" << LL_ENDL; - gAgentWearables.createStandardWearables(); - } - else - { - bool do_append = false; - LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); - // Need to fetch cof contents before we can wear. + LL_DEBUGS() << "starting" << LL_ENDL; + + // Not going through the processAgentInitialWearables path, so need to set this here. + LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); + // Initiate creation of COF, since we're also bypassing that. + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); + + ESex gender; + if (gender_name == "male") + { + LL_DEBUGS() << "male" << LL_ENDL; + gender = SEX_MALE; + } + else + { + LL_DEBUGS() << "female" << LL_ENDL; + gender = SEX_FEMALE; + } + + if (!isAgentAvatarValid()) + { + LL_WARNS() << "Trying to load an initial outfit for an invalid agent avatar" << LL_ENDL; + return; + } + + gAgentAvatarp->setSex(gender); + + // try to find the requested outfit or folder + + // -- check for existing outfit in My Outfits + bool do_copy = false; + LLUUID cat_id = findDescendentCategoryIDByName( + gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS), + outfit_folder_name); + + // -- check for existing folder in Library + if (cat_id.isNull()) + { + cat_id = findDescendentCategoryIDByName( + gInventory.getLibraryRootFolderID(), + outfit_folder_name); + if (!cat_id.isNull()) + { + do_copy = true; + } + } + + if (cat_id.isNull()) + { + // -- final fallback: create standard wearables + LL_DEBUGS() << "standard wearables" << LL_ENDL; + gAgentWearables.createStandardWearables(); + } + else + { + bool do_append = false; + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + // Need to fetch cof contents before we can wear. if (do_copy) { callAfterCOFFetch(boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); @@ -2938,16 +2938,16 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, { callAfterCategoryLinksFetch(cat_id, boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); } - LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL; - } + LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL; + } - gAgent.setOutfitChosen(TRUE); - gAgentWearables.sendDummyAgentWearablesUpdate(); + gAgent.setOutfitChosen(TRUE); + gAgentWearables.sendDummyAgentWearablesUpdate(); } std::string& LLStartUp::getInitialOutfitName() { - return sInitialOutfit; + return sInitialOutfit; } std::string LLStartUp::getUserId() @@ -2963,8 +2963,8 @@ std::string LLStartUp::getUserId() // frees the bitmap void release_start_screen() { - LL_DEBUGS("AppInit") << "Releasing bitmap..." << LL_ENDL; - gStartTexture = NULL; + LL_DEBUGS("AppInit") << "Releasing bitmap..." << LL_ENDL; + gStartTexture = NULL; } @@ -2972,77 +2972,77 @@ void release_start_screen() std::string LLStartUp::startupStateToString(EStartupState state) { #define RTNENUM(E) case E: return #E - switch(state){ - RTNENUM( STATE_FIRST ); - RTNENUM( STATE_BROWSER_INIT ); - RTNENUM( STATE_LOGIN_SHOW ); - RTNENUM( STATE_LOGIN_WAIT ); - RTNENUM( STATE_LOGIN_CLEANUP ); - RTNENUM( STATE_LOGIN_AUTH_INIT ); - RTNENUM( STATE_LOGIN_CURL_UNSTUCK ); - RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); - RTNENUM( STATE_WORLD_INIT ); - RTNENUM( STATE_MULTIMEDIA_INIT ); - RTNENUM( STATE_FONT_INIT ); - RTNENUM( STATE_SEED_GRANTED_WAIT ); - RTNENUM( STATE_SEED_CAP_GRANTED ); - RTNENUM( STATE_WORLD_WAIT ); - RTNENUM( STATE_AGENT_SEND ); - RTNENUM( STATE_AGENT_WAIT ); - RTNENUM( STATE_INVENTORY_SEND ); + switch(state){ + RTNENUM( STATE_FIRST ); + RTNENUM( STATE_BROWSER_INIT ); + RTNENUM( STATE_LOGIN_SHOW ); + RTNENUM( STATE_LOGIN_WAIT ); + RTNENUM( STATE_LOGIN_CLEANUP ); + RTNENUM( STATE_LOGIN_AUTH_INIT ); + RTNENUM( STATE_LOGIN_CURL_UNSTUCK ); + RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); + RTNENUM( STATE_WORLD_INIT ); + RTNENUM( STATE_MULTIMEDIA_INIT ); + RTNENUM( STATE_FONT_INIT ); + RTNENUM( STATE_SEED_GRANTED_WAIT ); + RTNENUM( STATE_SEED_CAP_GRANTED ); + RTNENUM( STATE_WORLD_WAIT ); + RTNENUM( STATE_AGENT_SEND ); + RTNENUM( STATE_AGENT_WAIT ); + RTNENUM( STATE_INVENTORY_SEND ); RTNENUM(STATE_INVENTORY_CALLBACKS ); - RTNENUM( STATE_MISC ); - RTNENUM( STATE_PRECACHE ); - RTNENUM( STATE_WEARABLES_WAIT ); - RTNENUM( STATE_CLEANUP ); - RTNENUM( STATE_STARTED ); - default: - return llformat("(state #%d)", state); - } + RTNENUM( STATE_MISC ); + RTNENUM( STATE_PRECACHE ); + RTNENUM( STATE_WEARABLES_WAIT ); + RTNENUM( STATE_CLEANUP ); + RTNENUM( STATE_STARTED ); + default: + return llformat("(state #%d)", state); + } #undef RTNENUM } // static void LLStartUp::setStartupState( EStartupState state ) { - LL_INFOS("AppInit") << "Startup state changing from " << - getStartupStateString() << " to " << - startupStateToString(state) << LL_ENDL; + LL_INFOS("AppInit") << "Startup state changing from " << + getStartupStateString() << " to " << + startupStateToString(state) << LL_ENDL; - getPhases().stopPhase(getStartupStateString()); - gStartupState = state; - getPhases().startPhase(getStartupStateString()); + getPhases().stopPhase(getStartupStateString()); + gStartupState = state; + getPhases().startPhase(getStartupStateString()); - postStartupState(); + postStartupState(); } void LLStartUp::postStartupState() { - LLSD stateInfo; - stateInfo["str"] = getStartupStateString(); - stateInfo["enum"] = gStartupState; - sStateWatcher->post(stateInfo); - gDebugInfo["StartupState"] = getStartupStateString(); + LLSD stateInfo; + stateInfo["str"] = getStartupStateString(); + stateInfo["enum"] = gStartupState; + sStateWatcher->post(stateInfo); + gDebugInfo["StartupState"] = getStartupStateString(); } void reset_login() { - gAgentWearables.cleanup(); - gAgentCamera.cleanup(); - gAgent.cleanup(); + gAgentWearables.cleanup(); + gAgentCamera.cleanup(); + gAgent.cleanup(); gSky.cleanup(); // mVOSkyp is an inworld object. - LLWorld::getInstance()->resetClass(); + LLWorld::getInstance()->resetClass(); - if ( gViewerWindow ) - { // Hide menus and normal buttons - gViewerWindow->setNormalControlsVisible( FALSE ); - gLoginMenuBarView->setVisible( TRUE ); - gLoginMenuBarView->setEnabled( TRUE ); - } + if ( gViewerWindow ) + { // Hide menus and normal buttons + gViewerWindow->setNormalControlsVisible( FALSE ); + gLoginMenuBarView->setVisible( TRUE ); + gLoginMenuBarView->setEnabled( TRUE ); + } - // Hide any other stuff - LLFloaterReg::hideVisibleInstances(); + // Hide any other stuff + LLFloaterReg::hideVisibleInstances(); LLStartUp::setStartupState( STATE_BROWSER_INIT ); if (LLVoiceClient::instanceExists()) @@ -3062,117 +3062,117 @@ void reset_login() // early, before the login screen). JC void LLStartUp::multimediaInit() { - LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL; - std::string msg = LLTrans::getString("LoginInitializingMultimedia"); - set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); + LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingMultimedia"); + set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str()); + display_startup(); } void LLStartUp::fontInit() { - LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL; - std::string msg = LLTrans::getString("LoginInitializingFonts"); - set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); + LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingFonts"); + set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str()); + display_startup(); - LLFontGL::loadDefaultFonts(); + LLFontGL::loadDefaultFonts(); } void LLStartUp::initNameCache() { - // Can be called multiple times - if ( gCacheName ) return; - - gCacheName = new LLCacheName(gMessageSystem); - gCacheName->addObserver(&callback_cache_name); - gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting")); - gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody")); - gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone")); - // Load stored cache if possible - LLAppViewer::instance()->loadNameCache(); - - // Start cache in not-running state until we figure out if we have - // capabilities for display name lookup - LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance(); - cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI")); - cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); - cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); + // Can be called multiple times + if ( gCacheName ) return; + + gCacheName = new LLCacheName(gMessageSystem); + gCacheName->addObserver(&callback_cache_name); + gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting")); + gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody")); + gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone")); + // Load stored cache if possible + LLAppViewer::instance()->loadNameCache(); + + // Start cache in not-running state until we figure out if we have + // capabilities for display name lookup + LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance(); + cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI")); + cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); + cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); } void LLStartUp::initExperiences() -{ +{ // Should trigger loading the cache. LLExperienceCache::instance().setCapabilityQuery( boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); - LLExperienceLog::instance().initialize(); + LLExperienceLog::instance().initialize(); } void LLStartUp::cleanupNameCache() { - delete gCacheName; - gCacheName = NULL; + delete gCacheName; + gCacheName = NULL; } bool LLStartUp::dispatchURL() { - // ok, if we've gotten this far and have a startup URL + // ok, if we've gotten this far and have a startup URL if (!getStartSLURL().isValid()) - { - return false; - } + { + return false; + } if(getStartSLURL().getType() != LLSLURL::APP) - { - - // If we started with a location, but we're already - // at that location, don't pop dialogs open. - LLVector3 pos = gAgent.getPositionAgent(); - LLVector3 slurlpos = getStartSLURL().getPosition(); - F32 dx = pos.mV[VX] - slurlpos.mV[VX]; - F32 dy = pos.mV[VY] - slurlpos.mV[VY]; - const F32 SLOP = 2.f; // meters - - if( getStartSLURL().getRegion() != gAgent.getRegion()->getName() - || (dx*dx > SLOP*SLOP) - || (dy*dy > SLOP*SLOP) ) - { - LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, - NULL, false); - } - return true; - } - return false; + { + + // If we started with a location, but we're already + // at that location, don't pop dialogs open. + LLVector3 pos = gAgent.getPositionAgent(); + LLVector3 slurlpos = getStartSLURL().getPosition(); + F32 dx = pos.mV[VX] - slurlpos.mV[VX]; + F32 dy = pos.mV[VY] - slurlpos.mV[VY]; + const F32 SLOP = 2.f; // meters + + if( getStartSLURL().getRegion() != gAgent.getRegion()->getName() + || (dx*dx > SLOP*SLOP) + || (dy*dy > SLOP*SLOP) ) + { + LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, + NULL, false); + } + return true; + } + return false; } -void LLStartUp::setStartSLURL(const LLSLURL& slurl) +void LLStartUp::setStartSLURL(const LLSLURL& slurl) { - LL_DEBUGS("AppInit")< socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); - std::string socks_user = socks_cred->getIdentifier()["username"].asString(); - std::string socks_password = socks_cred->getAuthenticator()["creds"].asString(); - - bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password); - - if (!ok) - { - LLNotificationsUtil::add("SOCKS_BAD_CREDS"); - proxy_ok = false; - } - } - else if (auth_type.compare("None") == 0) - { - LLProxy::getInstance()->setAuthNone(); - } - else - { - LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL; - - // Unknown or missing setting. - gSavedSettings.setString("Socks5AuthType", "None"); - - // Clear the SOCKS credentials. - LLPointer socks_cred = new LLCredential("SOCKS5"); - gSecAPIHandler->deleteCredential(socks_cred); - - LLProxy::getInstance()->setAuthNone(); - } - - if (proxy_ok) - { - // Start the proxy and check for errors - // If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns. - LLHost socks_host; - socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); - socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); - int status = LLProxy::getInstance()->startSOCKSProxy(socks_host); - - if (status != SOCKS_OK) - { - LLSD subs; - subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); - subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); - - std::string error_string; - - switch(status) - { - case SOCKS_CONNECT_ERROR: // TCP Fail - error_string = "SOCKS_CONNECT_ERROR"; - break; - - case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection - error_string = "SOCKS_NOT_PERMITTED"; - break; - - case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server - error_string = "SOCKS_NOT_ACCEPTABLE"; - break; - - case SOCKS_AUTH_FAIL: // Authentication failed - error_string = "SOCKS_AUTH_FAIL"; - break; - - case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed - error_string = "SOCKS_UDP_FWD_NOT_GRANTED"; - break; - - case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server - error_string = "SOCKS_HOST_CONNECT_FAILED"; - break; - - case SOCKS_INVALID_HOST: // Improperly formatted host address or port. - error_string = "SOCKS_INVALID_HOST"; - break; - - default: - error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened, - LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL; - break; - } - - LLNotificationsUtil::add(error_string, subs); - proxy_ok = false; - } - } - } - else - { - LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up - } - - if (proxy_ok) - { - // Determine the HTTP proxy type (if any) - if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) - { - LLHost http_host; - http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); - http_host.setPort(gSavedSettings.getS32("BrowserProxyPort")); - if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP)) - { - LLSD subs; - subs["HOST"] = http_host.getIPString(); - subs["PORT"] = (S32)http_host.getPort(); - LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs); - proxy_ok = false; - } - } - else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) - { - LLHost socks_host; - socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); - socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); - if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS)) - { - LLSD subs; - subs["HOST"] = socks_host.getIPString(); - subs["PORT"] = (S32)socks_host.getPort(); - LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs); - proxy_ok = false; - } - } - else if (httpProxyType.compare("None") == 0) - { - LLProxy::getInstance()->disableHTTPProxy(); - } - else - { - LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration: " << httpProxyType << LL_ENDL; - - // Set the missing or wrong configuration back to something valid. - gSavedSettings.setString("HttpProxyType", "None"); - LLProxy::getInstance()->disableHTTPProxy(); - - // Leave proxy_ok alone, since this isn't necessarily fatal. - } - } - - return proxy_ok; + bool proxy_ok = true; + std::string httpProxyType = gSavedSettings.getString("HttpProxyType"); + + // Set up SOCKS proxy (if needed) + if (gSavedSettings.getBOOL("Socks5ProxyEnabled")) + { + // Determine and update LLProxy with the saved authentication system + std::string auth_type = gSavedSettings.getString("Socks5AuthType"); + + if (auth_type.compare("UserPass") == 0) + { + LLPointer socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); + std::string socks_user = socks_cred->getIdentifier()["username"].asString(); + std::string socks_password = socks_cred->getAuthenticator()["creds"].asString(); + + bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password); + + if (!ok) + { + LLNotificationsUtil::add("SOCKS_BAD_CREDS"); + proxy_ok = false; + } + } + else if (auth_type.compare("None") == 0) + { + LLProxy::getInstance()->setAuthNone(); + } + else + { + LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL; + + // Unknown or missing setting. + gSavedSettings.setString("Socks5AuthType", "None"); + + // Clear the SOCKS credentials. + LLPointer socks_cred = new LLCredential("SOCKS5"); + gSecAPIHandler->deleteCredential(socks_cred); + + LLProxy::getInstance()->setAuthNone(); + } + + if (proxy_ok) + { + // Start the proxy and check for errors + // If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns. + LLHost socks_host; + socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + int status = LLProxy::getInstance()->startSOCKSProxy(socks_host); + + if (status != SOCKS_OK) + { + LLSD subs; + subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); + subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); + + std::string error_string; + + switch(status) + { + case SOCKS_CONNECT_ERROR: // TCP Fail + error_string = "SOCKS_CONNECT_ERROR"; + break; + + case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection + error_string = "SOCKS_NOT_PERMITTED"; + break; + + case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server + error_string = "SOCKS_NOT_ACCEPTABLE"; + break; + + case SOCKS_AUTH_FAIL: // Authentication failed + error_string = "SOCKS_AUTH_FAIL"; + break; + + case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed + error_string = "SOCKS_UDP_FWD_NOT_GRANTED"; + break; + + case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server + error_string = "SOCKS_HOST_CONNECT_FAILED"; + break; + + case SOCKS_INVALID_HOST: // Improperly formatted host address or port. + error_string = "SOCKS_INVALID_HOST"; + break; + + default: + error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened, + LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL; + break; + } + + LLNotificationsUtil::add(error_string, subs); + proxy_ok = false; + } + } + } + else + { + LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up + } + + if (proxy_ok) + { + // Determine the HTTP proxy type (if any) + if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) + { + LLHost http_host; + http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); + http_host.setPort(gSavedSettings.getS32("BrowserProxyPort")); + if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP)) + { + LLSD subs; + subs["HOST"] = http_host.getIPString(); + subs["PORT"] = (S32)http_host.getPort(); + LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs); + proxy_ok = false; + } + } + else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) + { + LLHost socks_host; + socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS)) + { + LLSD subs; + subs["HOST"] = socks_host.getIPString(); + subs["PORT"] = (S32)socks_host.getPort(); + LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs); + proxy_ok = false; + } + } + else if (httpProxyType.compare("None") == 0) + { + LLProxy::getInstance()->disableHTTPProxy(); + } + else + { + LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration: " << httpProxyType << LL_ENDL; + + // Set the missing or wrong configuration back to something valid. + gSavedSettings.setString("HttpProxyType", "None"); + LLProxy::getInstance()->disableHTTPProxy(); + + // Leave proxy_ok alone, since this isn't necessarily fatal. + } + } + + return proxy_ok; } bool login_alert_done(const LLSD& notification, const LLSD& response) { - LLPanelLogin::giveFocus(); - return false; + LLPanelLogin::giveFocus(); + return false; } -// parse the certificate information into args for the +// parse the certificate information into args for the // certificate notifications LLSD transform_cert_args(LLPointer cert) { - LLSD args = LLSD::emptyMap(); - std::string value; - LLSD cert_info; - cert->getLLSD(cert_info); - // convert all of the elements in the cert into - // args for the xml dialog, so we have flexability to - // display various parts of the cert by only modifying - // the cert alert dialog xml. - for(LLSD::map_iterator iter = cert_info.beginMap(); - iter != cert_info.endMap(); - iter++) - { - // key usage and extended key usage - // are actually arrays, and we want to format them as comma separated - // strings, so special case those. - LLSDSerialize::toXML(cert_info[iter->first], std::cout); - if((iter->first == std::string(CERT_KEY_USAGE)) || - (iter->first == std::string(CERT_EXTENDED_KEY_USAGE))) - { - value = ""; - LLSD usage = cert_info[iter->first]; - for (LLSD::array_iterator usage_iter = usage.beginArray(); - usage_iter != usage.endArray(); - usage_iter++) - { - - if(usage_iter != usage.beginArray()) - { - value += ", "; - } - - value += (*usage_iter).asString(); - } - - } - else - { - value = iter->second.asString(); - } - - std::string name = iter->first; - std::transform(name.begin(), name.end(), name.begin(), - (int(*)(int))toupper); - args[name.c_str()] = value; - } - return args; + LLSD args = LLSD::emptyMap(); + std::string value; + LLSD cert_info; + cert->getLLSD(cert_info); + // convert all of the elements in the cert into + // args for the xml dialog, so we have flexability to + // display various parts of the cert by only modifying + // the cert alert dialog xml. + for(LLSD::map_iterator iter = cert_info.beginMap(); + iter != cert_info.endMap(); + iter++) + { + // key usage and extended key usage + // are actually arrays, and we want to format them as comma separated + // strings, so special case those. + LLSDSerialize::toXML(cert_info[iter->first], std::cout); + if((iter->first == std::string(CERT_KEY_USAGE)) || + (iter->first == std::string(CERT_EXTENDED_KEY_USAGE))) + { + value = ""; + LLSD usage = cert_info[iter->first]; + for (LLSD::array_iterator usage_iter = usage.beginArray(); + usage_iter != usage.endArray(); + usage_iter++) + { + + if(usage_iter != usage.beginArray()) + { + value += ", "; + } + + value += (*usage_iter).asString(); + } + + } + else + { + value = iter->second.asString(); + } + + std::string name = iter->first; + std::transform(name.begin(), name.end(), name.begin(), + (int(*)(int))toupper); + args[name.c_str()] = value; + } + return args; } // when we handle a cert error, give focus back to the login panel void general_cert_done(const LLSD& notification, const LLSD& response) { - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - LLPanelLogin::giveFocus(); + LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + LLPanelLogin::giveFocus(); } // check to see if the user wants to trust the cert. -// if they do, add it to the cert store and +// if they do, add it to the cert store and void trust_cert_done(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); - switch(option) - { - case OPT_TRUST_CERT: - { - LLPointer cert = gSecAPIHandler->getCertificate(notification["payload"]["certificate"]); - LLPointer store = gSecAPIHandler->getCertificateStore(gSavedSettings.getString("CertStore")); - store->add(cert); - store->save(); - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - break; - } - case OPT_CANCEL_TRUST: - reset_login(); - gSavedSettings.setBOOL("AutoLogin", FALSE); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - default: - LLPanelLogin::giveFocus(); - break; - } + S32 option = LLNotification::getSelectedOption(notification, response); + switch(option) + { + case OPT_TRUST_CERT: + { + LLPointer cert = gSecAPIHandler->getCertificate(notification["payload"]["certificate"]); + LLPointer store = gSecAPIHandler->getCertificateStore(gSavedSettings.getString("CertStore")); + store->add(cert); + store->save(); + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + break; + } + case OPT_CANCEL_TRUST: + reset_login(); + gSavedSettings.setBOOL("AutoLogin", FALSE); + LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + default: + LLPanelLogin::giveFocus(); + break; + } } void apply_udp_blacklist(const std::string& csv) { - std::string::size_type start = 0; - std::string::size_type comma = 0; - do - { - comma = csv.find(",", start); - if (comma == std::string::npos) - { - comma = csv.length(); - } - std::string item(csv, start, comma-start); - - LL_DEBUGS() << "udp_blacklist " << item << LL_ENDL; - gMessageSystem->banUdpMessage(item); - - start = comma + 1; - - } - while(comma < csv.length()); - + std::string::size_type start = 0; + std::string::size_type comma = 0; + do + { + comma = csv.find(",", start); + if (comma == std::string::npos) + { + comma = csv.length(); + } + std::string item(csv, start, comma-start); + + LL_DEBUGS() << "udp_blacklist " << item << LL_ENDL; + gMessageSystem->banUdpMessage(item); + + start = comma + 1; + + } + while(comma < csv.length()); + } void on_benefits_failed_callback(const LLSD& notification, const LLSD& response) { - LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL; + LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL; } bool init_benefits(LLSD& response) { - bool succ = true; - - std::string package_name = response["account_type"].asString(); - const LLSD& benefits_sd = response["account_level_benefits"]; - if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) || - !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd)) - { - succ = false; - } - else - { - LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL; - } - const LLSD& packages_sd = response["premium_packages"]; - for(LLSD::map_const_iterator package_iter = packages_sd.beginMap(); - package_iter != packages_sd.endMap(); - ++package_iter) - { - std::string package_name = package_iter->first; - const LLSD& benefits_sd = package_iter->second["benefits"]; - if (LLAgentBenefitsMgr::init(package_name, benefits_sd)) - { - LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL; - } - else - { - LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL; - succ = false; - } - } - - if (!LLAgentBenefitsMgr::has("Base")) - { - LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL; - succ = false; - } - if (!LLAgentBenefitsMgr::has("Premium")) - { - LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL; - succ = false; - } - - return succ; + bool succ = true; + + std::string package_name = response["account_type"].asString(); + const LLSD& benefits_sd = response["account_level_benefits"]; + if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) || + !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd)) + { + succ = false; + } + else + { + LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL; + } + const LLSD& packages_sd = response["premium_packages"]; + for(LLSD::map_const_iterator package_iter = packages_sd.beginMap(); + package_iter != packages_sd.endMap(); + ++package_iter) + { + std::string package_name = package_iter->first; + const LLSD& benefits_sd = package_iter->second["benefits"]; + if (LLAgentBenefitsMgr::init(package_name, benefits_sd)) + { + LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL; + } + else + { + LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL; + succ = false; + } + } + + if (!LLAgentBenefitsMgr::has("Base")) + { + LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL; + succ = false; + } + if (!LLAgentBenefitsMgr::has("Premium")) + { + LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL; + succ = false; + } + + return succ; } bool process_login_success_response() { - LLSD response = LLLoginInstance::getInstance()->getResponse(); - - mBenefitsSuccessfullyInit = init_benefits(response); - - std::string text(response["udp_blacklist"]); - if(!text.empty()) - { - apply_udp_blacklist(text); - } - - // unpack login data needed by the application - text = response["agent_id"].asString(); - if(!text.empty()) gAgentID.set(text); - gDebugInfo["AgentID"] = text; - - LLPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("PerfStatsCaptureEnabled")); - LLPerfStats::StatsRecorder::setFocusAv(gAgentID); - - // Agent id needed for parcel info request in LLUrlEntryParcel - // to resolve parcel name. - LLUrlEntryParcel::setAgentID(gAgentID); - - text = response["session_id"].asString(); - if(!text.empty()) gAgentSessionID.set(text); - gDebugInfo["SessionID"] = text; - - // Session id needed for parcel info request in LLUrlEntryParcel - // to resolve parcel name. - LLUrlEntryParcel::setSessionID(gAgentSessionID); - - text = response["secure_session_id"].asString(); - if(!text.empty()) gAgent.mSecureSessionID.set(text); - - // if the response contains a display name, use that, - // otherwise if the response contains a first and/or last name, - // use those. Otherwise use the credential identifier - - gDisplayName = ""; - if (response.has("display_name")) - { - gDisplayName.assign(response["display_name"].asString()); - if(!gDisplayName.empty()) - { - // Remove quotes from string. Login.cgi sends these to force - // names that look like numbers into strings. - LLStringUtil::replaceChar(gDisplayName, '"', ' '); - LLStringUtil::trim(gDisplayName); - } - } - std::string first_name; - if(response.has("first_name")) - { - first_name = response["first_name"].asString(); - LLStringUtil::replaceChar(first_name, '"', ' '); - LLStringUtil::trim(first_name); - gAgentUsername = first_name; - } - - if(response.has("last_name") && !gAgentUsername.empty()) - { - std::string last_name = response["last_name"].asString(); - if (last_name != "Resident") - { - LLStringUtil::replaceChar(last_name, '"', ' '); - LLStringUtil::trim(last_name); - gAgentUsername = gAgentUsername + " " + last_name; - } - } - - if(gDisplayName.empty()) - { - if(response.has("first_name")) - { - gDisplayName.assign(response["first_name"].asString()); - LLStringUtil::replaceChar(gDisplayName, '"', ' '); - LLStringUtil::trim(gDisplayName); - } - if(response.has("last_name")) - { - text.assign(response["last_name"].asString()); - LLStringUtil::replaceChar(text, '"', ' '); - LLStringUtil::trim(text); - if(!gDisplayName.empty()) - { - gDisplayName += " "; - } - gDisplayName += text; - } - } - - if(gDisplayName.empty()) - { - gDisplayName.assign(gUserCredential->asString()); - } - - // this is their actual ability to access content - text = response["agent_access_max"].asString(); - if (!text.empty()) - { - // agent_access can be 'A', 'M', and 'PG'. - gAgent.setMaturity(text[0]); - } - - // this is the value of their preference setting for that content - // which will always be <= agent_access_max - text = response["agent_region_access"].asString(); - if (!text.empty()) - { - U32 preferredMaturity = (U32)LLAgent::convertTextToMaturity(text[0]); - - gSavedSettings.setU32("PreferredMaturity", preferredMaturity); - } - - text = response["start_location"].asString(); - if(!text.empty()) - { - gAgentStartLocation.assign(text); - } - - text = response["circuit_code"].asString(); - if(!text.empty()) - { - gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10); - } - std::string sim_ip_str = response["sim_ip"]; - std::string sim_port_str = response["sim_port"]; - if(!sim_ip_str.empty() && !sim_port_str.empty()) - { - U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); - gFirstSim.set(sim_ip_str, sim_port); - if (gFirstSim.isOk()) - { - gMessageSystem->enableCircuit(gFirstSim, TRUE); - } - } - std::string region_x_str = response["region_x"]; - std::string region_y_str = response["region_y"]; - if(!region_x_str.empty() && !region_y_str.empty()) - { - U32 region_x = strtoul(region_x_str.c_str(), NULL, 10); - U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); - gFirstSimHandle = to_region_handle(region_x, region_y); - } - - const std::string look_at_str = response["look_at"]; - if (!look_at_str.empty()) - { - size_t len = look_at_str.size(); - LLMemoryStream mstr((U8*)look_at_str.c_str(), len); - LLSD sd = LLSDSerialize::fromNotation(mstr, len); - gAgentStartLookAt = ll_vector3_from_sd(sd); - } - - text = response["seed_capability"].asString(); - if (!text.empty()) gFirstSimSeedCap = text; - - text = response["seconds_since_epoch"].asString(); - if(!text.empty()) - { - U32 server_utc_time = strtoul(text.c_str(), NULL, 10); - if(server_utc_time) - { - time_t now = time(NULL); - gUTCOffset = (server_utc_time - now); - - // Print server timestamp - LLSD substitution; - substitution["datetime"] = (S32)server_utc_time; - std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]"; - LLStringUtil::format(timeStr, substitution); - LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL; - } - } - - // this is the base used to construct help URLs - text = response["help_url_format"].asString(); - if (!text.empty()) - { - // replace the default help URL format - gSavedSettings.setString("HelpURLFormat",text); - } - - std::string home_location = response["home"]; - if(!home_location.empty()) - { - size_t len = home_location.size(); - LLMemoryStream mstr((U8*)home_location.c_str(), len); - LLSD sd = LLSDSerialize::fromNotation(mstr, len); - S32 region_x = sd["region_handle"][0].asInteger(); - S32 region_y = sd["region_handle"][1].asInteger(); - U64 region_handle = to_region_handle(region_x, region_y); - LLVector3 position = ll_vector3_from_sd(sd["position"]); - gAgent.setHomePosRegion(region_handle, position); - } - - gAgent.mMOTD.assign(response["message"]); - - // Options... - // Each 'option' is an array of submaps. - // It appears that we only ever use the first element of the array. - LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"]; - if(inv_root_folder_id.notNull()) - { - gInventory.setRootFolderID(inv_root_folder_id); - //gInventory.mock(gAgent.getInventoryRootID()); - } - - LLSD login_flags = response["login-flags"][0]; - if(login_flags.size()) - { - std::string flag = login_flags["ever_logged_in"]; - if(!flag.empty()) - { - gAgent.setFirstLogin(flag == "N"); - } - - /* Flag is currently ignored by the viewer. - flag = login_flags["stipend_since_login"]; - if(flag == "Y") - { - stipend_since_login = true; - } - */ - - flag = login_flags["gendered"].asString(); - if(flag == "Y") - { - // We don't care about this flag anymore; now base whether - // outfit is chosen on COF contents, initial outfit - // requested and available, etc. - - //gAgent.setGenderChosen(TRUE); - } - - bool pacific_daylight_time = false; - flag = login_flags["daylight_savings"].asString(); - if(flag == "Y") - { - pacific_daylight_time = (flag == "Y"); - } - - //setup map of datetime strings to codes and slt & local time offset from utc - LLStringOps::setupDatetimeInfo(pacific_daylight_time); - } - - // set up the voice configuration. Ultimately, we should pass this up as part of each voice - // channel if we need to move to multiple voice servers per grid. - LLSD voice_config_info = response["voice-config"]; - if(voice_config_info.has("VoiceServerType")) - { - gSavedSettings.setString("VoiceServerType", voice_config_info["VoiceServerType"].asString()); - } - - // Request the map server url - std::string map_server_url = response["map-server-url"]; - if(!map_server_url.empty()) - { - // We got an answer from the grid -> use that for map for the current session - gSavedSettings.setString("CurrentMapServerURL", map_server_url); - LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL; - } - else - { - // No answer from the grid -> use the default setting for current session - map_server_url = gSavedSettings.getString("MapServerURL"); - gSavedSettings.setString("CurrentMapServerURL", map_server_url); - LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL; - } - - // Default male and female avatars allowing the user to choose their avatar on first login. - // These may be passed up by SLE to allow choice of enterprise avatars instead of the standard - // "new ruth." Not to be confused with 'initial-outfit' below - LLSD newuser_config = response["newuser-config"][0]; - if(newuser_config.has("DefaultFemaleAvatar")) - { - gSavedSettings.setString("DefaultFemaleAvatar", newuser_config["DefaultFemaleAvatar"].asString()); - } - if(newuser_config.has("DefaultMaleAvatar")) - { - gSavedSettings.setString("DefaultMaleAvatar", newuser_config["DefaultMaleAvatar"].asString()); - } - - // Initial outfit for the user. - LLSD initial_outfit = response["initial-outfit"][0]; - if(initial_outfit.size()) - { - std::string flag = initial_outfit["folder_name"]; - if(!flag.empty()) - { - // Initial outfit is a folder in your inventory, - // must be an exact folder-name match. - sInitialOutfit = flag; - } - - flag = initial_outfit["gender"].asString(); - if(!flag.empty()) - { - sInitialOutfitGender = flag; - } - } - - std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName"); - if (!fake_initial_outfit_name.empty()) - { - gAgent.setFirstLogin(true); - sInitialOutfit = fake_initial_outfit_name; - if (sInitialOutfitGender.empty()) - { - sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway. - } - - LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL; - } - - // set the location of the Agent Appearance service, from which we can request - // avatar baked textures if they are supported by the current region - std::string agent_appearance_url = response["agent_appearance_service"]; - if (!agent_appearance_url.empty()) - { - LLAppearanceMgr::instance().setAppearanceServiceURL(agent_appearance_url); - } - - // Set the location of the snapshot sharing config endpoint - std::string snapshot_config_url = response["snapshot_config_url"]; - if(!snapshot_config_url.empty()) - { - gSavedSettings.setString("SnapshotConfigURL", snapshot_config_url); - } - - // Start the process of fetching the OpenID session cookie for this user login - std::string openid_url = response["openid_url"]; - if(!openid_url.empty()) - { - std::string openid_token = response["openid_token"]; - LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token); - } - - - // Only save mfa_hash for future logins if the user wants their info remembered. - if(response.has("mfa_hash") + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + mBenefitsSuccessfullyInit = init_benefits(response); + + std::string text(response["udp_blacklist"]); + if(!text.empty()) + { + apply_udp_blacklist(text); + } + + // unpack login data needed by the application + text = response["agent_id"].asString(); + if(!text.empty()) gAgentID.set(text); + gDebugInfo["AgentID"] = text; + + LLPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("PerfStatsCaptureEnabled")); + LLPerfStats::StatsRecorder::setFocusAv(gAgentID); + + // Agent id needed for parcel info request in LLUrlEntryParcel + // to resolve parcel name. + LLUrlEntryParcel::setAgentID(gAgentID); + + text = response["session_id"].asString(); + if(!text.empty()) gAgentSessionID.set(text); + gDebugInfo["SessionID"] = text; + + // Session id needed for parcel info request in LLUrlEntryParcel + // to resolve parcel name. + LLUrlEntryParcel::setSessionID(gAgentSessionID); + + text = response["secure_session_id"].asString(); + if(!text.empty()) gAgent.mSecureSessionID.set(text); + + // if the response contains a display name, use that, + // otherwise if the response contains a first and/or last name, + // use those. Otherwise use the credential identifier + + gDisplayName = ""; + if (response.has("display_name")) + { + gDisplayName.assign(response["display_name"].asString()); + if(!gDisplayName.empty()) + { + // Remove quotes from string. Login.cgi sends these to force + // names that look like numbers into strings. + LLStringUtil::replaceChar(gDisplayName, '"', ' '); + LLStringUtil::trim(gDisplayName); + } + } + std::string first_name; + if(response.has("first_name")) + { + first_name = response["first_name"].asString(); + LLStringUtil::replaceChar(first_name, '"', ' '); + LLStringUtil::trim(first_name); + gAgentUsername = first_name; + } + + if(response.has("last_name") && !gAgentUsername.empty()) + { + std::string last_name = response["last_name"].asString(); + if (last_name != "Resident") + { + LLStringUtil::replaceChar(last_name, '"', ' '); + LLStringUtil::trim(last_name); + gAgentUsername = gAgentUsername + " " + last_name; + } + } + + if(gDisplayName.empty()) + { + if(response.has("first_name")) + { + gDisplayName.assign(response["first_name"].asString()); + LLStringUtil::replaceChar(gDisplayName, '"', ' '); + LLStringUtil::trim(gDisplayName); + } + if(response.has("last_name")) + { + text.assign(response["last_name"].asString()); + LLStringUtil::replaceChar(text, '"', ' '); + LLStringUtil::trim(text); + if(!gDisplayName.empty()) + { + gDisplayName += " "; + } + gDisplayName += text; + } + } + + if(gDisplayName.empty()) + { + gDisplayName.assign(gUserCredential->asString()); + } + + // this is their actual ability to access content + text = response["agent_access_max"].asString(); + if (!text.empty()) + { + // agent_access can be 'A', 'M', and 'PG'. + gAgent.setMaturity(text[0]); + } + + // this is the value of their preference setting for that content + // which will always be <= agent_access_max + text = response["agent_region_access"].asString(); + if (!text.empty()) + { + U32 preferredMaturity = (U32)LLAgent::convertTextToMaturity(text[0]); + + gSavedSettings.setU32("PreferredMaturity", preferredMaturity); + } + + text = response["start_location"].asString(); + if(!text.empty()) + { + gAgentStartLocation.assign(text); + } + + text = response["circuit_code"].asString(); + if(!text.empty()) + { + gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10); + } + std::string sim_ip_str = response["sim_ip"]; + std::string sim_port_str = response["sim_port"]; + if(!sim_ip_str.empty() && !sim_port_str.empty()) + { + U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); + gFirstSim.set(sim_ip_str, sim_port); + if (gFirstSim.isOk()) + { + gMessageSystem->enableCircuit(gFirstSim, TRUE); + } + } + std::string region_x_str = response["region_x"]; + std::string region_y_str = response["region_y"]; + if(!region_x_str.empty() && !region_y_str.empty()) + { + U32 region_x = strtoul(region_x_str.c_str(), NULL, 10); + U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); + gFirstSimHandle = to_region_handle(region_x, region_y); + } + + const std::string look_at_str = response["look_at"]; + if (!look_at_str.empty()) + { + size_t len = look_at_str.size(); + LLMemoryStream mstr((U8*)look_at_str.c_str(), len); + LLSD sd = LLSDSerialize::fromNotation(mstr, len); + gAgentStartLookAt = ll_vector3_from_sd(sd); + } + + text = response["seed_capability"].asString(); + if (!text.empty()) gFirstSimSeedCap = text; + + text = response["seconds_since_epoch"].asString(); + if(!text.empty()) + { + U32 server_utc_time = strtoul(text.c_str(), NULL, 10); + if(server_utc_time) + { + time_t now = time(NULL); + gUTCOffset = (server_utc_time - now); + + // Print server timestamp + LLSD substitution; + substitution["datetime"] = (S32)server_utc_time; + std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]"; + LLStringUtil::format(timeStr, substitution); + LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL; + } + } + + // this is the base used to construct help URLs + text = response["help_url_format"].asString(); + if (!text.empty()) + { + // replace the default help URL format + gSavedSettings.setString("HelpURLFormat",text); + } + + std::string home_location = response["home"]; + if(!home_location.empty()) + { + size_t len = home_location.size(); + LLMemoryStream mstr((U8*)home_location.c_str(), len); + LLSD sd = LLSDSerialize::fromNotation(mstr, len); + S32 region_x = sd["region_handle"][0].asInteger(); + S32 region_y = sd["region_handle"][1].asInteger(); + U64 region_handle = to_region_handle(region_x, region_y); + LLVector3 position = ll_vector3_from_sd(sd["position"]); + gAgent.setHomePosRegion(region_handle, position); + } + + gAgent.mMOTD.assign(response["message"]); + + // Options... + // Each 'option' is an array of submaps. + // It appears that we only ever use the first element of the array. + LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"]; + if(inv_root_folder_id.notNull()) + { + gInventory.setRootFolderID(inv_root_folder_id); + //gInventory.mock(gAgent.getInventoryRootID()); + } + + LLSD login_flags = response["login-flags"][0]; + if(login_flags.size()) + { + std::string flag = login_flags["ever_logged_in"]; + if(!flag.empty()) + { + gAgent.setFirstLogin(flag == "N"); + } + + /* Flag is currently ignored by the viewer. + flag = login_flags["stipend_since_login"]; + if(flag == "Y") + { + stipend_since_login = true; + } + */ + + flag = login_flags["gendered"].asString(); + if(flag == "Y") + { + // We don't care about this flag anymore; now base whether + // outfit is chosen on COF contents, initial outfit + // requested and available, etc. + + //gAgent.setGenderChosen(TRUE); + } + + bool pacific_daylight_time = false; + flag = login_flags["daylight_savings"].asString(); + if(flag == "Y") + { + pacific_daylight_time = (flag == "Y"); + } + + //setup map of datetime strings to codes and slt & local time offset from utc + LLStringOps::setupDatetimeInfo(pacific_daylight_time); + } + + // set up the voice configuration. Ultimately, we should pass this up as part of each voice + // channel if we need to move to multiple voice servers per grid. + LLSD voice_config_info = response["voice-config"]; + if(voice_config_info.has("VoiceServerType")) + { + gSavedSettings.setString("VoiceServerType", voice_config_info["VoiceServerType"].asString()); + } + + // Request the map server url + std::string map_server_url = response["map-server-url"]; + if(!map_server_url.empty()) + { + // We got an answer from the grid -> use that for map for the current session + gSavedSettings.setString("CurrentMapServerURL", map_server_url); + LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL; + } + else + { + // No answer from the grid -> use the default setting for current session + map_server_url = gSavedSettings.getString("MapServerURL"); + gSavedSettings.setString("CurrentMapServerURL", map_server_url); + LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL; + } + + // Default male and female avatars allowing the user to choose their avatar on first login. + // These may be passed up by SLE to allow choice of enterprise avatars instead of the standard + // "new ruth." Not to be confused with 'initial-outfit' below + LLSD newuser_config = response["newuser-config"][0]; + if(newuser_config.has("DefaultFemaleAvatar")) + { + gSavedSettings.setString("DefaultFemaleAvatar", newuser_config["DefaultFemaleAvatar"].asString()); + } + if(newuser_config.has("DefaultMaleAvatar")) + { + gSavedSettings.setString("DefaultMaleAvatar", newuser_config["DefaultMaleAvatar"].asString()); + } + + // Initial outfit for the user. + LLSD initial_outfit = response["initial-outfit"][0]; + if(initial_outfit.size()) + { + std::string flag = initial_outfit["folder_name"]; + if(!flag.empty()) + { + // Initial outfit is a folder in your inventory, + // must be an exact folder-name match. + sInitialOutfit = flag; + } + + flag = initial_outfit["gender"].asString(); + if(!flag.empty()) + { + sInitialOutfitGender = flag; + } + } + + std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName"); + if (!fake_initial_outfit_name.empty()) + { + gAgent.setFirstLogin(true); + sInitialOutfit = fake_initial_outfit_name; + if (sInitialOutfitGender.empty()) + { + sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway. + } + + LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL; + } + + // set the location of the Agent Appearance service, from which we can request + // avatar baked textures if they are supported by the current region + std::string agent_appearance_url = response["agent_appearance_service"]; + if (!agent_appearance_url.empty()) + { + LLAppearanceMgr::instance().setAppearanceServiceURL(agent_appearance_url); + } + + // Set the location of the snapshot sharing config endpoint + std::string snapshot_config_url = response["snapshot_config_url"]; + if(!snapshot_config_url.empty()) + { + gSavedSettings.setString("SnapshotConfigURL", snapshot_config_url); + } + + // Start the process of fetching the OpenID session cookie for this user login + std::string openid_url = response["openid_url"]; + if(!openid_url.empty()) + { + std::string openid_token = response["openid_token"]; + LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token); + } + + + // Only save mfa_hash for future logins if the user wants their info remembered. + if(response.has("mfa_hash") && gSavedSettings.getBOOL("RememberUser") && LLLoginInstance::getInstance()->saveMFA()) - { - std::string grid(LLGridManager::getInstance()->getGridId()); - std::string user_id(gUserCredential->userID()); - gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, response["mfa_hash"]); - // TODO(brad) - related to SL-17223 consider building a better interface that sync's automatically - gSecAPIHandler->syncProtectedMap(); - } + { + std::string grid(LLGridManager::getInstance()->getGridId()); + std::string user_id(gUserCredential->userID()); + gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, response["mfa_hash"]); + // TODO(brad) - related to SL-17223 consider building a better interface that sync's automatically + gSecAPIHandler->syncProtectedMap(); + } else if (!LLLoginInstance::getInstance()->saveMFA()) { std::string grid(LLGridManager::getInstance()->getGridId()); @@ -3867,26 +3867,26 @@ bool process_login_success_response() gSecAPIHandler->syncProtectedMap(); } - bool success = false; - // JC: gesture loading done below, when we have an asset system - // in place. Don't delete/clear gUserCredentials until then. - if(gAgentID.notNull() - && gAgentSessionID.notNull() - && gMessageSystem->mOurCircuitCode - && gFirstSim.isOk() - && gInventory.getRootFolderID().notNull()) - { - success = true; - } + bool success = false; + // JC: gesture loading done below, when we have an asset system + // in place. Don't delete/clear gUserCredentials until then. + if(gAgentID.notNull() + && gAgentSessionID.notNull() + && gMessageSystem->mOurCircuitCode + && gFirstSim.isOk() + && gInventory.getRootFolderID().notNull()) + { + success = true; + } LLAppViewer* pApp = LLAppViewer::instance(); - pApp->writeDebugInfo(); //Write our static data now that we have username, session_id, etc. - return success; + pApp->writeDebugInfo(); //Write our static data now that we have username, session_id, etc. + return success; } void transition_back_to_login_panel(const std::string& emsg) { - // Bounce back to the login screen. - reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - gSavedSettings.setBOOL("AutoLogin", FALSE); + // Bounce back to the login screen. + reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + gSavedSettings.setBOOL("AutoLogin", FALSE); } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llstartup.cpp | 7752 +++++++++++++++++++++---------------------- 1 file changed, 3876 insertions(+), 3876 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0b8cb4163b..384c8caf90 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1,3876 +1,3876 @@ -/** - * @file llstartup.cpp - * @brief startup routines. - * - * $LicenseInfo:firstyear=2004&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 "llviewerprecompiledheaders.h" - -#include "llappviewer.h" -#include "llstartup.h" -#include "llcallstack.h" - -#if LL_WINDOWS -# include // _spawnl() -#else -# include // mkdir() -#endif -#include // std::unique_ptr - -#include "llviewermedia_streamingaudio.h" -#include "llaudioengine.h" - -#ifdef LL_OPENAL -#include "llaudioengine_openal.h" -#endif - -#include "llavatarnamecache.h" -#include "llexperiencecache.h" -#include "lllandmark.h" -#include "llcachename.h" -#include "lldir.h" -#include "lldonotdisturbnotificationstorage.h" -#include "llerrorcontrol.h" -#include "llfloaterreg.h" -#include "llfocusmgr.h" -#include "llfloatergridstatus.h" -#include "llfloaterimsession.h" -#include "lllocationhistory.h" -#include "llgltfmateriallist.h" -#include "llimageworker.h" - -#include "llloginflags.h" -#include "llmd5.h" -#include "llmemorystream.h" -#include "llmessageconfig.h" -#include "llmoveview.h" -#include "llfloaterimcontainer.h" -#include "llfloaterimnearbychat.h" -#include "llnotifications.h" -#include "llnotificationsutil.h" -#include "llpersistentnotificationstorage.h" -#include "llpresetsmanager.h" -#include "llteleporthistory.h" -#include "llregionhandle.h" -#include "llsd.h" -#include "llsdserialize.h" -#include "llsdutil_math.h" -#include "llstring.h" -#include "lluserrelations.h" -#include "llversioninfo.h" -#include "llviewercontrol.h" -#include "llviewerhelp.h" -#include "llxorcipher.h" // saved password, MAC address -#include "llwindow.h" -#include "message.h" -#include "v3math.h" - -#include "llagent.h" -#include "llagentbenefits.h" -#include "llagentcamera.h" -#include "llagentpicksinfo.h" -#include "llagentwearables.h" -#include "llagentpilot.h" -#include "llfloateravatarpicker.h" -#include "llcallbacklist.h" -#include "llcallingcard.h" -#include "llclassifiedinfo.h" -#include "llconsole.h" -#include "llcontainerview.h" -#include "llconversationlog.h" -#include "lldebugview.h" -#include "lldrawable.h" -#include "lleventnotifier.h" -#include "llface.h" -#include "llfeaturemanager.h" -//#include "llfirstuse.h" -#include "llfloaterhud.h" -#include "llfloaterland.h" -#include "llfloatertopobjects.h" -#include "llfloaterworldmap.h" -#include "llgesturemgr.h" -#include "llgroupmgr.h" -#include "llhudeffecttrail.h" -#include "llhudmanager.h" -#include "llimage.h" -#include "llinventorybridge.h" -#include "llinventorymodel.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llkeyboard.h" -#include "llloginhandler.h" // gLoginHandler, SLURL support -#include "lllogininstance.h" // Host the login module. -#include "llpanellogin.h" -#include "llmutelist.h" -#include "llavatarpropertiesprocessor.h" -#include "llpanelgrouplandmoney.h" -#include "llpanelgroupnotices.h" -#include "llparcel.h" -#include "llpreview.h" -#include "llpreviewscript.h" -#include "llproxy.h" -#include "llproductinforequest.h" -#include "llqueryflags.h" -#include "llsecapi.h" -#include "llselectmgr.h" -#include "llsky.h" -#include "llstatview.h" -#include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance -#include "llsurface.h" -#include "lltexturecache.h" -#include "lltexturefetch.h" -#include "lltoolmgr.h" -#include "lltrans.h" -#include "llui.h" -#include "lluiusage.h" -#include "llurldispatcher.h" -#include "llurlentry.h" -#include "llslurl.h" -#include "llurlhistory.h" -#include "llurlwhitelist.h" -#include "llvieweraudio.h" -#include "llviewerassetstorage.h" -#include "llviewercamera.h" -#include "llviewerdisplay.h" -#include "llviewergenericmessage.h" -#include "llviewergesture.h" -#include "llviewertexturelist.h" -#include "llviewermedia.h" -#include "llviewermenu.h" -#include "llviewermessage.h" -#include "llviewernetwork.h" -#include "llviewerobjectlist.h" -#include "llviewerparcelaskplay.h" -#include "llviewerparcelmedia.h" -#include "llviewerparcelmgr.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llviewerstatsrecorder.h" -#include "llviewerthrottle.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llvoavatarself.h" -#include "llweb.h" -#include "llworld.h" -#include "llworldmapmessage.h" -#include "llxfermanager.h" -#include "pipeline.h" -#include "llappviewer.h" -#include "llfasttimerview.h" -#include "llfloatermap.h" -#include "llweb.h" -#include "llvoiceclient.h" -#include "llnamelistctrl.h" -#include "llnamebox.h" -#include "llnameeditor.h" -#include "llpostprocess.h" -#include "llagentlanguage.h" -#include "llwearable.h" -#include "llinventorybridge.h" -#include "llappearancemgr.h" -#include "llavatariconctrl.h" -#include "llvoicechannel.h" -#include "llpathfindingmanager.h" -#include "llremoteparcelrequest.h" - -#include "lllogin.h" -#include "llevents.h" -#include "llstartuplistener.h" -#include "lltoolbarview.h" -#include "llexperiencelog.h" -#include "llcleanup.h" - -#include "llenvironment.h" - -#include "llstacktrace.h" - -#include "threadpool.h" -#include "llperfstats.h" - - -#if LL_WINDOWS -#include "lldxhardware.h" -#endif - -// -// exported globals -// -bool gAgentMovementCompleted = false; - -const std::string SCREEN_HOME_FILENAME = "screen_home%s.png"; -const std::string SCREEN_LAST_FILENAME = "screen_last%s.png"; - -LLPointer gStartTexture; - -// -// Imported globals -// -extern S32 gStartImageWidth; -extern S32 gStartImageHeight; - -// -// local globals -// -static bool gGotUseCircuitCodeAck = false; -static std::string sInitialOutfit; -static std::string sInitialOutfitGender; // "male" or "female" - -static bool gUseCircuitCallbackCalled = false; - -EStartupState LLStartUp::gStartupState = STATE_FIRST; -LLSLURL LLStartUp::sStartSLURL; - -static LLPointer gUserCredential; -static std::string gDisplayName; -static bool gRememberPassword = true; -static bool gRememberUser = true; - -static U64 gFirstSimHandle = 0; -static LLHost gFirstSim; -static std::string gFirstSimSeedCap; -static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f); -static std::string gAgentStartLocation = "safe"; -static bool mLoginStatePastUI = false; -static bool mBenefitsSuccessfullyInit = false; - -const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds -const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT = 4; // Give region 4 chances - -std::unique_ptr LLStartUp::sStateWatcher(new LLEventStream("StartupState")); -std::unique_ptr LLStartUp::sListener(new LLStartupListener()); -std::unique_ptr LLStartUp::sPhases(new LLViewerStats::PhaseMap); - -// -// local function declaration -// - -void login_show(); -void login_callback(S32 option, void* userdata); -void show_release_notes_if_required(); -void show_first_run_dialog(); -bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); -void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); -bool login_alert_status(const LLSD& notification, const LLSD& response); -void use_circuit_callback(void**, S32 result); -void register_viewer_callbacks(LLMessageSystem* msg); -void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32); -bool callback_choose_gender(const LLSD& notification, const LLSD& response); -void release_start_screen(); -void reset_login(); -LLSD transform_cert_args(LLPointer cert); -void general_cert_done(const LLSD& notification, const LLSD& response); -void trust_cert_done(const LLSD& notification, const LLSD& response); -void apply_udp_blacklist(const std::string& csv); -bool process_login_success_response(); -void on_benefits_failed_callback(const LLSD& notification, const LLSD& response); -void transition_back_to_login_panel(const std::string& emsg); - -void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group) -{ - LLNameBox::refreshAll(id, full_name, is_group); - LLNameEditor::refreshAll(id, full_name, is_group); - - // TODO: Actually be intelligent about the refresh. - // For now, just brute force refresh the dialogs. - dialog_refresh_all(); -} - -// -// exported functionality -// - -void pump_idle_startup_network(void) -{ - { - LockMessageChecker lmc(gMessageSystem); - while (lmc.checkAllMessages(gFrameCount, gServicePump)) - { - display_startup(); - } - lmc.processAcks(); - } - display_startup(); -} - -// -// local classes -// -void update_texture_fetch() -{ - LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread - LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread - LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread - gTextureList.updateImages(0.10f); - - if (LLImageGLThread::sEnabledTextures) - { - std::shared_ptr main_queue = LL::WorkQueue::getInstance("mainloop"); - main_queue->runFor(std::chrono::milliseconds(1)); - } -} - -void set_flags_and_update_appearance() -{ - LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); - LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op); - - LLInventoryModelBackgroundFetch::instance().start(); -} - -// Returns false to skip other idle processing. Should only return -// true when all initialization done. -bool idle_startup() -{ - if (gViewerWindow == NULL) - { - // We expect window to be initialized - LL_WARNS_ONCE() << "gViewerWindow is not initialized" << LL_ENDL; - return false; // No world yet - } - - const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay"); - static LLTimer timeout; - - static LLTimer login_time; - - // until this is encapsulated, this little hack for the - // auth/transform loop will do. - static F32 progress = 0.10f; - - static std::string auth_desc; - static std::string auth_message; - - static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server - - // last location by default - static S32 agent_location_id = START_LOCATION_ID_LAST; - - static bool show_connect_box = true; - - //static bool stipend_since_login = false; - - // HACK: These are things from the main loop that usually aren't done - // until initialization is complete, but need to be done here for things - // to work. - gIdleCallbacks.callFunctions(); - gViewerWindow->updateUI(); - - LLMortician::updateClass(); - - const std::string delims (" "); - std::string system; - int begIdx, endIdx; - std::string osString = LLOSInfo::instance().getOSStringSimple(); - - begIdx = osString.find_first_not_of (delims); - endIdx = osString.find_first_of (delims, begIdx); - system = osString.substr (begIdx, endIdx - begIdx); - system += "Locale"; - - LLStringUtil::setLocale (LLTrans::getString(system)); - - //note: Removing this line will cause incorrect button size in the login screen. -- bao. - gTextureList.updateImages(0.01f) ; - - if ( STATE_FIRST == LLStartUp::getStartupState() ) - { - static bool first_call = true; - if (first_call) - { - // Other phases get handled when startup state changes, - // need to capture the initial state as well. - LLStartUp::getPhases().startPhase(LLStartUp::getStartupStateString()); - first_call = false; - } - - gViewerWindow->showCursor(); - gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); - - ///////////////////////////////////////////////// - // - // Initialize stuff that doesn't need data from simulators - // - std::string lastGPU = gSavedSettings.getString("LastGPUString"); - std::string thisGPU = LLFeatureManager::getInstance()->getGPUString(); - - if (LLFeatureManager::getInstance()->isSafe()) - { - LLNotificationsUtil::add("DisplaySetToSafe"); - } - else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) && - (gSavedSettings.getS32("LastFeatureVersion") != 0)) - { - LLNotificationsUtil::add("DisplaySetToRecommendedFeatureChange"); - } - else if ( ! lastGPU.empty() && (lastGPU != thisGPU)) - { - LLSD subs; - subs["LAST_GPU"] = lastGPU; - subs["THIS_GPU"] = thisGPU; - LLNotificationsUtil::add("DisplaySetToRecommendedGPUChange", subs); - } - else if (!gViewerWindow->getInitAlert().empty()) - { - LLNotificationsUtil::add(gViewerWindow->getInitAlert()); - } - - //------------------------------------------------- - // Init the SOCKS 5 proxy if the user has configured - // one. We need to do this early in case the user - // is using SOCKS for HTTP so we get the login - // screen and HTTP tables via SOCKS. - //------------------------------------------------- - LLStartUp::startLLProxy(); - - gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion()); - gSavedSettings.setString("LastGPUString", thisGPU); - - - std::string xml_file = LLUI::locateSkin("xui_version.xml"); - LLXMLNodePtr root; - bool xml_ok = false; - if (LLXMLNode::parseFile(xml_file, root, NULL)) - { - if( (root->hasName("xui_version") ) ) - { - std::string value = root->getValue(); - F32 version = 0.0f; - LLStringUtil::convertToF32(value, version); - if (version >= 1.0f) - { - xml_ok = true; - } - } - } - if (!xml_ok) - { - // If XML is bad, there's a good possibility that notifications.xml is ALSO bad. - // If that's so, then we'll get a fatal error on attempting to load it, - // which will display a nontranslatable error message that says so. - // Otherwise, we'll display a reasonable error message that IS translatable. - LLAppViewer::instance()->earlyExit("BadInstallation"); - } - // - // Statistics stuff - // - - // Load autopilot and stats stuff - gAgentPilot.load(); - - //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps")); - - // Load the throttle settings - gViewerThrottle.load(); - - // - // Initialize messaging system - // - LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL; - - std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); - - LLFILE* found_template = NULL; - found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */ - - #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message_template.msg - // file will be located in: - // build-vc**/newview//app_settings - if (!found_template) - { - message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg"); - found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ - } - #elif LL_DARWIN - // On Mac dev builds, message_template.msg lives in: - // indra/build-*/newview//Second Life/Contents/Resources/app_settings - if (!found_template) - { - message_template_path = - gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, - "message_template.msg"); - found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ - } - #endif - - if (found_template) - { - fclose(found_template); - - U32 port = gSavedSettings.getU32("UserConnectionPort"); - - if ((NET_USE_OS_ASSIGNED_PORT == port) && // if nothing specified on command line (-port) - (gSavedSettings.getBOOL("ConnectionPortEnabled"))) - { - port = gSavedSettings.getU32("ConnectionPort"); - } - - // TODO parameterize - const F32 circuit_heartbeat_interval = 5; - const F32 circuit_timeout = 100; - - const LLUseCircuitCodeResponder* responder = NULL; - bool failure_is_fatal = true; - - if(!start_messaging_system( - message_template_path, - port, - LLVersionInfo::instance().getMajor(), - LLVersionInfo::instance().getMinor(), - LLVersionInfo::instance().getPatch(), - false, - std::string(), - responder, - failure_is_fatal, - circuit_heartbeat_interval, - circuit_timeout)) - { - std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode()); - LL_WARNS("AppInit") << diagnostic << LL_ENDL; - LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic)); - } - - #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message.xml file will - // be located in indra/build-vc**/newview//app_settings. - std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml"); - - if (!LLFile::isfile(message_path.c_str())) - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "")); - } - else - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - } - #else - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - #endif - - } - else - { - LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path)); - } - - if(gMessageSystem && gMessageSystem->isOK()) - { - // Initialize all of the callbacks in case of bad message - // system data - LLMessageSystem* msg = gMessageSystem; - msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE, - invalid_message_callback, - NULL); - msg->setExceptionFunc(MX_PACKET_TOO_SHORT, - invalid_message_callback, - NULL); - - // running off end of a packet is now valid in the case - // when a reader has a newer message template than - // the sender - /*msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET, - invalid_message_callback, - NULL);*/ - msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE, - invalid_message_callback, - NULL); - - if (gSavedSettings.getBOOL("LogMessages")) - { - LL_DEBUGS("AppInit") << "Message logging activated!" << LL_ENDL; - msg->startLogging(); - } - - // start the xfer system. by default, choke the downloads - // a lot... - const S32 VIEWER_MAX_XFER = 3; - start_xfer_manager(); - gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER); - F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle"); - if (xfer_throttle_bps > 1.f) - { - gXferManager->setUseAckThrottling(true); - gXferManager->setAckThrottleBPS(xfer_throttle_bps); - } - gAssetStorage = new LLViewerAssetStorage(msg, gXferManager); - - - F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage"); - msg->mPacketRing.setDropPercentage(dropPercent); - - F32 inBandwidth = gSavedSettings.getF32("InBandwidth"); - F32 outBandwidth = gSavedSettings.getF32("OutBandwidth"); - if (inBandwidth != 0.f) - { - LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL; - msg->mPacketRing.setUseInThrottle(true); - msg->mPacketRing.setInBandwidth(inBandwidth); - } - if (outBandwidth != 0.f) - { - LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL; - msg->mPacketRing.setUseOutThrottle(true); - msg->mPacketRing.setOutBandwidth(outBandwidth); - } - } - - LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; - - //------------------------------------------------- - // Init audio, which may be needed for prefs dialog - // or audio cues in connection UI. - //------------------------------------------------- - - if (false == gSavedSettings.getBOOL("NoAudio")) - { - delete gAudiop; - gAudiop = NULL; - -#ifdef LL_OPENAL -#if !LL_WINDOWS - if (NULL == getenv("LL_BAD_OPENAL_DRIVER")) -#endif // !LL_WINDOWS - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); - } -#endif - - if (gAudiop) - { -#if LL_WINDOWS - // FMOD Ex on Windows needs the window handle to stop playing audio - // when window is minimized. JC - void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); -#else - void* window_handle = NULL; -#endif - if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle())) - { - LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; - gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); - - gAudiop->setMuted(true); - } - else - { - LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; - delete gAudiop; - gAudiop = NULL; - } - } - } - - LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; - - if (LLTimer::knownBadTimer()) - { - LL_WARNS("AppInit") << "Unreliable timers detected (may be bad PCI chipset)!!" << LL_ENDL; - } - - // - // Log on to system - // - if (gUserCredential.isNull()) - { - gUserCredential = gLoginHandler.initializeLoginInfo(); - } - // Previous initializeLoginInfo may have generated user credentials. Re-check them. - if (gUserCredential.isNull()) - { - show_connect_box = true; - } - else if (gSavedSettings.getBOOL("AutoLogin")) - { - // Log into last account - gRememberPassword = true; - gRememberUser = true; - gSavedSettings.setBOOL("RememberPassword", true); - gSavedSettings.setBOOL("RememberUser", true); - show_connect_box = false; - } - else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3) - { - // Console provided login&password - gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); - gRememberUser = gSavedSettings.getBOOL("RememberUser"); - show_connect_box = false; - } - else - { - gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); - gRememberUser = gSavedSettings.getBOOL("RememberUser"); - show_connect_box = true; - } - - //setup map of datetime strings to codes and slt & local time offset from utc - // *TODO: Does this need to be here? - LLStringOps::setupDatetimeInfo(false); - - // Go to the next startup state - LLStartUp::setStartupState( STATE_BROWSER_INIT ); - return false; - } - - - if (STATE_BROWSER_INIT == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL; - std::string msg = LLTrans::getString("LoginInitializingBrowser"); - set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); - // LLViewerMedia::initBrowser(); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - return false; - } - - - if (STATE_LOGIN_SHOW == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "Initializing Window, show_connect_box = " - << show_connect_box << LL_ENDL; - - // if we've gone backwards in the login state machine, to this state where we show the UI - // AND the debug setting to exit in this case is true, then go ahead and bail quickly - if ( mLoginStatePastUI && gSavedSettings.getBOOL("QuitOnLoginActivated") ) - { - LL_DEBUGS("AppInit") << "taking QuitOnLoginActivated exit" << LL_ENDL; - // no requirement for notification here - just exit - LLAppViewer::instance()->earlyExitNoNotify(); - } - - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - - // Login screen needs menus for preferences, but we can enter - // this startup phase more than once. - if (gLoginMenuBarView == NULL) - { - LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL; - initialize_spellcheck_menu(); - init_menus(); - } - show_release_notes_if_required(); - - if (show_connect_box) - { - LL_DEBUGS("AppInit") << "show_connect_box on" << LL_ENDL; - // Load all the name information out of the login view - // NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't - // show the login view until login_show() is called below. - if (gUserCredential.isNull()) - { - LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL; - gUserCredential = gLoginHandler.initializeLoginInfo(); - } - // Make sure the process dialog doesn't hide things - gViewerWindow->setShowProgress(false); - // Show the login dialog - login_show(); - // connect dialog is already shown, so fill in the names - LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword); - LLPanelLogin::giveFocus(); - - // MAINT-3231 Show first run dialog only for Desura viewer - if (gSavedSettings.getString("sourceid") == "1208_desura") - { - if (gSavedSettings.getBOOL("FirstLoginThisInstall")) - { - LL_INFOS("AppInit") << "FirstLoginThisInstall, calling show_first_run_dialog()" << LL_ENDL; - show_first_run_dialog(); - } - else - { - LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; - } - } - display_startup(); - LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input - } - else - { - LL_DEBUGS("AppInit") << "show_connect_box off, skipping to STATE_LOGIN_CLEANUP" << LL_ENDL; - // skip directly to message template verification - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - } - - gViewerWindow->setNormalControlsVisible( false ); - gLoginMenuBarView->setVisible( true ); - gLoginMenuBarView->setEnabled( true ); - show_debug_menus(); - - // Hide the splash screen - LL_DEBUGS("AppInit") << "Hide the splash screen and show window" << LL_ENDL; - LLSplashScreen::hide(); - // Push our window frontmost - gViewerWindow->getWindow()->show(); - - // DEV-16927. The following code removes errant keystrokes that happen while the window is being - // first made visible. -#ifdef _WIN32 - LL_DEBUGS("AppInit") << "Processing PeekMessage" << LL_ENDL; - MSG msg; - while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ) - { - } - LL_DEBUGS("AppInit") << "PeekMessage processed" << LL_ENDL; -#endif - display_startup(); - timeout.reset(); - return false; - } - - if (STATE_LOGIN_WAIT == LLStartUp::getStartupState()) - { - // when we get to this state, we've already been past the login UI - // (possiblely automatically) - flag this so we can test in the - // STATE_LOGIN_SHOW state if we've gone backwards - mLoginStatePastUI = true; - - // Don't do anything. Wait for the login view to call the login_callback, - // which will push us to the next state. - - // display() function will be the one to run display_startup() - // Sleep so we don't spin the CPU - ms_sleep(1); - return false; - } - - if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) - { - // Post login screen, we should see if any settings have changed that may - // require us to either start/stop or change the socks proxy. As various communications - // past this point may require the proxy to be up. - if (!LLStartUp::startLLProxy()) - { - // Proxy start up failed, we should now bail the state machine - // startLLProxy() will have reported an error to the user - // already, so we just go back to the login screen. The user - // could then change the preferences to fix the issue. - - LLStartUp::setStartupState(STATE_LOGIN_SHOW); - return false; - } - - // reset the values that could have come in from a slurl - // DEV-42215: Make sure they're not empty -- gUserCredential - // might already have been set from gSavedSettings, and it's too bad - // to overwrite valid values with empty strings. - - if (show_connect_box) - { - // TODO if not use viewer auth - // Load all the name information out of the login view - LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword); - // end TODO - - // HACK: Try to make not jump on login - gKeyboard->resetKeys(); - } - - // when we get to this state, we've already been past the login UI - // (possiblely automatically) - flag this so we can test in the - // STATE_LOGIN_SHOW state if we've gone backwards - mLoginStatePastUI = true; - - // save the credentials - std::string userid = "unknown"; - if (gUserCredential.notNull()) - { - userid = gUserCredential->userID(); - if (gRememberUser) - { - gSecAPIHandler->addToCredentialMap("login_list", gUserCredential, gRememberPassword); - // Legacy viewers use this method to store user credentials, newer viewers - // reuse it to be compatible and to remember last session - gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword); - } - } - gSavedSettings.setBOOL("RememberPassword", gRememberPassword); - gSavedSettings.setBOOL("RememberUser", gRememberUser); - LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL; - gDebugInfo["LoginName"] = userid; - - // create necessary directories - // *FIX: these mkdir's should error check - gDirUtilp->setLindenUserDir(userid); - LLFile::mkdir(gDirUtilp->getLindenUserDir()); - - // As soon as directories are ready initialize notification storages - if (!LLPersistentNotificationStorage::instanceExists()) - { - // check existance since this part of code can be reached - // twice due to login failures - LLPersistentNotificationStorage::initParamSingleton(); - LLDoNotDisturbNotificationStorage::initParamSingleton(); - } - else - { - // reinitialize paths in case user switched grids or accounts - LLPersistentNotificationStorage::getInstance()->reset(); - LLDoNotDisturbNotificationStorage::getInstance()->reset(); - } - - // Set PerAccountSettingsFile to the default value. - std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")); - gSavedSettings.setString("PerAccountSettingsFile", settings_per_account); - gDebugInfo["PerAccountSettingsFilename"] = settings_per_account; - - // Note: can't store warnings files per account because some come up before login - - // Overwrite default user settings with user settings - LLAppViewer::instance()->loadSettingsFromDirectory("Account"); - - // Convert 'LogInstantMessages' into 'KeepConversationLogTranscripts' for backward compatibility (CHUI-743). - LLControlVariablePtr logInstantMessagesControl = gSavedPerAccountSettings.getControl("LogInstantMessages"); - if (logInstantMessagesControl.notNull()) - { - gSavedPerAccountSettings.setS32("KeepConversationLogTranscripts", logInstantMessagesControl->getValue() ? 2 : 1); - } - - // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation - // and startup time is close enough if we don't have a real value. - if (gSavedPerAccountSettings.getU32("LastLogoff") == 0) - { - gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); - } - - //Default the path if one isn't set. - // *NOTE: unable to check variable differ from "InstantMessageLogPath" because it was - // provided in pre 2.0 viewer. See EXT-6661 - if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty()) - { - gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir()); - gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir()); - } - else - { - gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - } - gDirUtilp->setPerAccountChatLogsDir(userid); - - LLFile::mkdir(gDirUtilp->getChatLogsDir()); - LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); - - if (show_connect_box) - { - LLSLURL slurl; - //LLPanelLogin::closePanel(); - } - - - // Load URL History File - LLURLHistory::loadFile("url_history.xml"); - // Load location history - LLLocationHistory::getInstance()->load(); - - // Load Avatars icons cache - LLAvatarIconIDCache::getInstance()->load(); - - LLRenderMuteList::getInstance()->loadFromFile(); - - //------------------------------------------------- - // Handle startup progress screen - //------------------------------------------------- - - // on startup the user can request to go to their home, - // their last location, or some URL "-url //sim/x/y[/z]" - // All accounts have both a home and a last location, and we don't support - // more locations than that. Choose the appropriate one. JC - switch (LLStartUp::getStartSLURL().getType()) - { - case LLSLURL::LOCATION: - agent_location_id = START_LOCATION_ID_URL; - break; - case LLSLURL::LAST_LOCATION: - agent_location_id = START_LOCATION_ID_LAST; - break; - default: - agent_location_id = START_LOCATION_ID_HOME; - break; - } - - gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); - - // Display the startup progress bar. - gViewerWindow->initTextures(agent_location_id); - gViewerWindow->setShowProgress(true); - gViewerWindow->setProgressCancelButtonVisible(true, LLTrans::getString("Quit")); - - gViewerWindow->revealIntroPanel(); - - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); - - return false; - } - - if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState()) - { - gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId(); - - // Update progress status and the display loop. - auth_desc = LLTrans::getString("LoginInProgress"); - set_startup_status(progress, auth_desc, auth_message); - progress += 0.02f; - display_startup(); - - // Setting initial values... - LLLoginInstance* login = LLLoginInstance::getInstance(); - login->setNotificationsInterface(LLNotifications::getInstance()); - - login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); - login->setLastExecEvent(gLastExecEvent); - login->setLastExecDuration(gLastExecDuration); - - // This call to LLLoginInstance::connect() starts the - // authentication process. - login->connect(gUserCredential); - - LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK ); - return false; - } - - if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState()) - { - // If we get here we have gotten past the potential stall - // in curl, so take "may appear frozen" out of progress bar. JC - auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); - set_startup_status(progress, auth_desc, auth_message); - - LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); - return false; - } - - if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) - { - // Generic failure message - std::ostringstream emsg; - emsg << LLTrans::getString("LoginFailedHeader") << "\n"; - if(LLLoginInstance::getInstance()->authFailure()) - { - LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): " - << LLLoginInstance::getInstance()->getResponse() << LL_ENDL; - LLSD response = LLLoginInstance::getInstance()->getResponse(); - // Still have error conditions that may need some - // sort of handling - dig up specific message - std::string reason_response = response["reason"]; - std::string message_response = response["message"]; - std::string message_id = response["message_id"]; - std::string message; // actual string to show the user - - bool localized_by_id = false; - if(!message_id.empty()) - { - LLSD message_args = response["message_args"]; - if (message_args.has("TIME") - && (message_id == "LoginFailedAcountSuspended" - || message_id == "LoginFailedAccountMaintenance")) - { - LLDate date; - std::string time_string; - if (date.fromString(message_args["TIME"].asString())) - { - LLSD args; - args["datetime"] = (S32)date.secondsSinceEpoch(); - LLTrans::findString(time_string, "LocalTime", args); - } - else - { - time_string = message_args["TIME"].asString() + " " + LLTrans::getString("PacificTime"); - } - - message_args["TIME"] = time_string; - } - // message will be filled in with the template and arguments - if (LLTrans::findString(message, message_id, message_args)) - { - localized_by_id = true; - } - } - - if(!localized_by_id && !message_response.empty()) - { - // *HACK: "no_inventory_host" sent as the message itself. - // Remove this clause when server is sending message_id as well. - message = LLAgent::sTeleportErrorMessages[ message_response ]; - } - - if (message.empty()) - { - // Fallback to server-supplied string; necessary since server - // may add strings that this viewer is not yet aware of - message = message_response; - } - - emsg << message; - - - if(reason_response == "key") - { - // Couldn't login because user/password is wrong - // Clear the credential - gUserCredential->clearAuthenticator(); - } - - if(reason_response == "update" - || reason_response == "optional") - { - // In the case of a needed update, quit. - // Its either downloading or declined. - // If optional was skipped this case shouldn't - // be reached. - - LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL; - LLLoginInstance::getInstance()->disconnect(); - LLAppViewer::instance()->forceQuit(); - } - else - { - if (reason_response != "tos" && reason_response != "mfa_challenge") - { - // Don't pop up a notification in the TOS or MFA cases because - // the specialized floater has already scolded the user. - std::string error_code; - if(response.has("errorcode")) - { - error_code = response["errorcode"].asString(); - } - if ((reason_response == "CURLError") && - (error_code == "SSL_CACERT" || error_code == "SSL_PEER_CERTIFICATE") && - response.has("certificate")) - { - // This was a certificate error, so grab the certificate - // and throw up the appropriate dialog. - LLPointer certificate; - try - { - certificate = gSecAPIHandler->getCertificate(response["certificate"]); - } - catch (LLCertException &cert_exception) - { - LL_WARNS("LLStartup", "SECAPI") << "Caught " << cert_exception.what() << " certificate expception on getCertificate("<< response["certificate"] << ")" << LL_ENDL; - LLSD args; - args["REASON"] = LLTrans::getString(cert_exception.what()); - - LLNotificationsUtil::add("GeneralCertificateErrorShort", args, response, - general_cert_done); - - reset_login(); - gSavedSettings.setBOOL("AutoLogin", false); - show_connect_box = true; - } - if(certificate) - { - LLSD args = transform_cert_args(certificate); - - if(error_code == "SSL_CACERT") - { - // if we are handling an untrusted CA, throw up the dialog - // with the 'trust this CA' button. - LLNotificationsUtil::add("TrustCertificateError", args, response, - trust_cert_done); - - show_connect_box = true; - } - else - { - // the certificate exception returns a unique string for each type of exception. - // we grab this string via the LLUserAuth object, and use that to grab the localized - // string. - args["REASON"] = LLTrans::getString(message_response); - - LLNotificationsUtil::add("GeneralCertificateError", args, response, - general_cert_done); - - reset_login(); - gSavedSettings.setBOOL("AutoLogin", false); - show_connect_box = true; - - } - - } - } - else if (reason_response == "BadType") - { - LLNotificationsUtil::add("LoginFailedToParse", LLSD(), LLSD(), login_alert_done); - } - else if (!message.empty()) - { - // This wasn't a certificate error, so throw up the normal - // notificatioin message. - LLSD args; - args["ERROR_MESSAGE"] = emsg.str(); - LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; - LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); - } - } - transition_back_to_login_panel(emsg.str()); - show_connect_box = true; - } - } - else if(LLLoginInstance::getInstance()->authSuccess()) - { - if(process_login_success_response()) - { - // Pass the user information to the voice chat server interface. - LLVoiceClient::getInstance()->userAuthorized(gUserCredential->userID(), gAgentID); - // create the default proximal channel - LLVoiceChannel::initClass(); - LLStartUp::setStartupState( STATE_WORLD_INIT); - LLTrace::get_frame_recording().reset(); - } - else - { - LLSD args; - args["ERROR_MESSAGE"] = emsg.str(); - LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; - LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); - transition_back_to_login_panel(emsg.str()); - show_connect_box = true; - return false; - } - } - return false; - } - - //--------------------------------------------------------------------- - // World Init - //--------------------------------------------------------------------- - if (STATE_WORLD_INIT == LLStartUp::getStartupState()) - { - set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); - display_startup(); - // We should have an agent id by this point. - llassert(!(gAgentID == LLUUID::null)); - - // Finish agent initialization. (Requires gSavedSettings, builds camera) - gAgent.init(); - display_startup(); - gAgentCamera.init(); - display_startup(); - display_startup(); - - // Since we connected, save off the settings so the user doesn't have to - // type the name/password again if we crash. - gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), true); - LLUIColorTable::instance().saveUserSettings(); - - display_startup(); - - // - // Initialize classes w/graphics stuff. - // - LLViewerStatsRecorder::instance(); // Since textures work in threads - LLSurface::initClasses(); - display_startup(); - - display_startup(); - - LLDrawable::initClass(); - display_startup(); - - // init the shader managers - LLPostProcess::initClass(); - display_startup(); - - LLAvatarAppearance::initClass("avatar_lad.xml","avatar_skeleton.xml"); - display_startup(); - - LLViewerObject::initVOClasses(); - display_startup(); - - // Initialize all our tools. Must be done after saved settings loaded. - // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton. - LLToolMgr::getInstance()->initTools(); - display_startup(); - - // Pre-load floaters, like the world map, that are slow to spawn - // due to XML complexity. - gViewerWindow->initWorldUI(); - - display_startup(); - - // This is where we used to initialize gWorldp. Original comment said: - // World initialization must be done after above window init - - // User might have overridden far clip - LLWorld::getInstance()->setLandFarClip(gAgentCamera.mDrawDistance); - display_startup(); - // Before we create the first region, we need to set the agent's mOriginGlobal - // This is necessary because creating objects before this is set will result in a - // bad mPositionAgent cache. - - gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); - display_startup(); - - LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); - display_startup(); - - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); - LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; - - LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == " - << gFirstSimSeedCap << LL_ENDL; - regionp->setSeedCapability(gFirstSimSeedCap); - LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; - display_startup(); - // Set agent's initial region to be the one we just created. - gAgent.setRegion(regionp); - display_startup(); - // Set agent's initial position, which will be read by LLVOAvatar when the avatar - // object is created. I think this must be done after setting the region. JC - gAgent.setPositionAgent(agent_start_position_region); - - display_startup(); - LLStartUp::initExperiences(); - - display_startup(); - - // If logging should be enebled, turns it on and loads history from disk - // Note: does not happen on init of singleton because preferences can use - // this instance without logging in - LLConversationLog::getInstance()->initLoggingState(); - - LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); - - return false; - } - - - //--------------------------------------------------------------------- - // Load QuickTime/GStreamer and other multimedia engines, can be slow. - // Do it while we're waiting on the network for our seed capability. JC - //--------------------------------------------------------------------- - if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState()) - { - LLStartUp::multimediaInit(); - LLStartUp::setStartupState( STATE_FONT_INIT ); - display_startup(); - return false; - } - - // Loading fonts takes several seconds - if (STATE_FONT_INIT == LLStartUp::getStartupState()) - { - LLStartUp::fontInit(); - LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT ); - display_startup(); - return false; - } - - //--------------------------------------------------------------------- - // Wait for Seed Cap Grant - //--------------------------------------------------------------------- - if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); - if (regionp->capabilitiesReceived()) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - else if (regionp->capabilitiesError()) - { - LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) - { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); - } - else - { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); - } - reset_login(); - } - else - { - U32 num_retries = regionp->getNumSeedCapRetries(); - if (num_retries > MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT) - { - LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) - { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); - } - else - { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); - } - reset_login(); - } - else if (num_retries > 0) - { - LLStringUtil::format_map_t args; - args["[NUMBER]"] = llformat("%d", num_retries + 1); - set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD.c_str()); - } - else - { - set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str()); - } - } - display_startup(); - return false; - } - - - //--------------------------------------------------------------------- - // Seed Capability Granted - // no newMessage calls should happen before this point - //--------------------------------------------------------------------- - if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState()) - { - display_startup(); - - // These textures are not warrantied to be cached, so needs - // to hapen with caps granted - gTextureList.doPrefetchImages(); - - // will init images, should be done with caps, but before gSky.init() - LLEnvironment::getInstance()->initSingleton(); - - display_startup(); - update_texture_fetch(); - display_startup(); - - if ( gViewerWindow != NULL) - { // This isn't the first logon attempt, so show the UI - gViewerWindow->setNormalControlsVisible( true ); - } - gLoginMenuBarView->setVisible( false ); - gLoginMenuBarView->setEnabled( false ); - display_startup(); - - // direct logging to the debug console's line buffer - LLError::logToFixedBuffer(gDebugView->mDebugConsolep); - display_startup(); - - // set initial visibility of debug console - gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); - display_startup(); - - // - // Set message handlers - // - LL_INFOS("AppInit") << "Initializing communications..." << LL_ENDL; - - // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted - register_viewer_callbacks(gMessageSystem); - display_startup(); - - // Debugging info parameters - gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms - display_startup(); - - #ifndef LL_RELEASE_FOR_DOWNLOAD - gMessageSystem->setTimeDecodes( true ); // Time the decode of each msg - gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode - #endif - display_startup(); - - gXferManager->registerCallbacks(gMessageSystem); - display_startup(); - - LLStartUp::initNameCache(); - display_startup(); - - // update the voice settings *after* gCacheName initialization - // so that we can construct voice UI that relies on the name cache - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->updateSettings(); - } - display_startup(); - - // create a container's instance for start a controlling conversation windows - // by the voice's events - LLFloaterIMContainer::getInstance(); - if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2) - { - LLViewerParcelAskPlay::getInstance()->loadSettings(); - } - - gAgent.addRegionChangedCallback(boost::bind(&LLPerfStats::StatsRecorder::clearStats)); - - // *Note: this is where gWorldMap used to be initialized. - - // register null callbacks for audio until the audio system is initialized - gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL); - gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL); - display_startup(); - - //reset statistics - LLViewerStats::instance().resetStats(); - - display_startup(); - // - // Set up region and surface defaults - // - - - // Sets up the parameters for the first simulator - - LL_DEBUGS("AppInit") << "Initializing camera..." << LL_ENDL; - gFrameTime = totalTime(); - F32Seconds last_time = gFrameTimeSeconds; - gFrameTimeSeconds = (gFrameTime - gStartTime); - - gFrameIntervalSeconds = gFrameTimeSeconds - last_time; - if (gFrameIntervalSeconds < 0.f) - { - gFrameIntervalSeconds = 0.f; - } - - // Make sure agent knows correct aspect ratio - // FOV limits depend upon aspect ratio so this needs to happen before initializing the FOV below - LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWorldViewHeightRaw()); - LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio()); - // Initialize FOV - LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle")); - display_startup(); - - // Move agent to starting location. The position handed to us by - // the space server is in global coordinates, but the agent frame - // is in region local coordinates. Therefore, we need to adjust - // the coordinates handed to us to fit in the local region. - - gAgent.setPositionAgent(agent_start_position_region); - gAgent.resetAxes(gAgentStartLookAt); - gAgentCamera.stopCameraAnimation(); - gAgentCamera.resetCamera(); - display_startup(); - - // Initialize global class data needed for surfaces (i.e. textures) - LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; - // Initialize all of the viewer object classes for the first time (doing things like texture fetches. - LLGLState::checkStates(); - - gSky.init(); - - LLGLState::checkStates(); - - display_startup(); - - LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL; - // For all images pre-loaded into viewer cache, init - // priorities and fetching using decodeAllImages. - // Most of the fetching and decoding likely to be done - // by update_texture_fetch() later, while viewer waits. - // - // Need to do this AFTER we init the sky - const S32 DECODE_TIME_SEC = 2; - for (int i = 0; i < DECODE_TIME_SEC; i++) - { - F32 frac = (F32)i / (F32)DECODE_TIME_SEC; - set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD); - display_startup(); - gTextureList.decodeAllImages(1.f); - } - LLStartUp::setStartupState( STATE_WORLD_WAIT ); - - display_startup(); - - // JC - Do this as late as possible to increase likelihood Purify - // will run. - LLMessageSystem* msg = gMessageSystem; - if (!msg->mOurCircuitCode) - { - LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL; - } - - gUseCircuitCallbackCalled = false; - - msg->enableCircuit(gFirstSim, true); - // now, use the circuit info to tell simulator about us! - LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL; - msg->newMessageFast(_PREHASH_UseCircuitCode); - msg->nextBlockFast(_PREHASH_CircuitCode); - msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); - msg->sendReliable( - gFirstSim, - gSavedSettings.getS32("UseCircuitCodeMaxRetries"), - false, - (F32Seconds)gSavedSettings.getF32("UseCircuitCodeTimeout"), - use_circuit_callback, - NULL); - - timeout.reset(); - display_startup(); - - return false; - } - - //--------------------------------------------------------------------- - // World Wait - //--------------------------------------------------------------------- - if(STATE_WORLD_WAIT == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "Waiting for simulator ack...." << LL_ENDL; - set_startup_status(0.59f, LLTrans::getString("LoginWaitingForRegionHandshake"), gAgent.mMOTD); - if(gGotUseCircuitCodeAck) - { - LLStartUp::setStartupState( STATE_AGENT_SEND ); - } - pump_idle_startup_network(); - return false; - } - - //--------------------------------------------------------------------- - // Agent Send - //--------------------------------------------------------------------- - if (STATE_AGENT_SEND == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "Connecting to region..." << LL_ENDL; - set_startup_status(0.60f, LLTrans::getString("LoginConnectingToRegion"), gAgent.mMOTD); - display_startup(); - // register with the message system so it knows we're - // expecting this message - LLMessageSystem* msg = gMessageSystem; - msg->setHandlerFuncFast( - _PREHASH_AgentMovementComplete, - process_agent_movement_complete); - LLViewerRegion* regionp = gAgent.getRegion(); - if(regionp) - { - send_complete_agent_movement(regionp->getHost()); - gAssetStorage->setUpstream(regionp->getHost()); - gCacheName->setUpstream(regionp->getHost()); - } - display_startup(); - - // Create login effect - // But not on first login, because you can't see your avatar then - if (!gAgent.isFirstLogin()) - { - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, true); - effectp->setPositionGlobal(gAgent.getPositionGlobal()); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - LLHUDManager::getInstance()->sendEffects(); - } - - LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT - - timeout.reset(); - display_startup(); - return false; - } - - //--------------------------------------------------------------------- - // Agent Wait - //--------------------------------------------------------------------- - if (STATE_AGENT_WAIT == LLStartUp::getStartupState()) - { - { - LockMessageChecker lmc(gMessageSystem); - while (lmc.checkAllMessages(gFrameCount, gServicePump)) - { - if (gAgentMovementCompleted) - { - // Sometimes we have more than one message in the - // queue. break out of this loop and continue - // processing. If we don't, then this could skip one - // or more login steps. - break; - } - else - { - LL_DEBUGS("AppInit") << "Awaiting AvatarInitComplete, got " - << gMessageSystem->getMessageName() << LL_ENDL; - } - display_startup(); - } - lmc.processAcks(); - } - - display_startup(); - - if (gAgentMovementCompleted) - { - LLStartUp::setStartupState( STATE_INVENTORY_SEND ); - } - display_startup(); - - if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) - { - LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) - { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); - } - else - { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); - } - reset_login(); - } - return false; - } - - //--------------------------------------------------------------------- - // Inventory Send - //--------------------------------------------------------------------- - if (STATE_INVENTORY_SEND == LLStartUp::getStartupState()) - { - LL_PROFILE_ZONE_NAMED("State inventory send") - display_startup(); - - // request mute list - LL_INFOS() << "Requesting Mute List" << LL_ENDL; - LLMuteList::getInstance()->requestFromServer(gAgent.getID()); - - // Get L$ and ownership credit information - LL_INFOS() << "Requesting Money Balance" << LL_ENDL; - LLStatusBar::sendMoneyBalanceRequest(); - - display_startup(); - - // Inform simulator of our language preference - LLAgentLanguage::update(); - - display_startup(); - // unpack thin inventory - LLSD response = LLLoginInstance::getInstance()->getResponse(); - //bool dump_buffer = false; - - LLSD inv_lib_root = response["inventory-lib-root"]; - if(inv_lib_root.isDefined()) - { - // should only be one - LLSD id = inv_lib_root[0]["folder_id"]; - if(id.isDefined()) - { - gInventory.setLibraryRootFolderID(id.asUUID()); - } - } - display_startup(); - - LLSD inv_lib_owner = response["inventory-lib-owner"]; - if(inv_lib_owner.isDefined()) - { - // should only be one - LLSD id = inv_lib_owner[0]["agent_id"]; - if(id.isDefined()) - { - gInventory.setLibraryOwnerID(LLUUID(id.asUUID())); - } - } - display_startup(); - LLStartUp::setStartupState(STATE_INVENTORY_SKEL); - display_startup(); - return false; - } - - if (STATE_INVENTORY_SKEL == LLStartUp::getStartupState()) - { - LL_PROFILE_ZONE_NAMED("State inventory load skeleton") - - LLSD response = LLLoginInstance::getInstance()->getResponse(); - - LLSD inv_skel_lib = response["inventory-skel-lib"]; - if (inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull()) - { - LL_PROFILE_ZONE_NAMED("load library inv") - if (!gInventory.loadSkeleton(inv_skel_lib, gInventory.getLibraryOwnerID())) - { - LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; - } - } - display_startup(); - - LLSD inv_skeleton = response["inventory-skeleton"]; - if (inv_skeleton.isDefined()) - { - LL_PROFILE_ZONE_NAMED("load personal inv") - if (!gInventory.loadSkeleton(inv_skeleton, gAgent.getID())) - { - LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL; - } - } - display_startup(); - LLStartUp::setStartupState(STATE_INVENTORY_SEND2); - display_startup(); - return false; - } - - if (STATE_INVENTORY_SEND2 == LLStartUp::getStartupState()) - { - LL_PROFILE_ZONE_NAMED("State inventory send2") - - LLSD response = LLLoginInstance::getInstance()->getResponse(); - - LLSD inv_basic = response["inventory-basic"]; - if(inv_basic.isDefined()) - { - LL_INFOS() << "Basic inventory root folder id is " << inv_basic["folder_id"] << LL_ENDL; - } - - LLSD buddy_list = response["buddy-list"]; - if(buddy_list.isDefined()) - { - LLAvatarTracker::buddy_map_t list; - LLUUID agent_id; - S32 has_rights = 0, given_rights = 0; - for(LLSD::array_const_iterator it = buddy_list.beginArray(), - end = buddy_list.endArray(); it != end; ++it) - { - LLSD buddy_id = (*it)["buddy_id"]; - if(buddy_id.isDefined()) - { - agent_id = buddy_id.asUUID(); - } - - LLSD buddy_rights_has = (*it)["buddy_rights_has"]; - if(buddy_rights_has.isDefined()) - { - has_rights = buddy_rights_has.asInteger(); - } - - LLSD buddy_rights_given = (*it)["buddy_rights_given"]; - if(buddy_rights_given.isDefined()) - { - given_rights = buddy_rights_given.asInteger(); - } - - list[agent_id] = new LLRelationship(given_rights, has_rights, false); - } - LLAvatarTracker::instance().addBuddyList(list); - display_startup(); - } - - bool show_hud = false; - LLSD tutorial_setting = response["tutorial_setting"]; - if(tutorial_setting.isDefined()) - { - for(LLSD::array_const_iterator it = tutorial_setting.beginArray(), - end = tutorial_setting.endArray(); it != end; ++it) - { - LLSD tutorial_url = (*it)["tutorial_url"]; - if(tutorial_url.isDefined()) - { - // Tutorial floater will append language code - gSavedSettings.setString("TutorialURL", tutorial_url.asString()); - } - - // For Viewer 2.0 we are not using the web-based tutorial - // If we reverse that decision, put this code back and use - // login.cgi to send a different URL with content that matches - // the Viewer 2.0 UI. - //LLSD use_tutorial = (*it)["use_tutorial"]; - //if(use_tutorial.asString() == "true") - //{ - // show_hud = true; - //} - } - } - display_startup(); - - // Either we want to show tutorial because this is the first login - // to a Linden Help Island or the user quit with the tutorial - // visible. JC - if (show_hud || gSavedSettings.getBOOL("ShowTutorial")) - { - LLFloaterReg::showInstance("hud", LLSD(), false); - } - display_startup(); - - LLSD event_notifications = response["event_notifications"]; - if(event_notifications.isDefined()) - { - gEventNotifier.load(event_notifications); - } - display_startup(); - - LLSD classified_categories = response["classified_categories"]; - if(classified_categories.isDefined()) - { - LLClassifiedInfo::loadCategories(classified_categories); - } - display_startup(); - - // This method MUST be called before gInventory.findCategoryUUIDForType because of - // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap. - gInventory.buildParentChildMap(); - - // If buildParentChildMap succeeded, inventory will now be in - // a usable state and gInventory.isInventoryUsable() will be - // true. - - // if inventory is unusable, show warning. - if (!gInventory.isInventoryUsable()) - { - LLNotificationsUtil::add("InventoryUnusable"); - } - - LLInventoryModelBackgroundFetch::instance().start(); - gInventory.createCommonSystemCategories(); - LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS ); - display_startup(); - - return false; - } - - //--------------------------------------------------------------------- - // STATE_INVENTORY_CALLBACKS - //--------------------------------------------------------------------- - if (STATE_INVENTORY_CALLBACKS == LLStartUp::getStartupState()) - { - if (!LLInventoryModel::isSysFoldersReady()) - { - display_startup(); - return false; - } - - LLInventoryModelBackgroundFetch::instance().start(); - LLAppearanceMgr::instance().initCOFID(); - LLUUID cof_id = LLAppearanceMgr::instance().getCOF(); - LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); - if (cof - && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) - { - // Special case, dupplicate request prevention. - // Cof folder will be requested via FetchCOF - // in appearance manager, prevent recursive fetch - cof->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); - } - - - // It's debatable whether this flag is a good idea - sets all - // bits, and in general it isn't true that inventory - // initialization generates all types of changes. Maybe add an - // INITIALIZE mask bit instead? - gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); - gInventory.notifyObservers(); - - display_startup(); - - // set up callbacks - LL_INFOS() << "Registering Callbacks" << LL_ENDL; - LLMessageSystem* msg = gMessageSystem; - LL_INFOS() << " Inventory" << LL_ENDL; - LLInventoryModel::registerCallbacks(msg); - LL_INFOS() << " AvatarTracker" << LL_ENDL; - LLAvatarTracker::instance().registerCallbacks(msg); - LL_INFOS() << " Landmark" << LL_ENDL; - LLLandmark::registerCallbacks(msg); - display_startup(); - - // request all group information - LL_INFOS() << "Requesting Agent Data" << LL_ENDL; - gAgent.sendAgentDataUpdateRequest(); - display_startup(); - // Create the inventory views - LL_INFOS() << "Creating Inventory Views" << LL_ENDL; - LLFloaterReg::getInstance("inventory"); - display_startup(); - LLStartUp::setStartupState( STATE_MISC ); - display_startup(); - - return false; - } - - - //--------------------------------------------------------------------- - // Misc - //--------------------------------------------------------------------- - if (STATE_MISC == LLStartUp::getStartupState()) - { - // We have a region, and just did a big inventory download. - // We can estimate the user's connection speed, and set their - // max bandwidth accordingly. JC - if (gSavedSettings.getBOOL("FirstLoginThisInstall")) - { - // This is actually a pessimistic computation, because TCP may not have enough - // time to ramp up on the (small) default inventory file to truly measure max - // bandwidth. JC - F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS(); - const F32 FAST_RATE_BPS = 600.f * 1024.f; - const F32 FASTER_RATE_BPS = 750.f * 1024.f; - F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); - if (rate_bps > FASTER_RATE_BPS - && rate_bps > max_bandwidth) - { - LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " - << FASTER_RATE_BPS/1024.f - << " kbps" << LL_ENDL; - gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f); - } - else if (rate_bps > FAST_RATE_BPS - && rate_bps > max_bandwidth) - { - LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " - << FAST_RATE_BPS/1024.f - << " kbps" << LL_ENDL; - gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f); - } - - if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin")) - { - gSavedSettings.setBOOL("HelpFloaterOpen", true); - } - - // Set the show start location to true, now that the user has logged - // on with this install. - gSavedSettings.setBOOL("ShowStartLocation", true); - } - - display_startup(); - - // Load stored local environment if needed. - LLEnvironment::instance().loadFromSettings(); - - // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp) - //check_merchant_status(); - - display_startup(); - - if (gSavedSettings.getBOOL("HelpFloaterOpen")) - { - // show default topic - LLViewerHelp::instance().showTopic(""); - } - - display_startup(); - - // We're successfully logged in. - gSavedSettings.setBOOL("FirstLoginThisInstall", false); - - LLFloaterReg::showInitialVisibleInstances(); - - LLFloaterGridStatus::getInstance()->startGridStatusTimer(); - - display_startup(); - - display_startup(); - // JC: Initializing audio requests many sounds for download. - init_audio(); - display_startup(); - - // JC: Initialize "active" gestures. This may also trigger - // many gesture downloads, if this is the user's first - // time on this machine or -purge has been run. - LLSD gesture_options - = LLLoginInstance::getInstance()->getResponse("gestures"); - if (gesture_options.isDefined()) - { - LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size() - << LL_ENDL; - uuid_vec_t item_ids; - for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(), - end = gesture_options.endArray(); resp_it != end; ++resp_it) - { - // If the id is not specifed in the LLSD, - // the LLSD operator[]() will return a null LLUUID. - LLUUID item_id = (*resp_it)["item_id"]; - LLUUID asset_id = (*resp_it)["asset_id"]; - - if (item_id.notNull() && asset_id.notNull()) - { - // Could schedule and delay these for later. - const bool no_inform_server = false; - const bool no_deactivate_similar = false; - LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id, - no_inform_server, - no_deactivate_similar); - // We need to fetch the inventory items for these gestures - // so we have the names to populate the UI. - item_ids.push_back(item_id); - } - } - // no need to add gesture to inventory observer, it's already made in constructor - LLGestureMgr::instance().setFetchIDs(item_ids); - LLGestureMgr::instance().startFetch(); - } - gDisplaySwapBuffers = true; - display_startup(); - - LLMessageSystem* msg = gMessageSystem; - msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger); - msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound); - msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound); - msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change); - - LL_DEBUGS("AppInit") << "Initialization complete" << LL_ENDL; - - LL_DEBUGS("SceneLoadTiming", "Start") << "Scene Load Started " << LL_ENDL; - gRenderStartTime.reset(); - gForegroundTime.reset(); - - // HACK: Inform simulator of window size. - // Do this here so it's less likely to race with RegisterNewAgent. - // TODO: Put this into RegisterNewAgent - // JC - 7/20/2002 - gViewerWindow->sendShapeToSim(); - - LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA); - - // The reason we show the alert is because we want to - // reduce confusion for when you log in and your provided - // location is not your expected location. So, if this is - // your first login, then you do not have an expectation, - // thus, do not show this alert. - if (!gAgent.isFirstLogin()) - { - LL_INFOS() << "gAgentStartLocation : " << gAgentStartLocation << LL_ENDL; - LLSLURL start_slurl = LLStartUp::getStartSLURL(); - LL_DEBUGS("AppInit") << "start slurl "< 1.f) && isAgentAvatarValid()) - { - LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); - } - else if (timeout_frac > 10.f) - { - // If we exceed the wait above while isAgentAvatarValid is - // not true yet, we will change startup state and - // eventually (once avatar does get created) wind up at - // the gender chooser. This should occur only in very - // unusual circumstances, so set the timeout fairly high - // to minimize mistaken hits here. - LL_WARNS() << "Wait for valid avatar state exceeded " - << timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL; - LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); - } - else - { - update_texture_fetch(); - set_startup_status(0.60f + 0.30f * timeout_frac, - LLTrans::getString("LoginPrecaching"), - gAgent.mMOTD.c_str()); - display_startup(); - } - - return true; - } - - if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState()) - { - static LLFrameTimer wearables_timer; - - const F32 wearables_time = wearables_timer.getElapsedTimeF32(); - const F32 MAX_WEARABLES_TIME = 10.f; - - if (!gAgent.isOutfitChosen() && isAgentAvatarValid()) - { - // No point in waiting for clothing, we don't even know - // what outfit we want. Pop up a gender chooser dialog to - // ask and proceed to draw the world. JC - // - // *NOTE: We might hit this case even if we have an - // initial outfit, but if the load hasn't started - // already then something is wrong so fall back - // to generic outfits. JC - LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(), - callback_choose_gender); - LLStartUp::setStartupState( STATE_CLEANUP ); - } - - display_startup(); - - if (gAgent.isOutfitChosen() && (wearables_time > MAX_WEARABLES_TIME)) - { - if (gInventory.isInventoryUsable()) - { - LLNotificationsUtil::add("ClothingLoading"); - } - record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time); - LLStartUp::setStartupState( STATE_CLEANUP ); - } - else if (gAgent.isFirstLogin() - && isAgentAvatarValid() - && gAgentAvatarp->isFullyLoaded()) - { - // wait for avatar to be completely loaded - if (isAgentAvatarValid() - && gAgentAvatarp->isFullyLoaded()) - { - LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL; - LLStartUp::setStartupState( STATE_CLEANUP ); - return true; - } - } - else - { - // OK to just get the wearables - if ( gAgentWearables.areWearablesLoaded() ) - { - // We have our clothing, proceed. - LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL; - LLStartUp::setStartupState( STATE_CLEANUP ); - return true; - } - } - //fall through this frame to STATE_CLEANUP - } - - if (STATE_CLEANUP == LLStartUp::getStartupState()) - { - set_startup_status(1.0, "", ""); - display_startup(); - - if (!mBenefitsSuccessfullyInit) - { - LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2)); - } - - // Let the map know about the inventory. - LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); - if(floater_world_map) - { - floater_world_map->observeInventory(&gInventory); - floater_world_map->observeFriends(); - } - gViewerWindow->showCursor(); - gViewerWindow->getWindow()->resetBusyCount(); - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL; - //gViewerWindow->revealIntroPanel(); - gViewerWindow->setStartupComplete(); - gViewerWindow->setProgressCancelButtonVisible(false); - display_startup(); - - // We're not away from keyboard, even though login might have taken - // a while. JC - gAgent.clearAFK(); - - // Have the agent start watching the friends list so we can update proxies - gAgent.observeFriends(); - - // Start automatic replay if the flag is set. - if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession()) - { - LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL; - gAgentPilot.startPlayback(); - } - - show_debug_menus(); // Debug menu visiblity and First Use trigger - - // If we've got a startup URL, dispatch it - //LLStartUp::dispatchURL(); - - // Retrieve information about the land data - // (just accessing this the first time will fetch it, - // then the data is cached for the viewer's lifetime) - LLProductInfoRequestManager::instance(); - - // *FIX:Mani - What do I do here? - // Need we really clear the Auth response data? - // Clean up the userauth stuff. - // LLUserAuth::getInstance()->reset(); - - LLStartUp::setStartupState( STATE_STARTED ); - display_startup(); - - // Unmute audio if desired and setup volumes. - // This is a not-uncommon crash site, so surround it with - // LL_INFOS() output to aid diagnosis. - LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL; - audio_update_volume(); - LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL; - - // reset keyboard focus to sane state of pointing at world - gFocusMgr.setKeyboardFocus(NULL); - - LLAppViewer::instance()->handleLoginComplete(); - - LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); - - display_startup(); - - llassert(LLPathfindingManager::getInstance() != NULL); - LLPathfindingManager::getInstance()->initSystem(); - - gAgentAvatarp->sendHoverHeight(); - - // look for parcels we own - send_places_query(LLUUID::null, - LLUUID::null, - "", - DFQ_AGENT_OWNED, - LLParcel::C_ANY, - ""); - - LLUIUsage::instance().clear(); - - LLPerfStats::StatsRecorder::setAutotuneInit(); - - return true; - } - - return true; -} - -// -// local function definition -// - -void login_show() -{ - LL_INFOS("AppInit") << "Initializing Login Screen" << LL_ENDL; - - // Hide the toolbars: may happen to come back here if login fails after login agent but before login in region - if (gToolBarView) - { - gToolBarView->setVisible(false); - } - - LLPanelLogin::show( gViewerWindow->getWindowRectScaled(), login_callback, NULL ); -} - -// Callback for when login screen is closed. Option 0 = connect, option 1 = quit. -void login_callback(S32 option, void *userdata) -{ - const S32 CONNECT_OPTION = 0; - const S32 QUIT_OPTION = 1; - - if (CONNECT_OPTION == option) - { - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - return; - } - else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION - { - if (!gSavedSettings.getBOOL("RememberPassword")) - { - // turn off the setting and write out to disk - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , true ); - LLUIColorTable::instance().saveUserSettings(); - } - - // Next iteration through main loop should shut down the app cleanly. - LLAppViewer::instance()->userQuit(); - - if (LLAppViewer::instance()->quitRequested()) - { - LLPanelLogin::closePanel(); - } - return; - } - else - { - LL_WARNS("AppInit") << "Unknown login button clicked" << LL_ENDL; - } -} - -void release_notes_coro(const std::string url) -{ - if (url.empty()) - { - return; - } - - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("releaseNotesCoro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); - - httpOpts->setHeadersOnly(true); // only making sure it isn't 404 or something like that - - LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - if (!status) - { - return; - } - - LLWeb::loadURLInternal(url); -} - -/** -* Check if user is running a new version of the viewer. -* Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting. -*/ -void show_release_notes_if_required() -{ - static bool release_notes_shown = false; - // We happen to know that instantiating LLVersionInfo implicitly - // instantiates the LLEventMailDrop named "relnotes", which we (might) use - // below. If viewer release notes stop working, might be because that - // LLEventMailDrop got moved out of LLVersionInfo and hasn't yet been - // instantiated. - if (!release_notes_shown && (LLVersionInfo::instance().getChannelAndVersion() != gLastRunVersion) - && LLVersionInfo::instance().getViewerMaturity() != LLVersionInfo::TEST_VIEWER // don't show Release Notes for the test builds - && gSavedSettings.getBOOL("UpdaterShowReleaseNotes") - && !gSavedSettings.getBOOL("FirstLoginThisInstall")) - { - -#if LL_RELEASE_FOR_DOWNLOAD - if (!gSavedSettings.getBOOL("CmdLineSkipUpdater") - && !LLAppViewer::instance()->isUpdaterMissing()) - { - // Instantiate a "relnotes" listener which assumes any arriving event - // is the release notes URL string. Since "relnotes" is an - // LLEventMailDrop, this listener will be invoked whether or not the - // URL has already been posted. If so, it will fire immediately; - // otherwise it will fire whenever the URL is (later) posted. Either - // way, it will display the release notes as soon as the URL becomes - // available. - LLEventPumps::instance().obtain("relnotes").listen( - "showrelnotes", - [](const LLSD& url) { - LLCoros::instance().launch("releaseNotesCoro", - boost::bind(&release_notes_coro, url.asString())); - return false; - }); - } - else -#endif // LL_RELEASE_FOR_DOWNLOAD - { - LLSD info(LLAppViewer::instance()->getViewerInfo()); - std::string url = info["VIEWER_RELEASE_NOTES_URL"].asString(); - LLCoros::instance().launch("releaseNotesCoro", - boost::bind(&release_notes_coro, url)); - } - release_notes_shown = true; - } -} - -void show_first_run_dialog() -{ - LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); -} - -bool first_run_dialog_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) - { - LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL; - LLWeb::loadURLExternal(LLTrans::getString("create_account_url") ); - } - - LLPanelLogin::giveFocus(); - return false; -} - - - -void set_startup_status(const F32 frac, const std::string& string, const std::string& msg) -{ - gViewerWindow->setProgressPercent(frac*100); - gViewerWindow->setProgressString(string); - - gViewerWindow->setProgressMessage(msg); -} - -bool login_alert_status(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - // Buttons - switch( option ) - { - case 0: // OK - break; - // case 1: // Help - // LLWeb::loadURL(LLNotifications::instance().getGlobalString("SUPPORT_URL") ); - // break; - case 2: // Teleport - // Restart the login process, starting at our home locaton - LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - break; - default: - LL_WARNS("AppInit") << "Missing case in login_alert_status switch" << LL_ENDL; - } - - LLPanelLogin::giveFocus(); - return false; -} - - -void use_circuit_callback(void**, S32 result) -{ - // bail if we're quitting. - if(LLApp::isExiting()) return; - if( !gUseCircuitCallbackCalled ) - { - gUseCircuitCallbackCalled = true; - if (result) - { - // Make sure user knows something bad happened. JC - LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; - if (gRememberPassword) - { - LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); - } - else - { - LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); - } - reset_login(); - } - else - { - gGotUseCircuitCodeAck = true; - } - } -} - -void register_viewer_callbacks(LLMessageSystem* msg) -{ - msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data ); - msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update ); - msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update ); - msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update ); - msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved ); - msg->setHandlerFunc("SimStats", process_sim_stats); - msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message ); - msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data); - msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo); - - msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator); - msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL); - msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL); - msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator); - msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator); - msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL); - - msg->setHandlerFunc("CrossedRegion", process_crossed_region); - msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish); - - msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message); - msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message); - msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL); - msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message); - - msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value); - msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value); - msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation); - msg->setHandlerFuncFast(_PREHASH_ObjectAnimation, process_object_animation); - msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance); - msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint); - msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response); - msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties); - msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties); - - msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im); - msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question); - msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL); - msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL); - msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect); - - msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL); - msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL); - msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL); - msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL); - msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply, - &LLLiveLSLEditor::processScriptRunningReply); - - msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack); - - msg->setHandlerFunc("LogoutReply", process_logout_reply); - - //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility, - // &LLAgent::processAddModifyAbility); - //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility, - // &LLAgent::processRemoveModifyAbility); - msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate, - &LLAgent::processAgentDataUpdate); - msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate, - &LLAgent::processAgentGroupDataUpdate); - msg->setHandlerFunc("AgentDropGroup", - &LLAgent::processAgentDropGroup); - // land ownership messages - msg->setHandlerFuncFast(_PREHASH_ParcelOverlay, - LLViewerParcelMgr::processParcelOverlay); - msg->setHandlerFuncFast(_PREHASH_ParcelProperties, - LLViewerParcelMgr::processParcelProperties); - msg->setHandlerFunc("ParcelAccessListReply", - LLViewerParcelMgr::processParcelAccessListReply); - msg->setHandlerFunc("ParcelDwellReply", - LLViewerParcelMgr::processParcelDwellReply); - - msg->setHandlerFunc("AvatarPropertiesReply", - &LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply); - msg->setHandlerFunc("AvatarInterestsReply", - &LLAvatarPropertiesProcessor::processAvatarInterestsReply); - msg->setHandlerFunc("AvatarGroupsReply", - &LLAvatarPropertiesProcessor::processAvatarGroupsReply); - msg->setHandlerFunc("AvatarNotesReply", - &LLAvatarPropertiesProcessor::processAvatarNotesReply); - msg->setHandlerFunc("AvatarPicksReply", - &LLAvatarPropertiesProcessor::processAvatarPicksReply); - msg->setHandlerFunc("AvatarClassifiedReply", - &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply); - - msg->setHandlerFuncFast(_PREHASH_CreateGroupReply, - LLGroupMgr::processCreateGroupReply); - msg->setHandlerFuncFast(_PREHASH_JoinGroupReply, - LLGroupMgr::processJoinGroupReply); - msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply, - LLGroupMgr::processEjectGroupMemberReply); - msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply, - LLGroupMgr::processLeaveGroupReply); - msg->setHandlerFuncFast(_PREHASH_GroupProfileReply, - LLGroupMgr::processGroupPropertiesReply); - - // ratings deprecated - // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, - // LLFloaterRate::processReputationIndividualReply); - - msg->setHandlerFunc("ScriptControlChange", - LLAgent::processScriptControlChange ); - - msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect); - - msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers); - - msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply, - LLPanelGroupLandMoney::processGroupAccountSummaryReply); - msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply, - LLPanelGroupLandMoney::processGroupAccountDetailsReply); - msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply, - LLPanelGroupLandMoney::processGroupAccountTransactionsReply); - - msg->setHandlerFuncFast(_PREHASH_UserInfoReply, - process_user_info_reply); - - msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL); - - msg->setHandlerFunc("TeleportStart", process_teleport_start ); - msg->setHandlerFunc("TeleportProgress", process_teleport_progress); - msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL); - msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL); - - msg->setHandlerFunc("ImageNotInDatabase", LLViewerTextureList::processImageNotInDatabase, NULL); - - msg->setHandlerFuncFast(_PREHASH_GroupMembersReply, - LLGroupMgr::processGroupMembersReply); - msg->setHandlerFunc("GroupRoleDataReply", - LLGroupMgr::processGroupRoleDataReply); - msg->setHandlerFunc("GroupRoleMembersReply", - LLGroupMgr::processGroupRoleMembersReply); - msg->setHandlerFunc("GroupTitlesReply", - LLGroupMgr::processGroupTitlesReply); - // Special handler as this message is sometimes used for group land. - msg->setHandlerFunc("PlacesReply", process_places_reply); - msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply); - - msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); - - msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); - msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); - msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply); - - msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); - msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply); - msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply); - msg->setHandlerFunc("ScriptDialog", process_script_dialog); - msg->setHandlerFunc("LoadURL", process_load_url); - msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request); - msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply); - - // calling cards - msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard); - msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard); - msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard); - - msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply); - - msg->setHandlerFunc("InitiateDownload", process_initiate_download); - msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply); - msg->setHandlerFunc("GenericMessage", process_generic_message); - msg->setHandlerFunc("GenericStreamingMessage", process_generic_streaming_message); - msg->setHandlerFunc("LargeGenericMessage", process_large_generic_message); - - msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message); -} - -void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32) -{ - // nothing -} - -const S32 OPT_CLOSED_WINDOW = -1; -const S32 OPT_MALE = 0; -const S32 OPT_FEMALE = 1; -const S32 OPT_TRUST_CERT = 0; -const S32 OPT_CANCEL_TRUST = 1; - -bool callback_choose_gender(const LLSD& notification, const LLSD& response) -{ - - // These defaults are returned from the server on login. They are set in login.xml. - // If no default is returned from the server, they are retrieved from settings.xml. - - S32 option = LLNotification::getSelectedOption(notification, response); - switch(option) - { - case OPT_MALE: - LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultMaleAvatar"), "male" ); - break; - - case OPT_FEMALE: - case OPT_CLOSED_WINDOW: - default: - LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultFemaleAvatar"), "female" ); - break; - } - return false; -} - -std::string get_screen_filename(const std::string& pattern) -{ - if (LLGridManager::getInstance()->isInProductionGrid()) - { - return llformat(pattern.c_str(), ""); - } - else - { - const std::string& grid_id_str = LLGridManager::getInstance()->getGridId(); - const std::string& grid_id_lower = utf8str_tolower(grid_id_str); - std::string grid = "." + grid_id_lower; - return llformat(pattern.c_str(), grid.c_str()); - } -} - -//static -std::string LLStartUp::getScreenLastFilename() -{ - return get_screen_filename(SCREEN_LAST_FILENAME); -} - -//static -std::string LLStartUp::getScreenHomeFilename() -{ - return get_screen_filename(SCREEN_HOME_FILENAME); -} - -//static -void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, - const std::string& gender_name ) -{ - LL_DEBUGS() << "starting" << LL_ENDL; - - // Not going through the processAgentInitialWearables path, so need to set this here. - LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); - // Initiate creation of COF, since we're also bypassing that. - gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); - LLAppearanceMgr::getInstance()->initCOFID(); - - ESex gender; - if (gender_name == "male") - { - LL_DEBUGS() << "male" << LL_ENDL; - gender = SEX_MALE; - } - else - { - LL_DEBUGS() << "female" << LL_ENDL; - gender = SEX_FEMALE; - } - - if (!isAgentAvatarValid()) - { - LL_WARNS() << "Trying to load an initial outfit for an invalid agent avatar" << LL_ENDL; - return; - } - - gAgentAvatarp->setSex(gender); - - // try to find the requested outfit or folder - - // -- check for existing outfit in My Outfits - bool do_copy = false; - LLUUID cat_id = findDescendentCategoryIDByName( - gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS), - outfit_folder_name); - - // -- check for existing folder in Library - if (cat_id.isNull()) - { - cat_id = findDescendentCategoryIDByName( - gInventory.getLibraryRootFolderID(), - outfit_folder_name); - if (!cat_id.isNull()) - { - do_copy = true; - } - } - - if (cat_id.isNull()) - { - // -- final fallback: create standard wearables - LL_DEBUGS() << "standard wearables" << LL_ENDL; - gAgentWearables.createStandardWearables(); - } - else - { - bool do_append = false; - LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); - // Need to fetch cof contents before we can wear. - if (do_copy) - { - callAfterCOFFetch(boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); - } - else - { - callAfterCategoryLinksFetch(cat_id, boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); - } - LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL; - } - - gAgent.setOutfitChosen(true); - gAgentWearables.sendDummyAgentWearablesUpdate(); -} - -std::string& LLStartUp::getInitialOutfitName() -{ - return sInitialOutfit; -} - -std::string LLStartUp::getUserId() -{ - if (gUserCredential.isNull()) - { - return ""; - } - return gUserCredential->userID(); -} - - -// frees the bitmap -void release_start_screen() -{ - LL_DEBUGS("AppInit") << "Releasing bitmap..." << LL_ENDL; - gStartTexture = NULL; -} - - -// static -std::string LLStartUp::startupStateToString(EStartupState state) -{ -#define RTNENUM(E) case E: return #E - switch(state){ - RTNENUM( STATE_FIRST ); - RTNENUM( STATE_BROWSER_INIT ); - RTNENUM( STATE_LOGIN_SHOW ); - RTNENUM( STATE_LOGIN_WAIT ); - RTNENUM( STATE_LOGIN_CLEANUP ); - RTNENUM( STATE_LOGIN_AUTH_INIT ); - RTNENUM( STATE_LOGIN_CURL_UNSTUCK ); - RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); - RTNENUM( STATE_WORLD_INIT ); - RTNENUM( STATE_MULTIMEDIA_INIT ); - RTNENUM( STATE_FONT_INIT ); - RTNENUM( STATE_SEED_GRANTED_WAIT ); - RTNENUM( STATE_SEED_CAP_GRANTED ); - RTNENUM( STATE_WORLD_WAIT ); - RTNENUM( STATE_AGENT_SEND ); - RTNENUM( STATE_AGENT_WAIT ); - RTNENUM( STATE_INVENTORY_SEND ); - RTNENUM(STATE_INVENTORY_CALLBACKS ); - RTNENUM( STATE_INVENTORY_SKEL ); - RTNENUM( STATE_INVENTORY_SEND2 ); - RTNENUM( STATE_MISC ); - RTNENUM( STATE_PRECACHE ); - RTNENUM( STATE_WEARABLES_WAIT ); - RTNENUM( STATE_CLEANUP ); - RTNENUM( STATE_STARTED ); - default: - return llformat("(state #%d)", state); - } -#undef RTNENUM -} - -// static -void LLStartUp::setStartupState( EStartupState state ) -{ - LL_INFOS("AppInit") << "Startup state changing from " << - getStartupStateString() << " to " << - startupStateToString(state) << LL_ENDL; - - getPhases().stopPhase(getStartupStateString()); - gStartupState = state; - getPhases().startPhase(getStartupStateString()); - - postStartupState(); -} - -void LLStartUp::postStartupState() -{ - LLSD stateInfo; - stateInfo["str"] = getStartupStateString(); - stateInfo["enum"] = gStartupState; - sStateWatcher->post(stateInfo); - gDebugInfo["StartupState"] = getStartupStateString(); -} - - -void reset_login() -{ - gAgentWearables.cleanup(); - gAgentCamera.cleanup(); - gAgent.cleanup(); - gSky.cleanup(); // mVOSkyp is an inworld object. - LLWorld::getInstance()->resetClass(); - LLAppearanceMgr::getInstance()->cleanup(); - - if ( gViewerWindow ) - { // Hide menus and normal buttons - gViewerWindow->setNormalControlsVisible( false ); - gLoginMenuBarView->setVisible( true ); - gLoginMenuBarView->setEnabled( true ); - } - - // Hide any other stuff - LLFloaterReg::hideVisibleInstances(); - - if (LLStartUp::getStartupState() > STATE_WORLD_INIT) - { - gViewerWindow->resetStatusBarContainer(); - } - LLStartUp::setStartupState( STATE_BROWSER_INIT ); - - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->terminate(); - } - - // Clear any verified certs and verify them again on next login - // to ensure cert matches server instead of just getting reused - LLPointer store = gSecAPIHandler->getCertificateStore(""); - store->clearSertCache(); -} - -//--------------------------------------------------------------------------- - -// Initialize all plug-ins except the web browser (which was initialized -// early, before the login screen). JC -void LLStartUp::multimediaInit() -{ - LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL; - std::string msg = LLTrans::getString("LoginInitializingMultimedia"); - set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); -} - -void LLStartUp::fontInit() -{ - LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL; - std::string msg = LLTrans::getString("LoginInitializingFonts"); - set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); - - LLFontGL::loadDefaultFonts(); -} - -void LLStartUp::initNameCache() -{ - // Can be called multiple times - if ( gCacheName ) return; - - gCacheName = new LLCacheName(gMessageSystem); - gCacheName->addObserver(&callback_cache_name); - gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting")); - gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody")); - gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone")); - // Load stored cache if possible - LLAppViewer::instance()->loadNameCache(); - - // Start cache in not-running state until we figure out if we have - // capabilities for display name lookup - LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance(); - cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI")); - cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); - cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); -} - - -void LLStartUp::initExperiences() -{ - // Should trigger loading the cache. - LLExperienceCache::instance().setCapabilityQuery( - boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); - - LLExperienceLog::instance().initialize(); -} - -void LLStartUp::cleanupNameCache() -{ - delete gCacheName; - gCacheName = NULL; -} - -bool LLStartUp::dispatchURL() -{ - // ok, if we've gotten this far and have a startup URL - if (!getStartSLURL().isValid()) - { - return false; - } - if(getStartSLURL().getType() != LLSLURL::APP) - { - - // If we started with a location, but we're already - // at that location, don't pop dialogs open. - LLVector3 pos = gAgent.getPositionAgent(); - LLVector3 slurlpos = getStartSLURL().getPosition(); - F32 dx = pos.mV[VX] - slurlpos.mV[VX]; - F32 dy = pos.mV[VY] - slurlpos.mV[VY]; - const F32 SLOP = 2.f; // meters - - if( getStartSLURL().getRegion() != gAgent.getRegion()->getName() - || (dx*dx > SLOP*SLOP) - || (dy*dy > SLOP*SLOP) ) - { - LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, - NULL, false); - } - return true; - } - return false; -} - -void LLStartUp::setStartSLURL(const LLSLURL& slurl) -{ - LL_DEBUGS("AppInit")< socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); - std::string socks_user = socks_cred->getIdentifier()["username"].asString(); - std::string socks_password = socks_cred->getAuthenticator()["creds"].asString(); - - bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password); - - if (!ok) - { - LLNotificationsUtil::add("SOCKS_BAD_CREDS"); - proxy_ok = false; - } - } - else if (auth_type.compare("None") == 0) - { - LLProxy::getInstance()->setAuthNone(); - } - else - { - LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL; - - // Unknown or missing setting. - gSavedSettings.setString("Socks5AuthType", "None"); - - // Clear the SOCKS credentials. - LLPointer socks_cred = new LLCredential("SOCKS5"); - gSecAPIHandler->deleteCredential(socks_cred); - - LLProxy::getInstance()->setAuthNone(); - } - - if (proxy_ok) - { - // Start the proxy and check for errors - // If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns. - LLHost socks_host; - socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); - socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); - int status = LLProxy::getInstance()->startSOCKSProxy(socks_host); - - if (status != SOCKS_OK) - { - LLSD subs; - subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); - subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); - - std::string error_string; - - switch(status) - { - case SOCKS_CONNECT_ERROR: // TCP Fail - error_string = "SOCKS_CONNECT_ERROR"; - break; - - case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection - error_string = "SOCKS_NOT_PERMITTED"; - break; - - case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server - error_string = "SOCKS_NOT_ACCEPTABLE"; - break; - - case SOCKS_AUTH_FAIL: // Authentication failed - error_string = "SOCKS_AUTH_FAIL"; - break; - - case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed - error_string = "SOCKS_UDP_FWD_NOT_GRANTED"; - break; - - case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server - error_string = "SOCKS_HOST_CONNECT_FAILED"; - break; - - case SOCKS_INVALID_HOST: // Improperly formatted host address or port. - error_string = "SOCKS_INVALID_HOST"; - break; - - default: - error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened, - LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL; - break; - } - - LLNotificationsUtil::add(error_string, subs); - proxy_ok = false; - } - } - } - else - { - LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up - } - - if (proxy_ok) - { - // Determine the HTTP proxy type (if any) - if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) - { - LLHost http_host; - http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); - http_host.setPort(gSavedSettings.getS32("BrowserProxyPort")); - if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP)) - { - LLSD subs; - subs["HOST"] = http_host.getIPString(); - subs["PORT"] = (S32)http_host.getPort(); - LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs); - proxy_ok = false; - } - } - else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) - { - LLHost socks_host; - socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); - socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); - if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS)) - { - LLSD subs; - subs["HOST"] = socks_host.getIPString(); - subs["PORT"] = (S32)socks_host.getPort(); - LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs); - proxy_ok = false; - } - } - else if (httpProxyType.compare("None") == 0) - { - LLProxy::getInstance()->disableHTTPProxy(); - } - else - { - LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration: " << httpProxyType << LL_ENDL; - - // Set the missing or wrong configuration back to something valid. - gSavedSettings.setString("HttpProxyType", "None"); - LLProxy::getInstance()->disableHTTPProxy(); - - // Leave proxy_ok alone, since this isn't necessarily fatal. - } - } - - return proxy_ok; -} - -bool login_alert_done(const LLSD& notification, const LLSD& response) -{ - LLPanelLogin::giveFocus(); - return false; -} - -// parse the certificate information into args for the -// certificate notifications -LLSD transform_cert_args(LLPointer cert) -{ - LLSD args = LLSD::emptyMap(); - std::string value; - LLSD cert_info; - cert->getLLSD(cert_info); - // convert all of the elements in the cert into - // args for the xml dialog, so we have flexability to - // display various parts of the cert by only modifying - // the cert alert dialog xml. - for(LLSD::map_iterator iter = cert_info.beginMap(); - iter != cert_info.endMap(); - iter++) - { - // key usage and extended key usage - // are actually arrays, and we want to format them as comma separated - // strings, so special case those. - LLSDSerialize::toXML(cert_info[iter->first], std::cout); - if((iter->first == std::string(CERT_KEY_USAGE)) || - (iter->first == std::string(CERT_EXTENDED_KEY_USAGE))) - { - value = ""; - LLSD usage = cert_info[iter->first]; - for (LLSD::array_iterator usage_iter = usage.beginArray(); - usage_iter != usage.endArray(); - usage_iter++) - { - - if(usage_iter != usage.beginArray()) - { - value += ", "; - } - - value += (*usage_iter).asString(); - } - - } - else - { - value = iter->second.asString(); - } - - std::string name = iter->first; - std::transform(name.begin(), name.end(), name.begin(), - (int(*)(int))toupper); - args[name.c_str()] = value; - } - return args; -} - - -// when we handle a cert error, give focus back to the login panel -void general_cert_done(const LLSD& notification, const LLSD& response) -{ - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - LLPanelLogin::giveFocus(); -} - -// check to see if the user wants to trust the cert. -// if they do, add it to the cert store and -void trust_cert_done(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - switch(option) - { - case OPT_TRUST_CERT: - { - LLPointer cert = gSecAPIHandler->getCertificate(notification["payload"]["certificate"]); - LLPointer store = gSecAPIHandler->getCertificateStore(gSavedSettings.getString("CertStore")); - store->add(cert); - store->save(); - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - break; - } - case OPT_CANCEL_TRUST: - reset_login(); - gSavedSettings.setBOOL("AutoLogin", false); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - default: - LLPanelLogin::giveFocus(); - break; - } - -} - -void apply_udp_blacklist(const std::string& csv) -{ - - std::string::size_type start = 0; - std::string::size_type comma = 0; - do - { - comma = csv.find(",", start); - if (comma == std::string::npos) - { - comma = csv.length(); - } - std::string item(csv, start, comma-start); - - LL_DEBUGS() << "udp_blacklist " << item << LL_ENDL; - gMessageSystem->banUdpMessage(item); - - start = comma + 1; - - } - while(comma < csv.length()); - -} - -void on_benefits_failed_callback(const LLSD& notification, const LLSD& response) -{ - LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL; -} - -bool init_benefits(LLSD& response) -{ - bool succ = true; - - std::string package_name = response["account_type"].asString(); - const LLSD& benefits_sd = response["account_level_benefits"]; - if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) || - !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd)) - { - succ = false; - } - else - { - LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL; - } - const LLSD& packages_sd = response["premium_packages"]; - for(LLSD::map_const_iterator package_iter = packages_sd.beginMap(); - package_iter != packages_sd.endMap(); - ++package_iter) - { - std::string package_name = package_iter->first; - const LLSD& benefits_sd = package_iter->second["benefits"]; - if (LLAgentBenefitsMgr::init(package_name, benefits_sd)) - { - LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL; - } - else - { - LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL; - succ = false; - } - } - - if (!LLAgentBenefitsMgr::has("Base")) - { - LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL; - succ = false; - } - if (!LLAgentBenefitsMgr::has("Premium")) - { - LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL; - succ = false; - } - - return succ; -} - -bool process_login_success_response() -{ - LLSD response = LLLoginInstance::getInstance()->getResponse(); - - mBenefitsSuccessfullyInit = init_benefits(response); - - std::string text(response["udp_blacklist"]); - if(!text.empty()) - { - apply_udp_blacklist(text); - } - - // unpack login data needed by the application - text = response["agent_id"].asString(); - if(!text.empty()) gAgentID.set(text); - gDebugInfo["AgentID"] = text; - - LLPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("PerfStatsCaptureEnabled")); - LLPerfStats::StatsRecorder::setFocusAv(gAgentID); - - // Agent id needed for parcel info request in LLUrlEntryParcel - // to resolve parcel name. - LLUrlEntryParcel::setAgentID(gAgentID); - - text = response["session_id"].asString(); - if(!text.empty()) gAgentSessionID.set(text); - gDebugInfo["SessionID"] = text; - - // Session id needed for parcel info request in LLUrlEntryParcel - // to resolve parcel name. - LLUrlEntryParcel::setSessionID(gAgentSessionID); - - text = response["secure_session_id"].asString(); - if(!text.empty()) gAgent.mSecureSessionID.set(text); - - // if the response contains a display name, use that, - // otherwise if the response contains a first and/or last name, - // use those. Otherwise use the credential identifier - - gDisplayName = ""; - if (response.has("display_name")) - { - gDisplayName.assign(response["display_name"].asString()); - if(!gDisplayName.empty()) - { - // Remove quotes from string. Login.cgi sends these to force - // names that look like numbers into strings. - LLStringUtil::replaceChar(gDisplayName, '"', ' '); - LLStringUtil::trim(gDisplayName); - } - } - std::string first_name; - if(response.has("first_name")) - { - first_name = response["first_name"].asString(); - LLStringUtil::replaceChar(first_name, '"', ' '); - LLStringUtil::trim(first_name); - gAgentUsername = first_name; - } - - if(response.has("last_name") && !gAgentUsername.empty()) - { - std::string last_name = response["last_name"].asString(); - if (last_name != "Resident") - { - LLStringUtil::replaceChar(last_name, '"', ' '); - LLStringUtil::trim(last_name); - gAgentUsername = gAgentUsername + " " + last_name; - } - } - - if(gDisplayName.empty()) - { - if(response.has("first_name")) - { - gDisplayName.assign(response["first_name"].asString()); - LLStringUtil::replaceChar(gDisplayName, '"', ' '); - LLStringUtil::trim(gDisplayName); - } - if(response.has("last_name")) - { - text.assign(response["last_name"].asString()); - LLStringUtil::replaceChar(text, '"', ' '); - LLStringUtil::trim(text); - if(!gDisplayName.empty()) - { - gDisplayName += " "; - } - gDisplayName += text; - } - } - - if(gDisplayName.empty()) - { - gDisplayName.assign(gUserCredential->asString()); - } - - // this is their actual ability to access content - text = response["agent_access_max"].asString(); - if (!text.empty()) - { - // agent_access can be 'A', 'M', and 'PG'. - gAgent.setMaturity(text[0]); - } - - // this is the value of their preference setting for that content - // which will always be <= agent_access_max - text = response["agent_region_access"].asString(); - if (!text.empty()) - { - U32 preferredMaturity = (U32)LLAgent::convertTextToMaturity(text[0]); - - gSavedSettings.setU32("PreferredMaturity", preferredMaturity); - } - - text = response["start_location"].asString(); - if(!text.empty()) - { - gAgentStartLocation.assign(text); - } - - text = response["circuit_code"].asString(); - if(!text.empty()) - { - gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10); - } - std::string sim_ip_str = response["sim_ip"]; - std::string sim_port_str = response["sim_port"]; - if(!sim_ip_str.empty() && !sim_port_str.empty()) - { - U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); - gFirstSim.set(sim_ip_str, sim_port); - if (gFirstSim.isOk()) - { - gMessageSystem->enableCircuit(gFirstSim, true); - } - } - std::string region_x_str = response["region_x"]; - std::string region_y_str = response["region_y"]; - if(!region_x_str.empty() && !region_y_str.empty()) - { - U32 region_x = strtoul(region_x_str.c_str(), NULL, 10); - U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); - gFirstSimHandle = to_region_handle(region_x, region_y); - } - - const std::string look_at_str = response["look_at"]; - if (!look_at_str.empty()) - { - size_t len = look_at_str.size(); - LLMemoryStream mstr((U8*)look_at_str.c_str(), len); - LLSD sd = LLSDSerialize::fromNotation(mstr, len); - gAgentStartLookAt = ll_vector3_from_sd(sd); - } - - text = response["seed_capability"].asString(); - if (!text.empty()) gFirstSimSeedCap = text; - - text = response["seconds_since_epoch"].asString(); - if(!text.empty()) - { - U32 server_utc_time = strtoul(text.c_str(), NULL, 10); - if(server_utc_time) - { - time_t now = time(NULL); - gUTCOffset = (server_utc_time - now); - - // Print server timestamp - LLSD substitution; - substitution["datetime"] = (S32)server_utc_time; - std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]"; - LLStringUtil::format(timeStr, substitution); - LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL; - } - } - - // this is the base used to construct help URLs - text = response["help_url_format"].asString(); - if (!text.empty()) - { - // replace the default help URL format - gSavedSettings.setString("HelpURLFormat",text); - } - - std::string home_location = response["home"]; - if(!home_location.empty()) - { - size_t len = home_location.size(); - LLMemoryStream mstr((U8*)home_location.c_str(), len); - LLSD sd = LLSDSerialize::fromNotation(mstr, len); - S32 region_x = sd["region_handle"][0].asInteger(); - S32 region_y = sd["region_handle"][1].asInteger(); - U64 region_handle = to_region_handle(region_x, region_y); - LLVector3 position = ll_vector3_from_sd(sd["position"]); - gAgent.setHomePosRegion(region_handle, position); - } - - gAgent.mMOTD.assign(response["message"]); - - // Options... - // Each 'option' is an array of submaps. - // It appears that we only ever use the first element of the array. - LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"]; - if(inv_root_folder_id.notNull()) - { - gInventory.setRootFolderID(inv_root_folder_id); - //gInventory.mock(gAgent.getInventoryRootID()); - } - - LLSD login_flags = response["login-flags"][0]; - if(login_flags.size()) - { - std::string flag = login_flags["ever_logged_in"]; - if(!flag.empty()) - { - gAgent.setFirstLogin(flag == "N"); - } - - /* Flag is currently ignored by the viewer. - flag = login_flags["stipend_since_login"]; - if(flag == "Y") - { - stipend_since_login = true; - } - */ - - flag = login_flags["gendered"].asString(); - if(flag == "Y") - { - // We don't care about this flag anymore; now base whether - // outfit is chosen on COF contents, initial outfit - // requested and available, etc. - - //gAgent.setGenderChosen(true); - } - - bool pacific_daylight_time = false; - flag = login_flags["daylight_savings"].asString(); - if(flag == "Y") - { - pacific_daylight_time = (flag == "Y"); - } - - //setup map of datetime strings to codes and slt & local time offset from utc - LLStringOps::setupDatetimeInfo(pacific_daylight_time); - } - - // set up the voice configuration. Ultimately, we should pass this up as part of each voice - // channel if we need to move to multiple voice servers per grid. - LLSD voice_config_info = response["voice-config"]; - if(voice_config_info.has("VoiceServerType")) - { - gSavedSettings.setString("VoiceServerType", voice_config_info["VoiceServerType"].asString()); - } - - // Request the map server url - std::string map_server_url = response["map-server-url"]; - if(!map_server_url.empty()) - { - // We got an answer from the grid -> use that for map for the current session - gSavedSettings.setString("CurrentMapServerURL", map_server_url); - LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL; - } - else - { - // No answer from the grid -> use the default setting for current session - map_server_url = gSavedSettings.getString("MapServerURL"); - gSavedSettings.setString("CurrentMapServerURL", map_server_url); - LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL; - } - - // Default male and female avatars allowing the user to choose their avatar on first login. - // These may be passed up by SLE to allow choice of enterprise avatars instead of the standard - // "new ruth." Not to be confused with 'initial-outfit' below - LLSD newuser_config = response["newuser-config"][0]; - if(newuser_config.has("DefaultFemaleAvatar")) - { - gSavedSettings.setString("DefaultFemaleAvatar", newuser_config["DefaultFemaleAvatar"].asString()); - } - if(newuser_config.has("DefaultMaleAvatar")) - { - gSavedSettings.setString("DefaultMaleAvatar", newuser_config["DefaultMaleAvatar"].asString()); - } - - // Initial outfit for the user. - LLSD initial_outfit = response["initial-outfit"][0]; - if(initial_outfit.size()) - { - std::string flag = initial_outfit["folder_name"]; - if(!flag.empty()) - { - // Initial outfit is a folder in your inventory, - // must be an exact folder-name match. - sInitialOutfit = flag; - } - - flag = initial_outfit["gender"].asString(); - if(!flag.empty()) - { - sInitialOutfitGender = flag; - } - } - - std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName"); - if (!fake_initial_outfit_name.empty()) - { - gAgent.setFirstLogin(true); - sInitialOutfit = fake_initial_outfit_name; - if (sInitialOutfitGender.empty()) - { - sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway. - } - - LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL; - } - - // set the location of the Agent Appearance service, from which we can request - // avatar baked textures if they are supported by the current region - std::string agent_appearance_url = response["agent_appearance_service"]; - if (!agent_appearance_url.empty()) - { - LLAppearanceMgr::instance().setAppearanceServiceURL(agent_appearance_url); - } - - // Set the location of the snapshot sharing config endpoint - std::string snapshot_config_url = response["snapshot_config_url"]; - if(!snapshot_config_url.empty()) - { - gSavedSettings.setString("SnapshotConfigURL", snapshot_config_url); - } - - // Start the process of fetching the OpenID session cookie for this user login - std::string openid_url = response["openid_url"]; - if(!openid_url.empty()) - { - std::string openid_token = response["openid_token"]; - LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token); - } - - - // Only save mfa_hash for future logins if the user wants their info remembered. - if(response.has("mfa_hash") - && gSavedSettings.getBOOL("RememberUser") - && LLLoginInstance::getInstance()->saveMFA()) - { - std::string grid(LLGridManager::getInstance()->getGridId()); - std::string user_id(gUserCredential->userID()); - gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, response["mfa_hash"]); - // TODO(brad) - related to SL-17223 consider building a better interface that sync's automatically - gSecAPIHandler->syncProtectedMap(); - } - else if (!LLLoginInstance::getInstance()->saveMFA()) - { - std::string grid(LLGridManager::getInstance()->getGridId()); - std::string user_id(gUserCredential->userID()); - gSecAPIHandler->removeFromProtectedMap("mfa_hash", grid, user_id); - gSecAPIHandler->syncProtectedMap(); - } - - bool success = false; - // JC: gesture loading done below, when we have an asset system - // in place. Don't delete/clear gUserCredentials until then. - if(gAgentID.notNull() - && gAgentSessionID.notNull() - && gMessageSystem->mOurCircuitCode - && gFirstSim.isOk() - && gInventory.getRootFolderID().notNull()) - { - success = true; - } - LLAppViewer* pApp = LLAppViewer::instance(); - pApp->writeDebugInfo(); //Write our static data now that we have username, session_id, etc. - return success; -} - -void transition_back_to_login_panel(const std::string& emsg) -{ - // Bounce back to the login screen. - reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - gSavedSettings.setBOOL("AutoLogin", false); -} - +/** + * @file llstartup.cpp + * @brief startup routines. + * + * $LicenseInfo:firstyear=2004&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 "llviewerprecompiledheaders.h" + +#include "llappviewer.h" +#include "llstartup.h" +#include "llcallstack.h" + +#if LL_WINDOWS +# include // _spawnl() +#else +# include // mkdir() +#endif +#include // std::unique_ptr + +#include "llviewermedia_streamingaudio.h" +#include "llaudioengine.h" + +#ifdef LL_OPENAL +#include "llaudioengine_openal.h" +#endif + +#include "llavatarnamecache.h" +#include "llexperiencecache.h" +#include "lllandmark.h" +#include "llcachename.h" +#include "lldir.h" +#include "lldonotdisturbnotificationstorage.h" +#include "llerrorcontrol.h" +#include "llfloaterreg.h" +#include "llfocusmgr.h" +#include "llfloatergridstatus.h" +#include "llfloaterimsession.h" +#include "lllocationhistory.h" +#include "llgltfmateriallist.h" +#include "llimageworker.h" + +#include "llloginflags.h" +#include "llmd5.h" +#include "llmemorystream.h" +#include "llmessageconfig.h" +#include "llmoveview.h" +#include "llfloaterimcontainer.h" +#include "llfloaterimnearbychat.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpersistentnotificationstorage.h" +#include "llpresetsmanager.h" +#include "llteleporthistory.h" +#include "llregionhandle.h" +#include "llsd.h" +#include "llsdserialize.h" +#include "llsdutil_math.h" +#include "llstring.h" +#include "lluserrelations.h" +#include "llversioninfo.h" +#include "llviewercontrol.h" +#include "llviewerhelp.h" +#include "llxorcipher.h" // saved password, MAC address +#include "llwindow.h" +#include "message.h" +#include "v3math.h" + +#include "llagent.h" +#include "llagentbenefits.h" +#include "llagentcamera.h" +#include "llagentpicksinfo.h" +#include "llagentwearables.h" +#include "llagentpilot.h" +#include "llfloateravatarpicker.h" +#include "llcallbacklist.h" +#include "llcallingcard.h" +#include "llclassifiedinfo.h" +#include "llconsole.h" +#include "llcontainerview.h" +#include "llconversationlog.h" +#include "lldebugview.h" +#include "lldrawable.h" +#include "lleventnotifier.h" +#include "llface.h" +#include "llfeaturemanager.h" +//#include "llfirstuse.h" +#include "llfloaterhud.h" +#include "llfloaterland.h" +#include "llfloatertopobjects.h" +#include "llfloaterworldmap.h" +#include "llgesturemgr.h" +#include "llgroupmgr.h" +#include "llhudeffecttrail.h" +#include "llhudmanager.h" +#include "llimage.h" +#include "llinventorybridge.h" +#include "llinventorymodel.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llkeyboard.h" +#include "llloginhandler.h" // gLoginHandler, SLURL support +#include "lllogininstance.h" // Host the login module. +#include "llpanellogin.h" +#include "llmutelist.h" +#include "llavatarpropertiesprocessor.h" +#include "llpanelgrouplandmoney.h" +#include "llpanelgroupnotices.h" +#include "llparcel.h" +#include "llpreview.h" +#include "llpreviewscript.h" +#include "llproxy.h" +#include "llproductinforequest.h" +#include "llqueryflags.h" +#include "llsecapi.h" +#include "llselectmgr.h" +#include "llsky.h" +#include "llstatview.h" +#include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance +#include "llsurface.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "lltoolmgr.h" +#include "lltrans.h" +#include "llui.h" +#include "lluiusage.h" +#include "llurldispatcher.h" +#include "llurlentry.h" +#include "llslurl.h" +#include "llurlhistory.h" +#include "llurlwhitelist.h" +#include "llvieweraudio.h" +#include "llviewerassetstorage.h" +#include "llviewercamera.h" +#include "llviewerdisplay.h" +#include "llviewergenericmessage.h" +#include "llviewergesture.h" +#include "llviewertexturelist.h" +#include "llviewermedia.h" +#include "llviewermenu.h" +#include "llviewermessage.h" +#include "llviewernetwork.h" +#include "llviewerobjectlist.h" +#include "llviewerparcelaskplay.h" +#include "llviewerparcelmedia.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llviewerstatsrecorder.h" +#include "llviewerthrottle.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llvoavatarself.h" +#include "llweb.h" +#include "llworld.h" +#include "llworldmapmessage.h" +#include "llxfermanager.h" +#include "pipeline.h" +#include "llappviewer.h" +#include "llfasttimerview.h" +#include "llfloatermap.h" +#include "llweb.h" +#include "llvoiceclient.h" +#include "llnamelistctrl.h" +#include "llnamebox.h" +#include "llnameeditor.h" +#include "llpostprocess.h" +#include "llagentlanguage.h" +#include "llwearable.h" +#include "llinventorybridge.h" +#include "llappearancemgr.h" +#include "llavatariconctrl.h" +#include "llvoicechannel.h" +#include "llpathfindingmanager.h" +#include "llremoteparcelrequest.h" + +#include "lllogin.h" +#include "llevents.h" +#include "llstartuplistener.h" +#include "lltoolbarview.h" +#include "llexperiencelog.h" +#include "llcleanup.h" + +#include "llenvironment.h" + +#include "llstacktrace.h" + +#include "threadpool.h" +#include "llperfstats.h" + + +#if LL_WINDOWS +#include "lldxhardware.h" +#endif + +// +// exported globals +// +bool gAgentMovementCompleted = false; + +const std::string SCREEN_HOME_FILENAME = "screen_home%s.png"; +const std::string SCREEN_LAST_FILENAME = "screen_last%s.png"; + +LLPointer gStartTexture; + +// +// Imported globals +// +extern S32 gStartImageWidth; +extern S32 gStartImageHeight; + +// +// local globals +// +static bool gGotUseCircuitCodeAck = false; +static std::string sInitialOutfit; +static std::string sInitialOutfitGender; // "male" or "female" + +static bool gUseCircuitCallbackCalled = false; + +EStartupState LLStartUp::gStartupState = STATE_FIRST; +LLSLURL LLStartUp::sStartSLURL; + +static LLPointer gUserCredential; +static std::string gDisplayName; +static bool gRememberPassword = true; +static bool gRememberUser = true; + +static U64 gFirstSimHandle = 0; +static LLHost gFirstSim; +static std::string gFirstSimSeedCap; +static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f); +static std::string gAgentStartLocation = "safe"; +static bool mLoginStatePastUI = false; +static bool mBenefitsSuccessfullyInit = false; + +const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds +const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT = 4; // Give region 4 chances + +std::unique_ptr LLStartUp::sStateWatcher(new LLEventStream("StartupState")); +std::unique_ptr LLStartUp::sListener(new LLStartupListener()); +std::unique_ptr LLStartUp::sPhases(new LLViewerStats::PhaseMap); + +// +// local function declaration +// + +void login_show(); +void login_callback(S32 option, void* userdata); +void show_release_notes_if_required(); +void show_first_run_dialog(); +bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); +void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); +bool login_alert_status(const LLSD& notification, const LLSD& response); +void use_circuit_callback(void**, S32 result); +void register_viewer_callbacks(LLMessageSystem* msg); +void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32); +bool callback_choose_gender(const LLSD& notification, const LLSD& response); +void release_start_screen(); +void reset_login(); +LLSD transform_cert_args(LLPointer cert); +void general_cert_done(const LLSD& notification, const LLSD& response); +void trust_cert_done(const LLSD& notification, const LLSD& response); +void apply_udp_blacklist(const std::string& csv); +bool process_login_success_response(); +void on_benefits_failed_callback(const LLSD& notification, const LLSD& response); +void transition_back_to_login_panel(const std::string& emsg); + +void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group) +{ + LLNameBox::refreshAll(id, full_name, is_group); + LLNameEditor::refreshAll(id, full_name, is_group); + + // TODO: Actually be intelligent about the refresh. + // For now, just brute force refresh the dialogs. + dialog_refresh_all(); +} + +// +// exported functionality +// + +void pump_idle_startup_network(void) +{ + { + LockMessageChecker lmc(gMessageSystem); + while (lmc.checkAllMessages(gFrameCount, gServicePump)) + { + display_startup(); + } + lmc.processAcks(); + } + display_startup(); +} + +// +// local classes +// +void update_texture_fetch() +{ + LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread + LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread + LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread + gTextureList.updateImages(0.10f); + + if (LLImageGLThread::sEnabledTextures) + { + std::shared_ptr main_queue = LL::WorkQueue::getInstance("mainloop"); + main_queue->runFor(std::chrono::milliseconds(1)); + } +} + +void set_flags_and_update_appearance() +{ + LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); + LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op); + + LLInventoryModelBackgroundFetch::instance().start(); +} + +// Returns false to skip other idle processing. Should only return +// true when all initialization done. +bool idle_startup() +{ + if (gViewerWindow == NULL) + { + // We expect window to be initialized + LL_WARNS_ONCE() << "gViewerWindow is not initialized" << LL_ENDL; + return false; // No world yet + } + + const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay"); + static LLTimer timeout; + + static LLTimer login_time; + + // until this is encapsulated, this little hack for the + // auth/transform loop will do. + static F32 progress = 0.10f; + + static std::string auth_desc; + static std::string auth_message; + + static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server + + // last location by default + static S32 agent_location_id = START_LOCATION_ID_LAST; + + static bool show_connect_box = true; + + //static bool stipend_since_login = false; + + // HACK: These are things from the main loop that usually aren't done + // until initialization is complete, but need to be done here for things + // to work. + gIdleCallbacks.callFunctions(); + gViewerWindow->updateUI(); + + LLMortician::updateClass(); + + const std::string delims (" "); + std::string system; + int begIdx, endIdx; + std::string osString = LLOSInfo::instance().getOSStringSimple(); + + begIdx = osString.find_first_not_of (delims); + endIdx = osString.find_first_of (delims, begIdx); + system = osString.substr (begIdx, endIdx - begIdx); + system += "Locale"; + + LLStringUtil::setLocale (LLTrans::getString(system)); + + //note: Removing this line will cause incorrect button size in the login screen. -- bao. + gTextureList.updateImages(0.01f) ; + + if ( STATE_FIRST == LLStartUp::getStartupState() ) + { + static bool first_call = true; + if (first_call) + { + // Other phases get handled when startup state changes, + // need to capture the initial state as well. + LLStartUp::getPhases().startPhase(LLStartUp::getStartupStateString()); + first_call = false; + } + + gViewerWindow->showCursor(); + gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); + + ///////////////////////////////////////////////// + // + // Initialize stuff that doesn't need data from simulators + // + std::string lastGPU = gSavedSettings.getString("LastGPUString"); + std::string thisGPU = LLFeatureManager::getInstance()->getGPUString(); + + if (LLFeatureManager::getInstance()->isSafe()) + { + LLNotificationsUtil::add("DisplaySetToSafe"); + } + else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) && + (gSavedSettings.getS32("LastFeatureVersion") != 0)) + { + LLNotificationsUtil::add("DisplaySetToRecommendedFeatureChange"); + } + else if ( ! lastGPU.empty() && (lastGPU != thisGPU)) + { + LLSD subs; + subs["LAST_GPU"] = lastGPU; + subs["THIS_GPU"] = thisGPU; + LLNotificationsUtil::add("DisplaySetToRecommendedGPUChange", subs); + } + else if (!gViewerWindow->getInitAlert().empty()) + { + LLNotificationsUtil::add(gViewerWindow->getInitAlert()); + } + + //------------------------------------------------- + // Init the SOCKS 5 proxy if the user has configured + // one. We need to do this early in case the user + // is using SOCKS for HTTP so we get the login + // screen and HTTP tables via SOCKS. + //------------------------------------------------- + LLStartUp::startLLProxy(); + + gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion()); + gSavedSettings.setString("LastGPUString", thisGPU); + + + std::string xml_file = LLUI::locateSkin("xui_version.xml"); + LLXMLNodePtr root; + bool xml_ok = false; + if (LLXMLNode::parseFile(xml_file, root, NULL)) + { + if( (root->hasName("xui_version") ) ) + { + std::string value = root->getValue(); + F32 version = 0.0f; + LLStringUtil::convertToF32(value, version); + if (version >= 1.0f) + { + xml_ok = true; + } + } + } + if (!xml_ok) + { + // If XML is bad, there's a good possibility that notifications.xml is ALSO bad. + // If that's so, then we'll get a fatal error on attempting to load it, + // which will display a nontranslatable error message that says so. + // Otherwise, we'll display a reasonable error message that IS translatable. + LLAppViewer::instance()->earlyExit("BadInstallation"); + } + // + // Statistics stuff + // + + // Load autopilot and stats stuff + gAgentPilot.load(); + + //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps")); + + // Load the throttle settings + gViewerThrottle.load(); + + // + // Initialize messaging system + // + LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL; + + std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); + + LLFILE* found_template = NULL; + found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */ + + #if LL_WINDOWS + // On the windows dev builds, unpackaged, the message_template.msg + // file will be located in: + // build-vc**/newview//app_settings + if (!found_template) + { + message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg"); + found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + } + #elif LL_DARWIN + // On Mac dev builds, message_template.msg lives in: + // indra/build-*/newview//Second Life/Contents/Resources/app_settings + if (!found_template) + { + message_template_path = + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, + "message_template.msg"); + found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + } + #endif + + if (found_template) + { + fclose(found_template); + + U32 port = gSavedSettings.getU32("UserConnectionPort"); + + if ((NET_USE_OS_ASSIGNED_PORT == port) && // if nothing specified on command line (-port) + (gSavedSettings.getBOOL("ConnectionPortEnabled"))) + { + port = gSavedSettings.getU32("ConnectionPort"); + } + + // TODO parameterize + const F32 circuit_heartbeat_interval = 5; + const F32 circuit_timeout = 100; + + const LLUseCircuitCodeResponder* responder = NULL; + bool failure_is_fatal = true; + + if(!start_messaging_system( + message_template_path, + port, + LLVersionInfo::instance().getMajor(), + LLVersionInfo::instance().getMinor(), + LLVersionInfo::instance().getPatch(), + false, + std::string(), + responder, + failure_is_fatal, + circuit_heartbeat_interval, + circuit_timeout)) + { + std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode()); + LL_WARNS("AppInit") << diagnostic << LL_ENDL; + LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic)); + } + + #if LL_WINDOWS + // On the windows dev builds, unpackaged, the message.xml file will + // be located in indra/build-vc**/newview//app_settings. + std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml"); + + if (!LLFile::isfile(message_path.c_str())) + { + LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "")); + } + else + { + LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + } + #else + LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + #endif + + } + else + { + LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path)); + } + + if(gMessageSystem && gMessageSystem->isOK()) + { + // Initialize all of the callbacks in case of bad message + // system data + LLMessageSystem* msg = gMessageSystem; + msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE, + invalid_message_callback, + NULL); + msg->setExceptionFunc(MX_PACKET_TOO_SHORT, + invalid_message_callback, + NULL); + + // running off end of a packet is now valid in the case + // when a reader has a newer message template than + // the sender + /*msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET, + invalid_message_callback, + NULL);*/ + msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE, + invalid_message_callback, + NULL); + + if (gSavedSettings.getBOOL("LogMessages")) + { + LL_DEBUGS("AppInit") << "Message logging activated!" << LL_ENDL; + msg->startLogging(); + } + + // start the xfer system. by default, choke the downloads + // a lot... + const S32 VIEWER_MAX_XFER = 3; + start_xfer_manager(); + gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER); + F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle"); + if (xfer_throttle_bps > 1.f) + { + gXferManager->setUseAckThrottling(true); + gXferManager->setAckThrottleBPS(xfer_throttle_bps); + } + gAssetStorage = new LLViewerAssetStorage(msg, gXferManager); + + + F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage"); + msg->mPacketRing.setDropPercentage(dropPercent); + + F32 inBandwidth = gSavedSettings.getF32("InBandwidth"); + F32 outBandwidth = gSavedSettings.getF32("OutBandwidth"); + if (inBandwidth != 0.f) + { + LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL; + msg->mPacketRing.setUseInThrottle(true); + msg->mPacketRing.setInBandwidth(inBandwidth); + } + if (outBandwidth != 0.f) + { + LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL; + msg->mPacketRing.setUseOutThrottle(true); + msg->mPacketRing.setOutBandwidth(outBandwidth); + } + } + + LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; + + //------------------------------------------------- + // Init audio, which may be needed for prefs dialog + // or audio cues in connection UI. + //------------------------------------------------- + + if (false == gSavedSettings.getBOOL("NoAudio")) + { + delete gAudiop; + gAudiop = NULL; + +#ifdef LL_OPENAL +#if !LL_WINDOWS + if (NULL == getenv("LL_BAD_OPENAL_DRIVER")) +#endif // !LL_WINDOWS + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); + } +#endif + + if (gAudiop) + { +#if LL_WINDOWS + // FMOD Ex on Windows needs the window handle to stop playing audio + // when window is minimized. JC + void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); +#else + void* window_handle = NULL; +#endif + if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle())) + { + LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); + + gAudiop->setMuted(true); + } + else + { + LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; + delete gAudiop; + gAudiop = NULL; + } + } + } + + LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; + + if (LLTimer::knownBadTimer()) + { + LL_WARNS("AppInit") << "Unreliable timers detected (may be bad PCI chipset)!!" << LL_ENDL; + } + + // + // Log on to system + // + if (gUserCredential.isNull()) + { + gUserCredential = gLoginHandler.initializeLoginInfo(); + } + // Previous initializeLoginInfo may have generated user credentials. Re-check them. + if (gUserCredential.isNull()) + { + show_connect_box = true; + } + else if (gSavedSettings.getBOOL("AutoLogin")) + { + // Log into last account + gRememberPassword = true; + gRememberUser = true; + gSavedSettings.setBOOL("RememberPassword", true); + gSavedSettings.setBOOL("RememberUser", true); + show_connect_box = false; + } + else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3) + { + // Console provided login&password + gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); + gRememberUser = gSavedSettings.getBOOL("RememberUser"); + show_connect_box = false; + } + else + { + gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); + gRememberUser = gSavedSettings.getBOOL("RememberUser"); + show_connect_box = true; + } + + //setup map of datetime strings to codes and slt & local time offset from utc + // *TODO: Does this need to be here? + LLStringOps::setupDatetimeInfo(false); + + // Go to the next startup state + LLStartUp::setStartupState( STATE_BROWSER_INIT ); + return false; + } + + + if (STATE_BROWSER_INIT == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingBrowser"); + set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); + display_startup(); + // LLViewerMedia::initBrowser(); + LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + return false; + } + + + if (STATE_LOGIN_SHOW == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "Initializing Window, show_connect_box = " + << show_connect_box << LL_ENDL; + + // if we've gone backwards in the login state machine, to this state where we show the UI + // AND the debug setting to exit in this case is true, then go ahead and bail quickly + if ( mLoginStatePastUI && gSavedSettings.getBOOL("QuitOnLoginActivated") ) + { + LL_DEBUGS("AppInit") << "taking QuitOnLoginActivated exit" << LL_ENDL; + // no requirement for notification here - just exit + LLAppViewer::instance()->earlyExitNoNotify(); + } + + gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + + // Login screen needs menus for preferences, but we can enter + // this startup phase more than once. + if (gLoginMenuBarView == NULL) + { + LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL; + initialize_spellcheck_menu(); + init_menus(); + } + show_release_notes_if_required(); + + if (show_connect_box) + { + LL_DEBUGS("AppInit") << "show_connect_box on" << LL_ENDL; + // Load all the name information out of the login view + // NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't + // show the login view until login_show() is called below. + if (gUserCredential.isNull()) + { + LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL; + gUserCredential = gLoginHandler.initializeLoginInfo(); + } + // Make sure the process dialog doesn't hide things + gViewerWindow->setShowProgress(false); + // Show the login dialog + login_show(); + // connect dialog is already shown, so fill in the names + LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword); + LLPanelLogin::giveFocus(); + + // MAINT-3231 Show first run dialog only for Desura viewer + if (gSavedSettings.getString("sourceid") == "1208_desura") + { + if (gSavedSettings.getBOOL("FirstLoginThisInstall")) + { + LL_INFOS("AppInit") << "FirstLoginThisInstall, calling show_first_run_dialog()" << LL_ENDL; + show_first_run_dialog(); + } + else + { + LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; + } + } + display_startup(); + LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input + } + else + { + LL_DEBUGS("AppInit") << "show_connect_box off, skipping to STATE_LOGIN_CLEANUP" << LL_ENDL; + // skip directly to message template verification + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + } + + gViewerWindow->setNormalControlsVisible( false ); + gLoginMenuBarView->setVisible( true ); + gLoginMenuBarView->setEnabled( true ); + show_debug_menus(); + + // Hide the splash screen + LL_DEBUGS("AppInit") << "Hide the splash screen and show window" << LL_ENDL; + LLSplashScreen::hide(); + // Push our window frontmost + gViewerWindow->getWindow()->show(); + + // DEV-16927. The following code removes errant keystrokes that happen while the window is being + // first made visible. +#ifdef _WIN32 + LL_DEBUGS("AppInit") << "Processing PeekMessage" << LL_ENDL; + MSG msg; + while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ) + { + } + LL_DEBUGS("AppInit") << "PeekMessage processed" << LL_ENDL; +#endif + display_startup(); + timeout.reset(); + return false; + } + + if (STATE_LOGIN_WAIT == LLStartUp::getStartupState()) + { + // when we get to this state, we've already been past the login UI + // (possiblely automatically) - flag this so we can test in the + // STATE_LOGIN_SHOW state if we've gone backwards + mLoginStatePastUI = true; + + // Don't do anything. Wait for the login view to call the login_callback, + // which will push us to the next state. + + // display() function will be the one to run display_startup() + // Sleep so we don't spin the CPU + ms_sleep(1); + return false; + } + + if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) + { + // Post login screen, we should see if any settings have changed that may + // require us to either start/stop or change the socks proxy. As various communications + // past this point may require the proxy to be up. + if (!LLStartUp::startLLProxy()) + { + // Proxy start up failed, we should now bail the state machine + // startLLProxy() will have reported an error to the user + // already, so we just go back to the login screen. The user + // could then change the preferences to fix the issue. + + LLStartUp::setStartupState(STATE_LOGIN_SHOW); + return false; + } + + // reset the values that could have come in from a slurl + // DEV-42215: Make sure they're not empty -- gUserCredential + // might already have been set from gSavedSettings, and it's too bad + // to overwrite valid values with empty strings. + + if (show_connect_box) + { + // TODO if not use viewer auth + // Load all the name information out of the login view + LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword); + // end TODO + + // HACK: Try to make not jump on login + gKeyboard->resetKeys(); + } + + // when we get to this state, we've already been past the login UI + // (possiblely automatically) - flag this so we can test in the + // STATE_LOGIN_SHOW state if we've gone backwards + mLoginStatePastUI = true; + + // save the credentials + std::string userid = "unknown"; + if (gUserCredential.notNull()) + { + userid = gUserCredential->userID(); + if (gRememberUser) + { + gSecAPIHandler->addToCredentialMap("login_list", gUserCredential, gRememberPassword); + // Legacy viewers use this method to store user credentials, newer viewers + // reuse it to be compatible and to remember last session + gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword); + } + } + gSavedSettings.setBOOL("RememberPassword", gRememberPassword); + gSavedSettings.setBOOL("RememberUser", gRememberUser); + LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL; + gDebugInfo["LoginName"] = userid; + + // create necessary directories + // *FIX: these mkdir's should error check + gDirUtilp->setLindenUserDir(userid); + LLFile::mkdir(gDirUtilp->getLindenUserDir()); + + // As soon as directories are ready initialize notification storages + if (!LLPersistentNotificationStorage::instanceExists()) + { + // check existance since this part of code can be reached + // twice due to login failures + LLPersistentNotificationStorage::initParamSingleton(); + LLDoNotDisturbNotificationStorage::initParamSingleton(); + } + else + { + // reinitialize paths in case user switched grids or accounts + LLPersistentNotificationStorage::getInstance()->reset(); + LLDoNotDisturbNotificationStorage::getInstance()->reset(); + } + + // Set PerAccountSettingsFile to the default value. + std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")); + gSavedSettings.setString("PerAccountSettingsFile", settings_per_account); + gDebugInfo["PerAccountSettingsFilename"] = settings_per_account; + + // Note: can't store warnings files per account because some come up before login + + // Overwrite default user settings with user settings + LLAppViewer::instance()->loadSettingsFromDirectory("Account"); + + // Convert 'LogInstantMessages' into 'KeepConversationLogTranscripts' for backward compatibility (CHUI-743). + LLControlVariablePtr logInstantMessagesControl = gSavedPerAccountSettings.getControl("LogInstantMessages"); + if (logInstantMessagesControl.notNull()) + { + gSavedPerAccountSettings.setS32("KeepConversationLogTranscripts", logInstantMessagesControl->getValue() ? 2 : 1); + } + + // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation + // and startup time is close enough if we don't have a real value. + if (gSavedPerAccountSettings.getU32("LastLogoff") == 0) + { + gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); + } + + //Default the path if one isn't set. + // *NOTE: unable to check variable differ from "InstantMessageLogPath" because it was + // provided in pre 2.0 viewer. See EXT-6661 + if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty()) + { + gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir()); + gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir()); + } + else + { + gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + } + gDirUtilp->setPerAccountChatLogsDir(userid); + + LLFile::mkdir(gDirUtilp->getChatLogsDir()); + LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); + + if (show_connect_box) + { + LLSLURL slurl; + //LLPanelLogin::closePanel(); + } + + + // Load URL History File + LLURLHistory::loadFile("url_history.xml"); + // Load location history + LLLocationHistory::getInstance()->load(); + + // Load Avatars icons cache + LLAvatarIconIDCache::getInstance()->load(); + + LLRenderMuteList::getInstance()->loadFromFile(); + + //------------------------------------------------- + // Handle startup progress screen + //------------------------------------------------- + + // on startup the user can request to go to their home, + // their last location, or some URL "-url //sim/x/y[/z]" + // All accounts have both a home and a last location, and we don't support + // more locations than that. Choose the appropriate one. JC + switch (LLStartUp::getStartSLURL().getType()) + { + case LLSLURL::LOCATION: + agent_location_id = START_LOCATION_ID_URL; + break; + case LLSLURL::LAST_LOCATION: + agent_location_id = START_LOCATION_ID_LAST; + break; + default: + agent_location_id = START_LOCATION_ID_HOME; + break; + } + + gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); + + // Display the startup progress bar. + gViewerWindow->initTextures(agent_location_id); + gViewerWindow->setShowProgress(true); + gViewerWindow->setProgressCancelButtonVisible(true, LLTrans::getString("Quit")); + + gViewerWindow->revealIntroPanel(); + + LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); + + return false; + } + + if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState()) + { + gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId(); + + // Update progress status and the display loop. + auth_desc = LLTrans::getString("LoginInProgress"); + set_startup_status(progress, auth_desc, auth_message); + progress += 0.02f; + display_startup(); + + // Setting initial values... + LLLoginInstance* login = LLLoginInstance::getInstance(); + login->setNotificationsInterface(LLNotifications::getInstance()); + + login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); + login->setLastExecEvent(gLastExecEvent); + login->setLastExecDuration(gLastExecDuration); + + // This call to LLLoginInstance::connect() starts the + // authentication process. + login->connect(gUserCredential); + + LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK ); + return false; + } + + if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState()) + { + // If we get here we have gotten past the potential stall + // in curl, so take "may appear frozen" out of progress bar. JC + auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); + set_startup_status(progress, auth_desc, auth_message); + + LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); + return false; + } + + if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) + { + // Generic failure message + std::ostringstream emsg; + emsg << LLTrans::getString("LoginFailedHeader") << "\n"; + if(LLLoginInstance::getInstance()->authFailure()) + { + LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): " + << LLLoginInstance::getInstance()->getResponse() << LL_ENDL; + LLSD response = LLLoginInstance::getInstance()->getResponse(); + // Still have error conditions that may need some + // sort of handling - dig up specific message + std::string reason_response = response["reason"]; + std::string message_response = response["message"]; + std::string message_id = response["message_id"]; + std::string message; // actual string to show the user + + bool localized_by_id = false; + if(!message_id.empty()) + { + LLSD message_args = response["message_args"]; + if (message_args.has("TIME") + && (message_id == "LoginFailedAcountSuspended" + || message_id == "LoginFailedAccountMaintenance")) + { + LLDate date; + std::string time_string; + if (date.fromString(message_args["TIME"].asString())) + { + LLSD args; + args["datetime"] = (S32)date.secondsSinceEpoch(); + LLTrans::findString(time_string, "LocalTime", args); + } + else + { + time_string = message_args["TIME"].asString() + " " + LLTrans::getString("PacificTime"); + } + + message_args["TIME"] = time_string; + } + // message will be filled in with the template and arguments + if (LLTrans::findString(message, message_id, message_args)) + { + localized_by_id = true; + } + } + + if(!localized_by_id && !message_response.empty()) + { + // *HACK: "no_inventory_host" sent as the message itself. + // Remove this clause when server is sending message_id as well. + message = LLAgent::sTeleportErrorMessages[ message_response ]; + } + + if (message.empty()) + { + // Fallback to server-supplied string; necessary since server + // may add strings that this viewer is not yet aware of + message = message_response; + } + + emsg << message; + + + if(reason_response == "key") + { + // Couldn't login because user/password is wrong + // Clear the credential + gUserCredential->clearAuthenticator(); + } + + if(reason_response == "update" + || reason_response == "optional") + { + // In the case of a needed update, quit. + // Its either downloading or declined. + // If optional was skipped this case shouldn't + // be reached. + + LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL; + LLLoginInstance::getInstance()->disconnect(); + LLAppViewer::instance()->forceQuit(); + } + else + { + if (reason_response != "tos" && reason_response != "mfa_challenge") + { + // Don't pop up a notification in the TOS or MFA cases because + // the specialized floater has already scolded the user. + std::string error_code; + if(response.has("errorcode")) + { + error_code = response["errorcode"].asString(); + } + if ((reason_response == "CURLError") && + (error_code == "SSL_CACERT" || error_code == "SSL_PEER_CERTIFICATE") && + response.has("certificate")) + { + // This was a certificate error, so grab the certificate + // and throw up the appropriate dialog. + LLPointer certificate; + try + { + certificate = gSecAPIHandler->getCertificate(response["certificate"]); + } + catch (LLCertException &cert_exception) + { + LL_WARNS("LLStartup", "SECAPI") << "Caught " << cert_exception.what() << " certificate expception on getCertificate("<< response["certificate"] << ")" << LL_ENDL; + LLSD args; + args["REASON"] = LLTrans::getString(cert_exception.what()); + + LLNotificationsUtil::add("GeneralCertificateErrorShort", args, response, + general_cert_done); + + reset_login(); + gSavedSettings.setBOOL("AutoLogin", false); + show_connect_box = true; + } + if(certificate) + { + LLSD args = transform_cert_args(certificate); + + if(error_code == "SSL_CACERT") + { + // if we are handling an untrusted CA, throw up the dialog + // with the 'trust this CA' button. + LLNotificationsUtil::add("TrustCertificateError", args, response, + trust_cert_done); + + show_connect_box = true; + } + else + { + // the certificate exception returns a unique string for each type of exception. + // we grab this string via the LLUserAuth object, and use that to grab the localized + // string. + args["REASON"] = LLTrans::getString(message_response); + + LLNotificationsUtil::add("GeneralCertificateError", args, response, + general_cert_done); + + reset_login(); + gSavedSettings.setBOOL("AutoLogin", false); + show_connect_box = true; + + } + + } + } + else if (reason_response == "BadType") + { + LLNotificationsUtil::add("LoginFailedToParse", LLSD(), LLSD(), login_alert_done); + } + else if (!message.empty()) + { + // This wasn't a certificate error, so throw up the normal + // notificatioin message. + LLSD args; + args["ERROR_MESSAGE"] = emsg.str(); + LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); + } + } + transition_back_to_login_panel(emsg.str()); + show_connect_box = true; + } + } + else if(LLLoginInstance::getInstance()->authSuccess()) + { + if(process_login_success_response()) + { + // Pass the user information to the voice chat server interface. + LLVoiceClient::getInstance()->userAuthorized(gUserCredential->userID(), gAgentID); + // create the default proximal channel + LLVoiceChannel::initClass(); + LLStartUp::setStartupState( STATE_WORLD_INIT); + LLTrace::get_frame_recording().reset(); + } + else + { + LLSD args; + args["ERROR_MESSAGE"] = emsg.str(); + LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); + transition_back_to_login_panel(emsg.str()); + show_connect_box = true; + return false; + } + } + return false; + } + + //--------------------------------------------------------------------- + // World Init + //--------------------------------------------------------------------- + if (STATE_WORLD_INIT == LLStartUp::getStartupState()) + { + set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); + display_startup(); + // We should have an agent id by this point. + llassert(!(gAgentID == LLUUID::null)); + + // Finish agent initialization. (Requires gSavedSettings, builds camera) + gAgent.init(); + display_startup(); + gAgentCamera.init(); + display_startup(); + display_startup(); + + // Since we connected, save off the settings so the user doesn't have to + // type the name/password again if we crash. + gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), true); + LLUIColorTable::instance().saveUserSettings(); + + display_startup(); + + // + // Initialize classes w/graphics stuff. + // + LLViewerStatsRecorder::instance(); // Since textures work in threads + LLSurface::initClasses(); + display_startup(); + + display_startup(); + + LLDrawable::initClass(); + display_startup(); + + // init the shader managers + LLPostProcess::initClass(); + display_startup(); + + LLAvatarAppearance::initClass("avatar_lad.xml","avatar_skeleton.xml"); + display_startup(); + + LLViewerObject::initVOClasses(); + display_startup(); + + // Initialize all our tools. Must be done after saved settings loaded. + // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton. + LLToolMgr::getInstance()->initTools(); + display_startup(); + + // Pre-load floaters, like the world map, that are slow to spawn + // due to XML complexity. + gViewerWindow->initWorldUI(); + + display_startup(); + + // This is where we used to initialize gWorldp. Original comment said: + // World initialization must be done after above window init + + // User might have overridden far clip + LLWorld::getInstance()->setLandFarClip(gAgentCamera.mDrawDistance); + display_startup(); + // Before we create the first region, we need to set the agent's mOriginGlobal + // This is necessary because creating objects before this is set will result in a + // bad mPositionAgent cache. + + gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); + display_startup(); + + LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); + display_startup(); + + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); + LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; + + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == " + << gFirstSimSeedCap << LL_ENDL; + regionp->setSeedCapability(gFirstSimSeedCap); + LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; + display_startup(); + // Set agent's initial region to be the one we just created. + gAgent.setRegion(regionp); + display_startup(); + // Set agent's initial position, which will be read by LLVOAvatar when the avatar + // object is created. I think this must be done after setting the region. JC + gAgent.setPositionAgent(agent_start_position_region); + + display_startup(); + LLStartUp::initExperiences(); + + display_startup(); + + // If logging should be enebled, turns it on and loads history from disk + // Note: does not happen on init of singleton because preferences can use + // this instance without logging in + LLConversationLog::getInstance()->initLoggingState(); + + LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); + + return false; + } + + + //--------------------------------------------------------------------- + // Load QuickTime/GStreamer and other multimedia engines, can be slow. + // Do it while we're waiting on the network for our seed capability. JC + //--------------------------------------------------------------------- + if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState()) + { + LLStartUp::multimediaInit(); + LLStartUp::setStartupState( STATE_FONT_INIT ); + display_startup(); + return false; + } + + // Loading fonts takes several seconds + if (STATE_FONT_INIT == LLStartUp::getStartupState()) + { + LLStartUp::fontInit(); + LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT ); + display_startup(); + return false; + } + + //--------------------------------------------------------------------- + // Wait for Seed Cap Grant + //--------------------------------------------------------------------- + if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); + if (regionp->capabilitiesReceived()) + { + LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); + } + else if (regionp->capabilitiesError()) + { + LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + else + { + U32 num_retries = regionp->getNumSeedCapRetries(); + if (num_retries > MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT) + { + LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + else if (num_retries > 0) + { + LLStringUtil::format_map_t args; + args["[NUMBER]"] = llformat("%d", num_retries + 1); + set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD.c_str()); + } + else + { + set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str()); + } + } + display_startup(); + return false; + } + + + //--------------------------------------------------------------------- + // Seed Capability Granted + // no newMessage calls should happen before this point + //--------------------------------------------------------------------- + if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState()) + { + display_startup(); + + // These textures are not warrantied to be cached, so needs + // to hapen with caps granted + gTextureList.doPrefetchImages(); + + // will init images, should be done with caps, but before gSky.init() + LLEnvironment::getInstance()->initSingleton(); + + display_startup(); + update_texture_fetch(); + display_startup(); + + if ( gViewerWindow != NULL) + { // This isn't the first logon attempt, so show the UI + gViewerWindow->setNormalControlsVisible( true ); + } + gLoginMenuBarView->setVisible( false ); + gLoginMenuBarView->setEnabled( false ); + display_startup(); + + // direct logging to the debug console's line buffer + LLError::logToFixedBuffer(gDebugView->mDebugConsolep); + display_startup(); + + // set initial visibility of debug console + gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); + display_startup(); + + // + // Set message handlers + // + LL_INFOS("AppInit") << "Initializing communications..." << LL_ENDL; + + // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted + register_viewer_callbacks(gMessageSystem); + display_startup(); + + // Debugging info parameters + gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms + display_startup(); + + #ifndef LL_RELEASE_FOR_DOWNLOAD + gMessageSystem->setTimeDecodes( true ); // Time the decode of each msg + gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode + #endif + display_startup(); + + gXferManager->registerCallbacks(gMessageSystem); + display_startup(); + + LLStartUp::initNameCache(); + display_startup(); + + // update the voice settings *after* gCacheName initialization + // so that we can construct voice UI that relies on the name cache + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->updateSettings(); + } + display_startup(); + + // create a container's instance for start a controlling conversation windows + // by the voice's events + LLFloaterIMContainer::getInstance(); + if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2) + { + LLViewerParcelAskPlay::getInstance()->loadSettings(); + } + + gAgent.addRegionChangedCallback(boost::bind(&LLPerfStats::StatsRecorder::clearStats)); + + // *Note: this is where gWorldMap used to be initialized. + + // register null callbacks for audio until the audio system is initialized + gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL); + gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL); + display_startup(); + + //reset statistics + LLViewerStats::instance().resetStats(); + + display_startup(); + // + // Set up region and surface defaults + // + + + // Sets up the parameters for the first simulator + + LL_DEBUGS("AppInit") << "Initializing camera..." << LL_ENDL; + gFrameTime = totalTime(); + F32Seconds last_time = gFrameTimeSeconds; + gFrameTimeSeconds = (gFrameTime - gStartTime); + + gFrameIntervalSeconds = gFrameTimeSeconds - last_time; + if (gFrameIntervalSeconds < 0.f) + { + gFrameIntervalSeconds = 0.f; + } + + // Make sure agent knows correct aspect ratio + // FOV limits depend upon aspect ratio so this needs to happen before initializing the FOV below + LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWorldViewHeightRaw()); + LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio()); + // Initialize FOV + LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle")); + display_startup(); + + // Move agent to starting location. The position handed to us by + // the space server is in global coordinates, but the agent frame + // is in region local coordinates. Therefore, we need to adjust + // the coordinates handed to us to fit in the local region. + + gAgent.setPositionAgent(agent_start_position_region); + gAgent.resetAxes(gAgentStartLookAt); + gAgentCamera.stopCameraAnimation(); + gAgentCamera.resetCamera(); + display_startup(); + + // Initialize global class data needed for surfaces (i.e. textures) + LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; + // Initialize all of the viewer object classes for the first time (doing things like texture fetches. + LLGLState::checkStates(); + + gSky.init(); + + LLGLState::checkStates(); + + display_startup(); + + LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL; + // For all images pre-loaded into viewer cache, init + // priorities and fetching using decodeAllImages. + // Most of the fetching and decoding likely to be done + // by update_texture_fetch() later, while viewer waits. + // + // Need to do this AFTER we init the sky + const S32 DECODE_TIME_SEC = 2; + for (int i = 0; i < DECODE_TIME_SEC; i++) + { + F32 frac = (F32)i / (F32)DECODE_TIME_SEC; + set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD); + display_startup(); + gTextureList.decodeAllImages(1.f); + } + LLStartUp::setStartupState( STATE_WORLD_WAIT ); + + display_startup(); + + // JC - Do this as late as possible to increase likelihood Purify + // will run. + LLMessageSystem* msg = gMessageSystem; + if (!msg->mOurCircuitCode) + { + LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL; + } + + gUseCircuitCallbackCalled = false; + + msg->enableCircuit(gFirstSim, true); + // now, use the circuit info to tell simulator about us! + LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL; + msg->newMessageFast(_PREHASH_UseCircuitCode); + msg->nextBlockFast(_PREHASH_CircuitCode); + msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); + msg->sendReliable( + gFirstSim, + gSavedSettings.getS32("UseCircuitCodeMaxRetries"), + false, + (F32Seconds)gSavedSettings.getF32("UseCircuitCodeTimeout"), + use_circuit_callback, + NULL); + + timeout.reset(); + display_startup(); + + return false; + } + + //--------------------------------------------------------------------- + // World Wait + //--------------------------------------------------------------------- + if(STATE_WORLD_WAIT == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "Waiting for simulator ack...." << LL_ENDL; + set_startup_status(0.59f, LLTrans::getString("LoginWaitingForRegionHandshake"), gAgent.mMOTD); + if(gGotUseCircuitCodeAck) + { + LLStartUp::setStartupState( STATE_AGENT_SEND ); + } + pump_idle_startup_network(); + return false; + } + + //--------------------------------------------------------------------- + // Agent Send + //--------------------------------------------------------------------- + if (STATE_AGENT_SEND == LLStartUp::getStartupState()) + { + LL_DEBUGS("AppInit") << "Connecting to region..." << LL_ENDL; + set_startup_status(0.60f, LLTrans::getString("LoginConnectingToRegion"), gAgent.mMOTD); + display_startup(); + // register with the message system so it knows we're + // expecting this message + LLMessageSystem* msg = gMessageSystem; + msg->setHandlerFuncFast( + _PREHASH_AgentMovementComplete, + process_agent_movement_complete); + LLViewerRegion* regionp = gAgent.getRegion(); + if(regionp) + { + send_complete_agent_movement(regionp->getHost()); + gAssetStorage->setUpstream(regionp->getHost()); + gCacheName->setUpstream(regionp->getHost()); + } + display_startup(); + + // Create login effect + // But not on first login, because you can't see your avatar then + if (!gAgent.isFirstLogin()) + { + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, true); + effectp->setPositionGlobal(gAgent.getPositionGlobal()); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + LLHUDManager::getInstance()->sendEffects(); + } + + LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT + + timeout.reset(); + display_startup(); + return false; + } + + //--------------------------------------------------------------------- + // Agent Wait + //--------------------------------------------------------------------- + if (STATE_AGENT_WAIT == LLStartUp::getStartupState()) + { + { + LockMessageChecker lmc(gMessageSystem); + while (lmc.checkAllMessages(gFrameCount, gServicePump)) + { + if (gAgentMovementCompleted) + { + // Sometimes we have more than one message in the + // queue. break out of this loop and continue + // processing. If we don't, then this could skip one + // or more login steps. + break; + } + else + { + LL_DEBUGS("AppInit") << "Awaiting AvatarInitComplete, got " + << gMessageSystem->getMessageName() << LL_ENDL; + } + display_startup(); + } + lmc.processAcks(); + } + + display_startup(); + + if (gAgentMovementCompleted) + { + LLStartUp::setStartupState( STATE_INVENTORY_SEND ); + } + display_startup(); + + if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) + { + LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + return false; + } + + //--------------------------------------------------------------------- + // Inventory Send + //--------------------------------------------------------------------- + if (STATE_INVENTORY_SEND == LLStartUp::getStartupState()) + { + LL_PROFILE_ZONE_NAMED("State inventory send") + display_startup(); + + // request mute list + LL_INFOS() << "Requesting Mute List" << LL_ENDL; + LLMuteList::getInstance()->requestFromServer(gAgent.getID()); + + // Get L$ and ownership credit information + LL_INFOS() << "Requesting Money Balance" << LL_ENDL; + LLStatusBar::sendMoneyBalanceRequest(); + + display_startup(); + + // Inform simulator of our language preference + LLAgentLanguage::update(); + + display_startup(); + // unpack thin inventory + LLSD response = LLLoginInstance::getInstance()->getResponse(); + //bool dump_buffer = false; + + LLSD inv_lib_root = response["inventory-lib-root"]; + if(inv_lib_root.isDefined()) + { + // should only be one + LLSD id = inv_lib_root[0]["folder_id"]; + if(id.isDefined()) + { + gInventory.setLibraryRootFolderID(id.asUUID()); + } + } + display_startup(); + + LLSD inv_lib_owner = response["inventory-lib-owner"]; + if(inv_lib_owner.isDefined()) + { + // should only be one + LLSD id = inv_lib_owner[0]["agent_id"]; + if(id.isDefined()) + { + gInventory.setLibraryOwnerID(LLUUID(id.asUUID())); + } + } + display_startup(); + LLStartUp::setStartupState(STATE_INVENTORY_SKEL); + display_startup(); + return false; + } + + if (STATE_INVENTORY_SKEL == LLStartUp::getStartupState()) + { + LL_PROFILE_ZONE_NAMED("State inventory load skeleton") + + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + LLSD inv_skel_lib = response["inventory-skel-lib"]; + if (inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull()) + { + LL_PROFILE_ZONE_NAMED("load library inv") + if (!gInventory.loadSkeleton(inv_skel_lib, gInventory.getLibraryOwnerID())) + { + LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; + } + } + display_startup(); + + LLSD inv_skeleton = response["inventory-skeleton"]; + if (inv_skeleton.isDefined()) + { + LL_PROFILE_ZONE_NAMED("load personal inv") + if (!gInventory.loadSkeleton(inv_skeleton, gAgent.getID())) + { + LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL; + } + } + display_startup(); + LLStartUp::setStartupState(STATE_INVENTORY_SEND2); + display_startup(); + return false; + } + + if (STATE_INVENTORY_SEND2 == LLStartUp::getStartupState()) + { + LL_PROFILE_ZONE_NAMED("State inventory send2") + + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + LLSD inv_basic = response["inventory-basic"]; + if(inv_basic.isDefined()) + { + LL_INFOS() << "Basic inventory root folder id is " << inv_basic["folder_id"] << LL_ENDL; + } + + LLSD buddy_list = response["buddy-list"]; + if(buddy_list.isDefined()) + { + LLAvatarTracker::buddy_map_t list; + LLUUID agent_id; + S32 has_rights = 0, given_rights = 0; + for(LLSD::array_const_iterator it = buddy_list.beginArray(), + end = buddy_list.endArray(); it != end; ++it) + { + LLSD buddy_id = (*it)["buddy_id"]; + if(buddy_id.isDefined()) + { + agent_id = buddy_id.asUUID(); + } + + LLSD buddy_rights_has = (*it)["buddy_rights_has"]; + if(buddy_rights_has.isDefined()) + { + has_rights = buddy_rights_has.asInteger(); + } + + LLSD buddy_rights_given = (*it)["buddy_rights_given"]; + if(buddy_rights_given.isDefined()) + { + given_rights = buddy_rights_given.asInteger(); + } + + list[agent_id] = new LLRelationship(given_rights, has_rights, false); + } + LLAvatarTracker::instance().addBuddyList(list); + display_startup(); + } + + bool show_hud = false; + LLSD tutorial_setting = response["tutorial_setting"]; + if(tutorial_setting.isDefined()) + { + for(LLSD::array_const_iterator it = tutorial_setting.beginArray(), + end = tutorial_setting.endArray(); it != end; ++it) + { + LLSD tutorial_url = (*it)["tutorial_url"]; + if(tutorial_url.isDefined()) + { + // Tutorial floater will append language code + gSavedSettings.setString("TutorialURL", tutorial_url.asString()); + } + + // For Viewer 2.0 we are not using the web-based tutorial + // If we reverse that decision, put this code back and use + // login.cgi to send a different URL with content that matches + // the Viewer 2.0 UI. + //LLSD use_tutorial = (*it)["use_tutorial"]; + //if(use_tutorial.asString() == "true") + //{ + // show_hud = true; + //} + } + } + display_startup(); + + // Either we want to show tutorial because this is the first login + // to a Linden Help Island or the user quit with the tutorial + // visible. JC + if (show_hud || gSavedSettings.getBOOL("ShowTutorial")) + { + LLFloaterReg::showInstance("hud", LLSD(), false); + } + display_startup(); + + LLSD event_notifications = response["event_notifications"]; + if(event_notifications.isDefined()) + { + gEventNotifier.load(event_notifications); + } + display_startup(); + + LLSD classified_categories = response["classified_categories"]; + if(classified_categories.isDefined()) + { + LLClassifiedInfo::loadCategories(classified_categories); + } + display_startup(); + + // This method MUST be called before gInventory.findCategoryUUIDForType because of + // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap. + gInventory.buildParentChildMap(); + + // If buildParentChildMap succeeded, inventory will now be in + // a usable state and gInventory.isInventoryUsable() will be + // true. + + // if inventory is unusable, show warning. + if (!gInventory.isInventoryUsable()) + { + LLNotificationsUtil::add("InventoryUnusable"); + } + + LLInventoryModelBackgroundFetch::instance().start(); + gInventory.createCommonSystemCategories(); + LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS ); + display_startup(); + + return false; + } + + //--------------------------------------------------------------------- + // STATE_INVENTORY_CALLBACKS + //--------------------------------------------------------------------- + if (STATE_INVENTORY_CALLBACKS == LLStartUp::getStartupState()) + { + if (!LLInventoryModel::isSysFoldersReady()) + { + display_startup(); + return false; + } + + LLInventoryModelBackgroundFetch::instance().start(); + LLAppearanceMgr::instance().initCOFID(); + LLUUID cof_id = LLAppearanceMgr::instance().getCOF(); + LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); + if (cof + && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // Special case, dupplicate request prevention. + // Cof folder will be requested via FetchCOF + // in appearance manager, prevent recursive fetch + cof->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + } + + + // It's debatable whether this flag is a good idea - sets all + // bits, and in general it isn't true that inventory + // initialization generates all types of changes. Maybe add an + // INITIALIZE mask bit instead? + gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); + gInventory.notifyObservers(); + + display_startup(); + + // set up callbacks + LL_INFOS() << "Registering Callbacks" << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + LL_INFOS() << " Inventory" << LL_ENDL; + LLInventoryModel::registerCallbacks(msg); + LL_INFOS() << " AvatarTracker" << LL_ENDL; + LLAvatarTracker::instance().registerCallbacks(msg); + LL_INFOS() << " Landmark" << LL_ENDL; + LLLandmark::registerCallbacks(msg); + display_startup(); + + // request all group information + LL_INFOS() << "Requesting Agent Data" << LL_ENDL; + gAgent.sendAgentDataUpdateRequest(); + display_startup(); + // Create the inventory views + LL_INFOS() << "Creating Inventory Views" << LL_ENDL; + LLFloaterReg::getInstance("inventory"); + display_startup(); + LLStartUp::setStartupState( STATE_MISC ); + display_startup(); + + return false; + } + + + //--------------------------------------------------------------------- + // Misc + //--------------------------------------------------------------------- + if (STATE_MISC == LLStartUp::getStartupState()) + { + // We have a region, and just did a big inventory download. + // We can estimate the user's connection speed, and set their + // max bandwidth accordingly. JC + if (gSavedSettings.getBOOL("FirstLoginThisInstall")) + { + // This is actually a pessimistic computation, because TCP may not have enough + // time to ramp up on the (small) default inventory file to truly measure max + // bandwidth. JC + F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS(); + const F32 FAST_RATE_BPS = 600.f * 1024.f; + const F32 FASTER_RATE_BPS = 750.f * 1024.f; + F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); + if (rate_bps > FASTER_RATE_BPS + && rate_bps > max_bandwidth) + { + LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " + << FASTER_RATE_BPS/1024.f + << " kbps" << LL_ENDL; + gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f); + } + else if (rate_bps > FAST_RATE_BPS + && rate_bps > max_bandwidth) + { + LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to " + << FAST_RATE_BPS/1024.f + << " kbps" << LL_ENDL; + gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f); + } + + if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin")) + { + gSavedSettings.setBOOL("HelpFloaterOpen", true); + } + + // Set the show start location to true, now that the user has logged + // on with this install. + gSavedSettings.setBOOL("ShowStartLocation", true); + } + + display_startup(); + + // Load stored local environment if needed. + LLEnvironment::instance().loadFromSettings(); + + // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp) + //check_merchant_status(); + + display_startup(); + + if (gSavedSettings.getBOOL("HelpFloaterOpen")) + { + // show default topic + LLViewerHelp::instance().showTopic(""); + } + + display_startup(); + + // We're successfully logged in. + gSavedSettings.setBOOL("FirstLoginThisInstall", false); + + LLFloaterReg::showInitialVisibleInstances(); + + LLFloaterGridStatus::getInstance()->startGridStatusTimer(); + + display_startup(); + + display_startup(); + // JC: Initializing audio requests many sounds for download. + init_audio(); + display_startup(); + + // JC: Initialize "active" gestures. This may also trigger + // many gesture downloads, if this is the user's first + // time on this machine or -purge has been run. + LLSD gesture_options + = LLLoginInstance::getInstance()->getResponse("gestures"); + if (gesture_options.isDefined()) + { + LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size() + << LL_ENDL; + uuid_vec_t item_ids; + for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(), + end = gesture_options.endArray(); resp_it != end; ++resp_it) + { + // If the id is not specifed in the LLSD, + // the LLSD operator[]() will return a null LLUUID. + LLUUID item_id = (*resp_it)["item_id"]; + LLUUID asset_id = (*resp_it)["asset_id"]; + + if (item_id.notNull() && asset_id.notNull()) + { + // Could schedule and delay these for later. + const bool no_inform_server = false; + const bool no_deactivate_similar = false; + LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id, + no_inform_server, + no_deactivate_similar); + // We need to fetch the inventory items for these gestures + // so we have the names to populate the UI. + item_ids.push_back(item_id); + } + } + // no need to add gesture to inventory observer, it's already made in constructor + LLGestureMgr::instance().setFetchIDs(item_ids); + LLGestureMgr::instance().startFetch(); + } + gDisplaySwapBuffers = true; + display_startup(); + + LLMessageSystem* msg = gMessageSystem; + msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger); + msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound); + msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound); + msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change); + + LL_DEBUGS("AppInit") << "Initialization complete" << LL_ENDL; + + LL_DEBUGS("SceneLoadTiming", "Start") << "Scene Load Started " << LL_ENDL; + gRenderStartTime.reset(); + gForegroundTime.reset(); + + // HACK: Inform simulator of window size. + // Do this here so it's less likely to race with RegisterNewAgent. + // TODO: Put this into RegisterNewAgent + // JC - 7/20/2002 + gViewerWindow->sendShapeToSim(); + + LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA); + + // The reason we show the alert is because we want to + // reduce confusion for when you log in and your provided + // location is not your expected location. So, if this is + // your first login, then you do not have an expectation, + // thus, do not show this alert. + if (!gAgent.isFirstLogin()) + { + LL_INFOS() << "gAgentStartLocation : " << gAgentStartLocation << LL_ENDL; + LLSLURL start_slurl = LLStartUp::getStartSLURL(); + LL_DEBUGS("AppInit") << "start slurl "< 1.f) && isAgentAvatarValid()) + { + LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); + } + else if (timeout_frac > 10.f) + { + // If we exceed the wait above while isAgentAvatarValid is + // not true yet, we will change startup state and + // eventually (once avatar does get created) wind up at + // the gender chooser. This should occur only in very + // unusual circumstances, so set the timeout fairly high + // to minimize mistaken hits here. + LL_WARNS() << "Wait for valid avatar state exceeded " + << timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL; + LLStartUp::setStartupState( STATE_WEARABLES_WAIT ); + } + else + { + update_texture_fetch(); + set_startup_status(0.60f + 0.30f * timeout_frac, + LLTrans::getString("LoginPrecaching"), + gAgent.mMOTD.c_str()); + display_startup(); + } + + return true; + } + + if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState()) + { + static LLFrameTimer wearables_timer; + + const F32 wearables_time = wearables_timer.getElapsedTimeF32(); + const F32 MAX_WEARABLES_TIME = 10.f; + + if (!gAgent.isOutfitChosen() && isAgentAvatarValid()) + { + // No point in waiting for clothing, we don't even know + // what outfit we want. Pop up a gender chooser dialog to + // ask and proceed to draw the world. JC + // + // *NOTE: We might hit this case even if we have an + // initial outfit, but if the load hasn't started + // already then something is wrong so fall back + // to generic outfits. JC + LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(), + callback_choose_gender); + LLStartUp::setStartupState( STATE_CLEANUP ); + } + + display_startup(); + + if (gAgent.isOutfitChosen() && (wearables_time > MAX_WEARABLES_TIME)) + { + if (gInventory.isInventoryUsable()) + { + LLNotificationsUtil::add("ClothingLoading"); + } + record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time); + LLStartUp::setStartupState( STATE_CLEANUP ); + } + else if (gAgent.isFirstLogin() + && isAgentAvatarValid() + && gAgentAvatarp->isFullyLoaded()) + { + // wait for avatar to be completely loaded + if (isAgentAvatarValid() + && gAgentAvatarp->isFullyLoaded()) + { + LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL; + LLStartUp::setStartupState( STATE_CLEANUP ); + return true; + } + } + else + { + // OK to just get the wearables + if ( gAgentWearables.areWearablesLoaded() ) + { + // We have our clothing, proceed. + LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL; + LLStartUp::setStartupState( STATE_CLEANUP ); + return true; + } + } + //fall through this frame to STATE_CLEANUP + } + + if (STATE_CLEANUP == LLStartUp::getStartupState()) + { + set_startup_status(1.0, "", ""); + display_startup(); + + if (!mBenefitsSuccessfullyInit) + { + LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2)); + } + + // Let the map know about the inventory. + LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); + if(floater_world_map) + { + floater_world_map->observeInventory(&gInventory); + floater_world_map->observeFriends(); + } + gViewerWindow->showCursor(); + gViewerWindow->getWindow()->resetBusyCount(); + gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL; + //gViewerWindow->revealIntroPanel(); + gViewerWindow->setStartupComplete(); + gViewerWindow->setProgressCancelButtonVisible(false); + display_startup(); + + // We're not away from keyboard, even though login might have taken + // a while. JC + gAgent.clearAFK(); + + // Have the agent start watching the friends list so we can update proxies + gAgent.observeFriends(); + + // Start automatic replay if the flag is set. + if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession()) + { + LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL; + gAgentPilot.startPlayback(); + } + + show_debug_menus(); // Debug menu visiblity and First Use trigger + + // If we've got a startup URL, dispatch it + //LLStartUp::dispatchURL(); + + // Retrieve information about the land data + // (just accessing this the first time will fetch it, + // then the data is cached for the viewer's lifetime) + LLProductInfoRequestManager::instance(); + + // *FIX:Mani - What do I do here? + // Need we really clear the Auth response data? + // Clean up the userauth stuff. + // LLUserAuth::getInstance()->reset(); + + LLStartUp::setStartupState( STATE_STARTED ); + display_startup(); + + // Unmute audio if desired and setup volumes. + // This is a not-uncommon crash site, so surround it with + // LL_INFOS() output to aid diagnosis. + LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL; + audio_update_volume(); + LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL; + + // reset keyboard focus to sane state of pointing at world + gFocusMgr.setKeyboardFocus(NULL); + + LLAppViewer::instance()->handleLoginComplete(); + + LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); + + display_startup(); + + llassert(LLPathfindingManager::getInstance() != NULL); + LLPathfindingManager::getInstance()->initSystem(); + + gAgentAvatarp->sendHoverHeight(); + + // look for parcels we own + send_places_query(LLUUID::null, + LLUUID::null, + "", + DFQ_AGENT_OWNED, + LLParcel::C_ANY, + ""); + + LLUIUsage::instance().clear(); + + LLPerfStats::StatsRecorder::setAutotuneInit(); + + return true; + } + + return true; +} + +// +// local function definition +// + +void login_show() +{ + LL_INFOS("AppInit") << "Initializing Login Screen" << LL_ENDL; + + // Hide the toolbars: may happen to come back here if login fails after login agent but before login in region + if (gToolBarView) + { + gToolBarView->setVisible(false); + } + + LLPanelLogin::show( gViewerWindow->getWindowRectScaled(), login_callback, NULL ); +} + +// Callback for when login screen is closed. Option 0 = connect, option 1 = quit. +void login_callback(S32 option, void *userdata) +{ + const S32 CONNECT_OPTION = 0; + const S32 QUIT_OPTION = 1; + + if (CONNECT_OPTION == option) + { + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + return; + } + else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION + { + if (!gSavedSettings.getBOOL("RememberPassword")) + { + // turn off the setting and write out to disk + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , true ); + LLUIColorTable::instance().saveUserSettings(); + } + + // Next iteration through main loop should shut down the app cleanly. + LLAppViewer::instance()->userQuit(); + + if (LLAppViewer::instance()->quitRequested()) + { + LLPanelLogin::closePanel(); + } + return; + } + else + { + LL_WARNS("AppInit") << "Unknown login button clicked" << LL_ENDL; + } +} + +void release_notes_coro(const std::string url) +{ + if (url.empty()) + { + return; + } + + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("releaseNotesCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); + + httpOpts->setHeadersOnly(true); // only making sure it isn't 404 or something like that + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + return; + } + + LLWeb::loadURLInternal(url); +} + +/** +* Check if user is running a new version of the viewer. +* Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting. +*/ +void show_release_notes_if_required() +{ + static bool release_notes_shown = false; + // We happen to know that instantiating LLVersionInfo implicitly + // instantiates the LLEventMailDrop named "relnotes", which we (might) use + // below. If viewer release notes stop working, might be because that + // LLEventMailDrop got moved out of LLVersionInfo and hasn't yet been + // instantiated. + if (!release_notes_shown && (LLVersionInfo::instance().getChannelAndVersion() != gLastRunVersion) + && LLVersionInfo::instance().getViewerMaturity() != LLVersionInfo::TEST_VIEWER // don't show Release Notes for the test builds + && gSavedSettings.getBOOL("UpdaterShowReleaseNotes") + && !gSavedSettings.getBOOL("FirstLoginThisInstall")) + { + +#if LL_RELEASE_FOR_DOWNLOAD + if (!gSavedSettings.getBOOL("CmdLineSkipUpdater") + && !LLAppViewer::instance()->isUpdaterMissing()) + { + // Instantiate a "relnotes" listener which assumes any arriving event + // is the release notes URL string. Since "relnotes" is an + // LLEventMailDrop, this listener will be invoked whether or not the + // URL has already been posted. If so, it will fire immediately; + // otherwise it will fire whenever the URL is (later) posted. Either + // way, it will display the release notes as soon as the URL becomes + // available. + LLEventPumps::instance().obtain("relnotes").listen( + "showrelnotes", + [](const LLSD& url) { + LLCoros::instance().launch("releaseNotesCoro", + boost::bind(&release_notes_coro, url.asString())); + return false; + }); + } + else +#endif // LL_RELEASE_FOR_DOWNLOAD + { + LLSD info(LLAppViewer::instance()->getViewerInfo()); + std::string url = info["VIEWER_RELEASE_NOTES_URL"].asString(); + LLCoros::instance().launch("releaseNotesCoro", + boost::bind(&release_notes_coro, url)); + } + release_notes_shown = true; + } +} + +void show_first_run_dialog() +{ + LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); +} + +bool first_run_dialog_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL; + LLWeb::loadURLExternal(LLTrans::getString("create_account_url") ); + } + + LLPanelLogin::giveFocus(); + return false; +} + + + +void set_startup_status(const F32 frac, const std::string& string, const std::string& msg) +{ + gViewerWindow->setProgressPercent(frac*100); + gViewerWindow->setProgressString(string); + + gViewerWindow->setProgressMessage(msg); +} + +bool login_alert_status(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // Buttons + switch( option ) + { + case 0: // OK + break; + // case 1: // Help + // LLWeb::loadURL(LLNotifications::instance().getGlobalString("SUPPORT_URL") ); + // break; + case 2: // Teleport + // Restart the login process, starting at our home locaton + LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + break; + default: + LL_WARNS("AppInit") << "Missing case in login_alert_status switch" << LL_ENDL; + } + + LLPanelLogin::giveFocus(); + return false; +} + + +void use_circuit_callback(void**, S32 result) +{ + // bail if we're quitting. + if(LLApp::isExiting()) return; + if( !gUseCircuitCallbackCalled ) + { + gUseCircuitCallbackCalled = true; + if (result) + { + // Make sure user knows something bad happened. JC + LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); + } + else + { + gGotUseCircuitCodeAck = true; + } + } +} + +void register_viewer_callbacks(LLMessageSystem* msg) +{ + msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data ); + msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update ); + msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update ); + msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update ); + msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved ); + msg->setHandlerFunc("SimStats", process_sim_stats); + msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message ); + msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data); + msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo); + + msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator); + msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL); + msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL); + msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator); + msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator); + msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL); + + msg->setHandlerFunc("CrossedRegion", process_crossed_region); + msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish); + + msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message); + msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message); + msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL); + msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message); + + msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value); + msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value); + msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation); + msg->setHandlerFuncFast(_PREHASH_ObjectAnimation, process_object_animation); + msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance); + msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint); + msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response); + msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties); + msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties); + + msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im); + msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question); + msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL); + msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL); + msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect); + + msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL); + msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL); + msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL); + msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL); + msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply, + &LLLiveLSLEditor::processScriptRunningReply); + + msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack); + + msg->setHandlerFunc("LogoutReply", process_logout_reply); + + //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility, + // &LLAgent::processAddModifyAbility); + //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility, + // &LLAgent::processRemoveModifyAbility); + msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate, + &LLAgent::processAgentDataUpdate); + msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate, + &LLAgent::processAgentGroupDataUpdate); + msg->setHandlerFunc("AgentDropGroup", + &LLAgent::processAgentDropGroup); + // land ownership messages + msg->setHandlerFuncFast(_PREHASH_ParcelOverlay, + LLViewerParcelMgr::processParcelOverlay); + msg->setHandlerFuncFast(_PREHASH_ParcelProperties, + LLViewerParcelMgr::processParcelProperties); + msg->setHandlerFunc("ParcelAccessListReply", + LLViewerParcelMgr::processParcelAccessListReply); + msg->setHandlerFunc("ParcelDwellReply", + LLViewerParcelMgr::processParcelDwellReply); + + msg->setHandlerFunc("AvatarPropertiesReply", + &LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply); + msg->setHandlerFunc("AvatarInterestsReply", + &LLAvatarPropertiesProcessor::processAvatarInterestsReply); + msg->setHandlerFunc("AvatarGroupsReply", + &LLAvatarPropertiesProcessor::processAvatarGroupsReply); + msg->setHandlerFunc("AvatarNotesReply", + &LLAvatarPropertiesProcessor::processAvatarNotesReply); + msg->setHandlerFunc("AvatarPicksReply", + &LLAvatarPropertiesProcessor::processAvatarPicksReply); + msg->setHandlerFunc("AvatarClassifiedReply", + &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply); + + msg->setHandlerFuncFast(_PREHASH_CreateGroupReply, + LLGroupMgr::processCreateGroupReply); + msg->setHandlerFuncFast(_PREHASH_JoinGroupReply, + LLGroupMgr::processJoinGroupReply); + msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply, + LLGroupMgr::processEjectGroupMemberReply); + msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply, + LLGroupMgr::processLeaveGroupReply); + msg->setHandlerFuncFast(_PREHASH_GroupProfileReply, + LLGroupMgr::processGroupPropertiesReply); + + // ratings deprecated + // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, + // LLFloaterRate::processReputationIndividualReply); + + msg->setHandlerFunc("ScriptControlChange", + LLAgent::processScriptControlChange ); + + msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect); + + msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers); + + msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply, + LLPanelGroupLandMoney::processGroupAccountSummaryReply); + msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply, + LLPanelGroupLandMoney::processGroupAccountDetailsReply); + msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply, + LLPanelGroupLandMoney::processGroupAccountTransactionsReply); + + msg->setHandlerFuncFast(_PREHASH_UserInfoReply, + process_user_info_reply); + + msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL); + + msg->setHandlerFunc("TeleportStart", process_teleport_start ); + msg->setHandlerFunc("TeleportProgress", process_teleport_progress); + msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL); + msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL); + + msg->setHandlerFunc("ImageNotInDatabase", LLViewerTextureList::processImageNotInDatabase, NULL); + + msg->setHandlerFuncFast(_PREHASH_GroupMembersReply, + LLGroupMgr::processGroupMembersReply); + msg->setHandlerFunc("GroupRoleDataReply", + LLGroupMgr::processGroupRoleDataReply); + msg->setHandlerFunc("GroupRoleMembersReply", + LLGroupMgr::processGroupRoleMembersReply); + msg->setHandlerFunc("GroupTitlesReply", + LLGroupMgr::processGroupTitlesReply); + // Special handler as this message is sometimes used for group land. + msg->setHandlerFunc("PlacesReply", process_places_reply); + msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply); + + msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); + + msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); + msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); + msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply); + + msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); + msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply); + msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply); + msg->setHandlerFunc("ScriptDialog", process_script_dialog); + msg->setHandlerFunc("LoadURL", process_load_url); + msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request); + msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply); + + // calling cards + msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard); + msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard); + msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard); + + msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply); + + msg->setHandlerFunc("InitiateDownload", process_initiate_download); + msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply); + msg->setHandlerFunc("GenericMessage", process_generic_message); + msg->setHandlerFunc("GenericStreamingMessage", process_generic_streaming_message); + msg->setHandlerFunc("LargeGenericMessage", process_large_generic_message); + + msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message); +} + +void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32) +{ + // nothing +} + +const S32 OPT_CLOSED_WINDOW = -1; +const S32 OPT_MALE = 0; +const S32 OPT_FEMALE = 1; +const S32 OPT_TRUST_CERT = 0; +const S32 OPT_CANCEL_TRUST = 1; + +bool callback_choose_gender(const LLSD& notification, const LLSD& response) +{ + + // These defaults are returned from the server on login. They are set in login.xml. + // If no default is returned from the server, they are retrieved from settings.xml. + + S32 option = LLNotification::getSelectedOption(notification, response); + switch(option) + { + case OPT_MALE: + LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultMaleAvatar"), "male" ); + break; + + case OPT_FEMALE: + case OPT_CLOSED_WINDOW: + default: + LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultFemaleAvatar"), "female" ); + break; + } + return false; +} + +std::string get_screen_filename(const std::string& pattern) +{ + if (LLGridManager::getInstance()->isInProductionGrid()) + { + return llformat(pattern.c_str(), ""); + } + else + { + const std::string& grid_id_str = LLGridManager::getInstance()->getGridId(); + const std::string& grid_id_lower = utf8str_tolower(grid_id_str); + std::string grid = "." + grid_id_lower; + return llformat(pattern.c_str(), grid.c_str()); + } +} + +//static +std::string LLStartUp::getScreenLastFilename() +{ + return get_screen_filename(SCREEN_LAST_FILENAME); +} + +//static +std::string LLStartUp::getScreenHomeFilename() +{ + return get_screen_filename(SCREEN_HOME_FILENAME); +} + +//static +void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, + const std::string& gender_name ) +{ + LL_DEBUGS() << "starting" << LL_ENDL; + + // Not going through the processAgentInitialWearables path, so need to set this here. + LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); + // Initiate creation of COF, since we're also bypassing that. + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); + LLAppearanceMgr::getInstance()->initCOFID(); + + ESex gender; + if (gender_name == "male") + { + LL_DEBUGS() << "male" << LL_ENDL; + gender = SEX_MALE; + } + else + { + LL_DEBUGS() << "female" << LL_ENDL; + gender = SEX_FEMALE; + } + + if (!isAgentAvatarValid()) + { + LL_WARNS() << "Trying to load an initial outfit for an invalid agent avatar" << LL_ENDL; + return; + } + + gAgentAvatarp->setSex(gender); + + // try to find the requested outfit or folder + + // -- check for existing outfit in My Outfits + bool do_copy = false; + LLUUID cat_id = findDescendentCategoryIDByName( + gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS), + outfit_folder_name); + + // -- check for existing folder in Library + if (cat_id.isNull()) + { + cat_id = findDescendentCategoryIDByName( + gInventory.getLibraryRootFolderID(), + outfit_folder_name); + if (!cat_id.isNull()) + { + do_copy = true; + } + } + + if (cat_id.isNull()) + { + // -- final fallback: create standard wearables + LL_DEBUGS() << "standard wearables" << LL_ENDL; + gAgentWearables.createStandardWearables(); + } + else + { + bool do_append = false; + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + // Need to fetch cof contents before we can wear. + if (do_copy) + { + callAfterCOFFetch(boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); + } + else + { + callAfterCategoryLinksFetch(cat_id, boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); + } + LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL; + } + + gAgent.setOutfitChosen(true); + gAgentWearables.sendDummyAgentWearablesUpdate(); +} + +std::string& LLStartUp::getInitialOutfitName() +{ + return sInitialOutfit; +} + +std::string LLStartUp::getUserId() +{ + if (gUserCredential.isNull()) + { + return ""; + } + return gUserCredential->userID(); +} + + +// frees the bitmap +void release_start_screen() +{ + LL_DEBUGS("AppInit") << "Releasing bitmap..." << LL_ENDL; + gStartTexture = NULL; +} + + +// static +std::string LLStartUp::startupStateToString(EStartupState state) +{ +#define RTNENUM(E) case E: return #E + switch(state){ + RTNENUM( STATE_FIRST ); + RTNENUM( STATE_BROWSER_INIT ); + RTNENUM( STATE_LOGIN_SHOW ); + RTNENUM( STATE_LOGIN_WAIT ); + RTNENUM( STATE_LOGIN_CLEANUP ); + RTNENUM( STATE_LOGIN_AUTH_INIT ); + RTNENUM( STATE_LOGIN_CURL_UNSTUCK ); + RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); + RTNENUM( STATE_WORLD_INIT ); + RTNENUM( STATE_MULTIMEDIA_INIT ); + RTNENUM( STATE_FONT_INIT ); + RTNENUM( STATE_SEED_GRANTED_WAIT ); + RTNENUM( STATE_SEED_CAP_GRANTED ); + RTNENUM( STATE_WORLD_WAIT ); + RTNENUM( STATE_AGENT_SEND ); + RTNENUM( STATE_AGENT_WAIT ); + RTNENUM( STATE_INVENTORY_SEND ); + RTNENUM(STATE_INVENTORY_CALLBACKS ); + RTNENUM( STATE_INVENTORY_SKEL ); + RTNENUM( STATE_INVENTORY_SEND2 ); + RTNENUM( STATE_MISC ); + RTNENUM( STATE_PRECACHE ); + RTNENUM( STATE_WEARABLES_WAIT ); + RTNENUM( STATE_CLEANUP ); + RTNENUM( STATE_STARTED ); + default: + return llformat("(state #%d)", state); + } +#undef RTNENUM +} + +// static +void LLStartUp::setStartupState( EStartupState state ) +{ + LL_INFOS("AppInit") << "Startup state changing from " << + getStartupStateString() << " to " << + startupStateToString(state) << LL_ENDL; + + getPhases().stopPhase(getStartupStateString()); + gStartupState = state; + getPhases().startPhase(getStartupStateString()); + + postStartupState(); +} + +void LLStartUp::postStartupState() +{ + LLSD stateInfo; + stateInfo["str"] = getStartupStateString(); + stateInfo["enum"] = gStartupState; + sStateWatcher->post(stateInfo); + gDebugInfo["StartupState"] = getStartupStateString(); +} + + +void reset_login() +{ + gAgentWearables.cleanup(); + gAgentCamera.cleanup(); + gAgent.cleanup(); + gSky.cleanup(); // mVOSkyp is an inworld object. + LLWorld::getInstance()->resetClass(); + LLAppearanceMgr::getInstance()->cleanup(); + + if ( gViewerWindow ) + { // Hide menus and normal buttons + gViewerWindow->setNormalControlsVisible( false ); + gLoginMenuBarView->setVisible( true ); + gLoginMenuBarView->setEnabled( true ); + } + + // Hide any other stuff + LLFloaterReg::hideVisibleInstances(); + + if (LLStartUp::getStartupState() > STATE_WORLD_INIT) + { + gViewerWindow->resetStatusBarContainer(); + } + LLStartUp::setStartupState( STATE_BROWSER_INIT ); + + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->terminate(); + } + + // Clear any verified certs and verify them again on next login + // to ensure cert matches server instead of just getting reused + LLPointer store = gSecAPIHandler->getCertificateStore(""); + store->clearSertCache(); +} + +//--------------------------------------------------------------------------- + +// Initialize all plug-ins except the web browser (which was initialized +// early, before the login screen). JC +void LLStartUp::multimediaInit() +{ + LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingMultimedia"); + set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str()); + display_startup(); +} + +void LLStartUp::fontInit() +{ + LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingFonts"); + set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str()); + display_startup(); + + LLFontGL::loadDefaultFonts(); +} + +void LLStartUp::initNameCache() +{ + // Can be called multiple times + if ( gCacheName ) return; + + gCacheName = new LLCacheName(gMessageSystem); + gCacheName->addObserver(&callback_cache_name); + gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting")); + gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody")); + gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone")); + // Load stored cache if possible + LLAppViewer::instance()->loadNameCache(); + + // Start cache in not-running state until we figure out if we have + // capabilities for display name lookup + LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance(); + cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI")); + cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); + cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); +} + + +void LLStartUp::initExperiences() +{ + // Should trigger loading the cache. + LLExperienceCache::instance().setCapabilityQuery( + boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); + + LLExperienceLog::instance().initialize(); +} + +void LLStartUp::cleanupNameCache() +{ + delete gCacheName; + gCacheName = NULL; +} + +bool LLStartUp::dispatchURL() +{ + // ok, if we've gotten this far and have a startup URL + if (!getStartSLURL().isValid()) + { + return false; + } + if(getStartSLURL().getType() != LLSLURL::APP) + { + + // If we started with a location, but we're already + // at that location, don't pop dialogs open. + LLVector3 pos = gAgent.getPositionAgent(); + LLVector3 slurlpos = getStartSLURL().getPosition(); + F32 dx = pos.mV[VX] - slurlpos.mV[VX]; + F32 dy = pos.mV[VY] - slurlpos.mV[VY]; + const F32 SLOP = 2.f; // meters + + if( getStartSLURL().getRegion() != gAgent.getRegion()->getName() + || (dx*dx > SLOP*SLOP) + || (dy*dy > SLOP*SLOP) ) + { + LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, + NULL, false); + } + return true; + } + return false; +} + +void LLStartUp::setStartSLURL(const LLSLURL& slurl) +{ + LL_DEBUGS("AppInit")< socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); + std::string socks_user = socks_cred->getIdentifier()["username"].asString(); + std::string socks_password = socks_cred->getAuthenticator()["creds"].asString(); + + bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password); + + if (!ok) + { + LLNotificationsUtil::add("SOCKS_BAD_CREDS"); + proxy_ok = false; + } + } + else if (auth_type.compare("None") == 0) + { + LLProxy::getInstance()->setAuthNone(); + } + else + { + LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL; + + // Unknown or missing setting. + gSavedSettings.setString("Socks5AuthType", "None"); + + // Clear the SOCKS credentials. + LLPointer socks_cred = new LLCredential("SOCKS5"); + gSecAPIHandler->deleteCredential(socks_cred); + + LLProxy::getInstance()->setAuthNone(); + } + + if (proxy_ok) + { + // Start the proxy and check for errors + // If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns. + LLHost socks_host; + socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + int status = LLProxy::getInstance()->startSOCKSProxy(socks_host); + + if (status != SOCKS_OK) + { + LLSD subs; + subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); + subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); + + std::string error_string; + + switch(status) + { + case SOCKS_CONNECT_ERROR: // TCP Fail + error_string = "SOCKS_CONNECT_ERROR"; + break; + + case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection + error_string = "SOCKS_NOT_PERMITTED"; + break; + + case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server + error_string = "SOCKS_NOT_ACCEPTABLE"; + break; + + case SOCKS_AUTH_FAIL: // Authentication failed + error_string = "SOCKS_AUTH_FAIL"; + break; + + case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed + error_string = "SOCKS_UDP_FWD_NOT_GRANTED"; + break; + + case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server + error_string = "SOCKS_HOST_CONNECT_FAILED"; + break; + + case SOCKS_INVALID_HOST: // Improperly formatted host address or port. + error_string = "SOCKS_INVALID_HOST"; + break; + + default: + error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened, + LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL; + break; + } + + LLNotificationsUtil::add(error_string, subs); + proxy_ok = false; + } + } + } + else + { + LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up + } + + if (proxy_ok) + { + // Determine the HTTP proxy type (if any) + if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) + { + LLHost http_host; + http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); + http_host.setPort(gSavedSettings.getS32("BrowserProxyPort")); + if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP)) + { + LLSD subs; + subs["HOST"] = http_host.getIPString(); + subs["PORT"] = (S32)http_host.getPort(); + LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs); + proxy_ok = false; + } + } + else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) + { + LLHost socks_host; + socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS)) + { + LLSD subs; + subs["HOST"] = socks_host.getIPString(); + subs["PORT"] = (S32)socks_host.getPort(); + LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs); + proxy_ok = false; + } + } + else if (httpProxyType.compare("None") == 0) + { + LLProxy::getInstance()->disableHTTPProxy(); + } + else + { + LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration: " << httpProxyType << LL_ENDL; + + // Set the missing or wrong configuration back to something valid. + gSavedSettings.setString("HttpProxyType", "None"); + LLProxy::getInstance()->disableHTTPProxy(); + + // Leave proxy_ok alone, since this isn't necessarily fatal. + } + } + + return proxy_ok; +} + +bool login_alert_done(const LLSD& notification, const LLSD& response) +{ + LLPanelLogin::giveFocus(); + return false; +} + +// parse the certificate information into args for the +// certificate notifications +LLSD transform_cert_args(LLPointer cert) +{ + LLSD args = LLSD::emptyMap(); + std::string value; + LLSD cert_info; + cert->getLLSD(cert_info); + // convert all of the elements in the cert into + // args for the xml dialog, so we have flexability to + // display various parts of the cert by only modifying + // the cert alert dialog xml. + for(LLSD::map_iterator iter = cert_info.beginMap(); + iter != cert_info.endMap(); + iter++) + { + // key usage and extended key usage + // are actually arrays, and we want to format them as comma separated + // strings, so special case those. + LLSDSerialize::toXML(cert_info[iter->first], std::cout); + if((iter->first == std::string(CERT_KEY_USAGE)) || + (iter->first == std::string(CERT_EXTENDED_KEY_USAGE))) + { + value = ""; + LLSD usage = cert_info[iter->first]; + for (LLSD::array_iterator usage_iter = usage.beginArray(); + usage_iter != usage.endArray(); + usage_iter++) + { + + if(usage_iter != usage.beginArray()) + { + value += ", "; + } + + value += (*usage_iter).asString(); + } + + } + else + { + value = iter->second.asString(); + } + + std::string name = iter->first; + std::transform(name.begin(), name.end(), name.begin(), + (int(*)(int))toupper); + args[name.c_str()] = value; + } + return args; +} + + +// when we handle a cert error, give focus back to the login panel +void general_cert_done(const LLSD& notification, const LLSD& response) +{ + LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + LLPanelLogin::giveFocus(); +} + +// check to see if the user wants to trust the cert. +// if they do, add it to the cert store and +void trust_cert_done(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + switch(option) + { + case OPT_TRUST_CERT: + { + LLPointer cert = gSecAPIHandler->getCertificate(notification["payload"]["certificate"]); + LLPointer store = gSecAPIHandler->getCertificateStore(gSavedSettings.getString("CertStore")); + store->add(cert); + store->save(); + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + break; + } + case OPT_CANCEL_TRUST: + reset_login(); + gSavedSettings.setBOOL("AutoLogin", false); + LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + default: + LLPanelLogin::giveFocus(); + break; + } + +} + +void apply_udp_blacklist(const std::string& csv) +{ + + std::string::size_type start = 0; + std::string::size_type comma = 0; + do + { + comma = csv.find(",", start); + if (comma == std::string::npos) + { + comma = csv.length(); + } + std::string item(csv, start, comma-start); + + LL_DEBUGS() << "udp_blacklist " << item << LL_ENDL; + gMessageSystem->banUdpMessage(item); + + start = comma + 1; + + } + while(comma < csv.length()); + +} + +void on_benefits_failed_callback(const LLSD& notification, const LLSD& response) +{ + LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL; +} + +bool init_benefits(LLSD& response) +{ + bool succ = true; + + std::string package_name = response["account_type"].asString(); + const LLSD& benefits_sd = response["account_level_benefits"]; + if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) || + !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd)) + { + succ = false; + } + else + { + LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL; + } + const LLSD& packages_sd = response["premium_packages"]; + for(LLSD::map_const_iterator package_iter = packages_sd.beginMap(); + package_iter != packages_sd.endMap(); + ++package_iter) + { + std::string package_name = package_iter->first; + const LLSD& benefits_sd = package_iter->second["benefits"]; + if (LLAgentBenefitsMgr::init(package_name, benefits_sd)) + { + LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL; + } + else + { + LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL; + succ = false; + } + } + + if (!LLAgentBenefitsMgr::has("Base")) + { + LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL; + succ = false; + } + if (!LLAgentBenefitsMgr::has("Premium")) + { + LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL; + succ = false; + } + + return succ; +} + +bool process_login_success_response() +{ + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + mBenefitsSuccessfullyInit = init_benefits(response); + + std::string text(response["udp_blacklist"]); + if(!text.empty()) + { + apply_udp_blacklist(text); + } + + // unpack login data needed by the application + text = response["agent_id"].asString(); + if(!text.empty()) gAgentID.set(text); + gDebugInfo["AgentID"] = text; + + LLPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("PerfStatsCaptureEnabled")); + LLPerfStats::StatsRecorder::setFocusAv(gAgentID); + + // Agent id needed for parcel info request in LLUrlEntryParcel + // to resolve parcel name. + LLUrlEntryParcel::setAgentID(gAgentID); + + text = response["session_id"].asString(); + if(!text.empty()) gAgentSessionID.set(text); + gDebugInfo["SessionID"] = text; + + // Session id needed for parcel info request in LLUrlEntryParcel + // to resolve parcel name. + LLUrlEntryParcel::setSessionID(gAgentSessionID); + + text = response["secure_session_id"].asString(); + if(!text.empty()) gAgent.mSecureSessionID.set(text); + + // if the response contains a display name, use that, + // otherwise if the response contains a first and/or last name, + // use those. Otherwise use the credential identifier + + gDisplayName = ""; + if (response.has("display_name")) + { + gDisplayName.assign(response["display_name"].asString()); + if(!gDisplayName.empty()) + { + // Remove quotes from string. Login.cgi sends these to force + // names that look like numbers into strings. + LLStringUtil::replaceChar(gDisplayName, '"', ' '); + LLStringUtil::trim(gDisplayName); + } + } + std::string first_name; + if(response.has("first_name")) + { + first_name = response["first_name"].asString(); + LLStringUtil::replaceChar(first_name, '"', ' '); + LLStringUtil::trim(first_name); + gAgentUsername = first_name; + } + + if(response.has("last_name") && !gAgentUsername.empty()) + { + std::string last_name = response["last_name"].asString(); + if (last_name != "Resident") + { + LLStringUtil::replaceChar(last_name, '"', ' '); + LLStringUtil::trim(last_name); + gAgentUsername = gAgentUsername + " " + last_name; + } + } + + if(gDisplayName.empty()) + { + if(response.has("first_name")) + { + gDisplayName.assign(response["first_name"].asString()); + LLStringUtil::replaceChar(gDisplayName, '"', ' '); + LLStringUtil::trim(gDisplayName); + } + if(response.has("last_name")) + { + text.assign(response["last_name"].asString()); + LLStringUtil::replaceChar(text, '"', ' '); + LLStringUtil::trim(text); + if(!gDisplayName.empty()) + { + gDisplayName += " "; + } + gDisplayName += text; + } + } + + if(gDisplayName.empty()) + { + gDisplayName.assign(gUserCredential->asString()); + } + + // this is their actual ability to access content + text = response["agent_access_max"].asString(); + if (!text.empty()) + { + // agent_access can be 'A', 'M', and 'PG'. + gAgent.setMaturity(text[0]); + } + + // this is the value of their preference setting for that content + // which will always be <= agent_access_max + text = response["agent_region_access"].asString(); + if (!text.empty()) + { + U32 preferredMaturity = (U32)LLAgent::convertTextToMaturity(text[0]); + + gSavedSettings.setU32("PreferredMaturity", preferredMaturity); + } + + text = response["start_location"].asString(); + if(!text.empty()) + { + gAgentStartLocation.assign(text); + } + + text = response["circuit_code"].asString(); + if(!text.empty()) + { + gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10); + } + std::string sim_ip_str = response["sim_ip"]; + std::string sim_port_str = response["sim_port"]; + if(!sim_ip_str.empty() && !sim_port_str.empty()) + { + U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); + gFirstSim.set(sim_ip_str, sim_port); + if (gFirstSim.isOk()) + { + gMessageSystem->enableCircuit(gFirstSim, true); + } + } + std::string region_x_str = response["region_x"]; + std::string region_y_str = response["region_y"]; + if(!region_x_str.empty() && !region_y_str.empty()) + { + U32 region_x = strtoul(region_x_str.c_str(), NULL, 10); + U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); + gFirstSimHandle = to_region_handle(region_x, region_y); + } + + const std::string look_at_str = response["look_at"]; + if (!look_at_str.empty()) + { + size_t len = look_at_str.size(); + LLMemoryStream mstr((U8*)look_at_str.c_str(), len); + LLSD sd = LLSDSerialize::fromNotation(mstr, len); + gAgentStartLookAt = ll_vector3_from_sd(sd); + } + + text = response["seed_capability"].asString(); + if (!text.empty()) gFirstSimSeedCap = text; + + text = response["seconds_since_epoch"].asString(); + if(!text.empty()) + { + U32 server_utc_time = strtoul(text.c_str(), NULL, 10); + if(server_utc_time) + { + time_t now = time(NULL); + gUTCOffset = (server_utc_time - now); + + // Print server timestamp + LLSD substitution; + substitution["datetime"] = (S32)server_utc_time; + std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]"; + LLStringUtil::format(timeStr, substitution); + LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL; + } + } + + // this is the base used to construct help URLs + text = response["help_url_format"].asString(); + if (!text.empty()) + { + // replace the default help URL format + gSavedSettings.setString("HelpURLFormat",text); + } + + std::string home_location = response["home"]; + if(!home_location.empty()) + { + size_t len = home_location.size(); + LLMemoryStream mstr((U8*)home_location.c_str(), len); + LLSD sd = LLSDSerialize::fromNotation(mstr, len); + S32 region_x = sd["region_handle"][0].asInteger(); + S32 region_y = sd["region_handle"][1].asInteger(); + U64 region_handle = to_region_handle(region_x, region_y); + LLVector3 position = ll_vector3_from_sd(sd["position"]); + gAgent.setHomePosRegion(region_handle, position); + } + + gAgent.mMOTD.assign(response["message"]); + + // Options... + // Each 'option' is an array of submaps. + // It appears that we only ever use the first element of the array. + LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"]; + if(inv_root_folder_id.notNull()) + { + gInventory.setRootFolderID(inv_root_folder_id); + //gInventory.mock(gAgent.getInventoryRootID()); + } + + LLSD login_flags = response["login-flags"][0]; + if(login_flags.size()) + { + std::string flag = login_flags["ever_logged_in"]; + if(!flag.empty()) + { + gAgent.setFirstLogin(flag == "N"); + } + + /* Flag is currently ignored by the viewer. + flag = login_flags["stipend_since_login"]; + if(flag == "Y") + { + stipend_since_login = true; + } + */ + + flag = login_flags["gendered"].asString(); + if(flag == "Y") + { + // We don't care about this flag anymore; now base whether + // outfit is chosen on COF contents, initial outfit + // requested and available, etc. + + //gAgent.setGenderChosen(true); + } + + bool pacific_daylight_time = false; + flag = login_flags["daylight_savings"].asString(); + if(flag == "Y") + { + pacific_daylight_time = (flag == "Y"); + } + + //setup map of datetime strings to codes and slt & local time offset from utc + LLStringOps::setupDatetimeInfo(pacific_daylight_time); + } + + // set up the voice configuration. Ultimately, we should pass this up as part of each voice + // channel if we need to move to multiple voice servers per grid. + LLSD voice_config_info = response["voice-config"]; + if(voice_config_info.has("VoiceServerType")) + { + gSavedSettings.setString("VoiceServerType", voice_config_info["VoiceServerType"].asString()); + } + + // Request the map server url + std::string map_server_url = response["map-server-url"]; + if(!map_server_url.empty()) + { + // We got an answer from the grid -> use that for map for the current session + gSavedSettings.setString("CurrentMapServerURL", map_server_url); + LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL; + } + else + { + // No answer from the grid -> use the default setting for current session + map_server_url = gSavedSettings.getString("MapServerURL"); + gSavedSettings.setString("CurrentMapServerURL", map_server_url); + LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL; + } + + // Default male and female avatars allowing the user to choose their avatar on first login. + // These may be passed up by SLE to allow choice of enterprise avatars instead of the standard + // "new ruth." Not to be confused with 'initial-outfit' below + LLSD newuser_config = response["newuser-config"][0]; + if(newuser_config.has("DefaultFemaleAvatar")) + { + gSavedSettings.setString("DefaultFemaleAvatar", newuser_config["DefaultFemaleAvatar"].asString()); + } + if(newuser_config.has("DefaultMaleAvatar")) + { + gSavedSettings.setString("DefaultMaleAvatar", newuser_config["DefaultMaleAvatar"].asString()); + } + + // Initial outfit for the user. + LLSD initial_outfit = response["initial-outfit"][0]; + if(initial_outfit.size()) + { + std::string flag = initial_outfit["folder_name"]; + if(!flag.empty()) + { + // Initial outfit is a folder in your inventory, + // must be an exact folder-name match. + sInitialOutfit = flag; + } + + flag = initial_outfit["gender"].asString(); + if(!flag.empty()) + { + sInitialOutfitGender = flag; + } + } + + std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName"); + if (!fake_initial_outfit_name.empty()) + { + gAgent.setFirstLogin(true); + sInitialOutfit = fake_initial_outfit_name; + if (sInitialOutfitGender.empty()) + { + sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway. + } + + LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL; + } + + // set the location of the Agent Appearance service, from which we can request + // avatar baked textures if they are supported by the current region + std::string agent_appearance_url = response["agent_appearance_service"]; + if (!agent_appearance_url.empty()) + { + LLAppearanceMgr::instance().setAppearanceServiceURL(agent_appearance_url); + } + + // Set the location of the snapshot sharing config endpoint + std::string snapshot_config_url = response["snapshot_config_url"]; + if(!snapshot_config_url.empty()) + { + gSavedSettings.setString("SnapshotConfigURL", snapshot_config_url); + } + + // Start the process of fetching the OpenID session cookie for this user login + std::string openid_url = response["openid_url"]; + if(!openid_url.empty()) + { + std::string openid_token = response["openid_token"]; + LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token); + } + + + // Only save mfa_hash for future logins if the user wants their info remembered. + if(response.has("mfa_hash") + && gSavedSettings.getBOOL("RememberUser") + && LLLoginInstance::getInstance()->saveMFA()) + { + std::string grid(LLGridManager::getInstance()->getGridId()); + std::string user_id(gUserCredential->userID()); + gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, response["mfa_hash"]); + // TODO(brad) - related to SL-17223 consider building a better interface that sync's automatically + gSecAPIHandler->syncProtectedMap(); + } + else if (!LLLoginInstance::getInstance()->saveMFA()) + { + std::string grid(LLGridManager::getInstance()->getGridId()); + std::string user_id(gUserCredential->userID()); + gSecAPIHandler->removeFromProtectedMap("mfa_hash", grid, user_id); + gSecAPIHandler->syncProtectedMap(); + } + + bool success = false; + // JC: gesture loading done below, when we have an asset system + // in place. Don't delete/clear gUserCredentials until then. + if(gAgentID.notNull() + && gAgentSessionID.notNull() + && gMessageSystem->mOurCircuitCode + && gFirstSim.isOk() + && gInventory.getRootFolderID().notNull()) + { + success = true; + } + LLAppViewer* pApp = LLAppViewer::instance(); + pApp->writeDebugInfo(); //Write our static data now that we have username, session_id, etc. + return success; +} + +void transition_back_to_login_panel(const std::string& emsg) +{ + // Bounce back to the login screen. + reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + gSavedSettings.setBOOL("AutoLogin", false); +} + -- cgit v1.2.3