From dc934629919bdcaea72c78e5291263914fb958ec Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 11 May 2009 20:05:46 +0000 Subject: svn merge -r113003:119136 svn+ssh://svn.lindenlab.com/svn/linden/branches/login-api/login-api-2 svn+ssh://svn.lindenlab.com/svn/linden/branches/login-api/login-api-3 --- indra/newview/lllogininstance.cpp | 532 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 532 insertions(+) create mode 100644 indra/newview/lllogininstance.cpp (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp new file mode 100644 index 0000000000..388bf38d61 --- /dev/null +++ b/indra/newview/lllogininstance.cpp @@ -0,0 +1,532 @@ +/** + * @file lllogininstance.cpp + * @brief Viewer's host for a login connection. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lllogininstance.h" + +// llcommon +#include "llevents.h" +#include "llmd5.h" +#include "stringize.h" + +// llmessage (!) +#include "llfiltersd2xmlrpc.h" // for xml_escape_string() + +// login +#include "lllogin.h" + +// newview +#include "llviewernetwork.h" +#include "llappviewer.h" // Wish I didn't have to, but... +#include "llviewercontrol.h" +#include "llurlsimstring.h" +#include "llfloatertos.h" +#include "llwindow.h" + +std::string construct_start_string(); + +LLLoginInstance::LLLoginInstance() : + mLoginModule(new LLLogin()), + mLoginState("offline"), + mUserInteraction(true), + mSkipOptionalUpdate(false), + mAttemptComplete(false), + mTransferRate(0.0f) +{ + mLoginModule->getEventPump().listen("lllogininstance", + boost::bind(&LLLoginInstance::handleLoginEvent, this, _1)); +} + +LLLoginInstance::~LLLoginInstance() +{ +} + + +void LLLoginInstance::connect(const LLSD& credentials) +{ + std::vector uris; + LLViewerLogin::getInstance()->getLoginURIs(uris); + connect(uris.front(), credentials); +} + +void LLLoginInstance::connect(const std::string& uri, const LLSD& credentials) +{ + constructAuthParams(credentials); + mLoginModule->connect(uri, mRequestData); +} + +void LLLoginInstance::reconnect() +{ + // Sort of like connect, only using the pre-existing + // request params. + std::vector uris; + LLViewerLogin::getInstance()->getLoginURIs(uris); + mLoginModule->connect(uris.front(), mRequestData); +} + +void LLLoginInstance::disconnect() +{ + mRequestData.clear(); + mLoginModule->disconnect(); +} + +LLSD LLLoginInstance::getResponse() +{ + return mResponseData; +} + +void LLLoginInstance::constructAuthParams(const LLSD& credentials) +{ + // Set up auth request options. +//#define LL_MINIMIAL_REQUESTED_OPTIONS + LLSD requested_options; + // *Note: this is where gUserAuth used to be created. + requested_options.append("inventory-root"); + requested_options.append("inventory-skeleton"); + //requested_options.append("inventory-meat"); + //requested_options.append("inventory-skel-targets"); +#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS) + if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary")) + { + requested_options.append("inventory-lib-root"); + requested_options.append("inventory-lib-owner"); + requested_options.append("inventory-skel-lib"); + // requested_options.append("inventory-meat-lib"); + } + + requested_options.append("initial-outfit"); + requested_options.append("gestures"); + requested_options.append("event_categories"); + requested_options.append("event_notifications"); + requested_options.append("classified_categories"); + //requested_options.append("inventory-targets"); + requested_options.append("buddy-list"); + requested_options.append("ui-config"); +#endif + requested_options.append("tutorial_setting"); + requested_options.append("login-flags"); + requested_options.append("global-textures"); + if(gSavedSettings.getBOOL("ConnectAsGod")) + { + gSavedSettings.setBOOL("UseDebugMenus", TRUE); + requested_options.append("god-connect"); + } + + char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ + LLMD5 hashed_mac; + hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); + hashed_mac.finalize(); + hashed_mac.hex_digest(hashed_mac_string); + + // prepend "$1$" to the password to indicate its the md5'd version. + std::string dpasswd("$1$"); + dpasswd.append(credentials["passwd"].asString()); + + // (re)initialize the request params with creds. + LLSD request_params(credentials); + request_params["passwd"] = dpasswd; + request_params["start"] = construct_start_string(); + request_params["skipoptional"] = mSkipOptionalUpdate; + request_params["agree_to_tos"] = false; // Always false here. Set true in + request_params["read_critical"] = false; // handleTOSResponse + request_params["last_exec_event"] = gLastExecEvent; + request_params["mac"] = hashed_mac_string; + request_params["version"] = gCurrentVersion; // Includes channel name + request_params["channel"] = gSavedSettings.getString("VersionChannelName"); + request_params["id0"] = LLAppViewer::instance()->getSerialNumber(); + + mRequestData["method"] = "login_to_simulator"; + mRequestData["params"] = request_params; + mRequestData["options"] = requested_options; +} + +bool LLLoginInstance::handleLoginEvent(const LLSD& event) +{ + std::cout << "LoginListener called!: \n"; + std::cout << event << "\n"; + + if(!(event.has("state") && event.has("progress"))) + { + llerrs << "Unknown message from LLLogin!" << llendl; + } + + mLoginState = event["state"].asString(); + mResponseData = event["data"]; + + if(event.has("transfer_rate")) + { + mTransferRate = event["transfer_rate"].asReal(); + } + + if(mLoginState == "offline") + { + handleLoginFailure(event); + } + else if(mLoginState == "online") + { + handleLoginSuccess(event); + } + + return false; +} + +bool LLLoginInstance::handleLoginFailure(const LLSD& event) +{ + // Login has failed. + // Figure out why and respond... + LLSD response = event["data"]; + std::string reason_response = response["reason"].asString(); + std::string message_response = response["message"].asString(); + if(mUserInteraction) + { + // For the cases of critical message or TOS agreement, + // start the TOS dialog. The dialog response will be handled + // by the LLLoginInstance::handleTOSResponse() callback. + // The callback intiates the login attempt next step, either + // to reconnect or to end the attempt in failure. + if(reason_response == "tos") + { + LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "agree_to_tos") + ); + tos_dialog->startModal(); + } + else if(reason_response == "critical") + { + LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical") + ); + tos_dialog->startModal(); + } + else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) + { + gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE); + updateApp(true, message_response); + } + else if(reason_response == "optional") + { + updateApp(false, message_response); + } + else + { + attemptComplete(); + } + } + else // no user interaction + { + attemptComplete(); + } + + return false; +} + +bool LLLoginInstance::handleLoginSuccess(const LLSD& event) +{ + LLSD response = event["data"]; + std::string message_response = response["message"].asString(); + if(gSavedSettings.getBOOL("ForceMandatoryUpdate")) + { + // Testing update... + gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE); + // Don't confuse startup by leaving login "online". + mLoginModule->disconnect(); + updateApp(true, message_response); + } + else + { + attemptComplete(); + } + return false; +} + +void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) +{ + if(accepted) + { + // Set the request data to true and retry login. + mRequestData[key] = true; + reconnect(); + } + else + { + attemptComplete(); + } +} + + +void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) +{ + // store off config state, as we might quit soon + gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); + + std::ostringstream message; + + //*TODO:translate + std::string msg; + if (!auth_msg.empty()) + { + msg = "(" + auth_msg + ") \n"; + } + + LLSD args; + args["MESSAGE"] = msg; + + LLSD payload; + payload["mandatory"] = mandatory; + +/* + We're constructing one of the following 6 strings here: + "DownloadWindowsMandatory" + "DownloadWindowsReleaseForDownload" + "DownloadWindows" + "DownloadMacMandatory" + "DownloadMacReleaseForDownload" + "DownloadMac" + + I've called them out explicitly in this comment so that they can be grepped for. + + Also, we assume that if we're not Windows we're Mac. If we ever intend to support + Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but + we'd rather deliver the wrong message than no message, so until Linux is supported + we'll leave it alone. + */ + std::string notification_name = "Download"; + +#if LL_WINDOWS + notification_name += "Windows"; +#else + notification_name += "Mac"; +#endif + + if (mandatory) + { + notification_name += "Mandatory"; + } + else + { +#if LL_RELEASE_FOR_DOWNLOAD + notification_name += "ReleaseForDownload"; +#endif + } + + LLNotifications::instance().add(notification_name, args, payload, + boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2)); +} + +bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + std::string update_exe_path; + bool mandatory = notification["payload"]["mandatory"].asBoolean(); + +#if !LL_RELEASE_FOR_DOWNLOAD + if (option == 2) + { + // This condition attempts to skip the + // update if using a dev build. + // The relog probably won't work if the + // update is mandatory. :) + + // *REMOVE:Mani - Saving for reference... + //LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); + mSkipOptionalUpdate = true; + reconnect(); + return false; + } +#endif + + if (option == 1) + { + // ...user doesn't want to do it + if (mandatory) + { + // Mandatory update, user chose to not to update... + // The login attemp is complete, startup should + // quit when detecting this. + attemptComplete(); + + // *REMOVE:Mani - Saving for reference... + //LLAppViewer::instance()->forceQuit(); + // // Bump them back to the login screen. + // //reset_login(); + } + else + { + // Optional update, user chose to skip + mSkipOptionalUpdate = true; + reconnect(); + } + return false; + } + + LLSD query_map = LLSD::emptyMap(); + // *TODO place os string in a global constant +#if LL_WINDOWS + query_map["os"] = "win"; +#elif LL_DARWIN + query_map["os"] = "mac"; +#elif LL_LINUX + query_map["os"] = "lnx"; +#elif LL_SOLARIS + query_map["os"] = "sol"; +#endif + // *TODO change userserver to be grid on both viewer and sim, since + // userserver no longer exists. + query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); + query_map["channel"] = gSavedSettings.getString("VersionChannelName"); + // *TODO constantize this guy + LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); + + if(LLAppViewer::sUpdaterInfo) + { + delete LLAppViewer::sUpdaterInfo; + } + LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; + +#if LL_WINDOWS + LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); + if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + // We're hosed, bail + LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL; + + attemptComplete(); + // *REMOVE:Mani - Saving for reference... + // LLAppViewer::instance()->forceQuit(); + return false; + } + + LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe"; + + std::string updater_source = gDirUtilp->getAppRODataDir(); + updater_source += gDirUtilp->getDirDelimiter(); + updater_source += "updater.exe"; + + LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source + << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath + << LL_ENDL; + + + if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE)) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL; + attemptComplete(); + // *REMOVE:Mani - Saving for reference... + // LLAppViewer::instance()->forceQuit(); + return false; + } + + // if a sim name was passed in via command line parameter (typically through a SLURL) + if ( LLURLSimString::sInstance.mSimString.length() ) + { + // record the location to start at next time + gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); + }; + + LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; + + //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird. + LLAppViewer::instance()->removeMarkerFile(); // In case updater fails + + // *NOTE:Mani The updater is spawned as the last thing before the WinMain exit. + // see LLAppViewerWin32.cpp + +#elif LL_DARWIN + // if a sim name was passed in via command line parameter (typically through a SLURL) + if ( LLURLSimString::sInstance.mSimString.length() ) + { + // record the location to start at next time + gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); + }; + + LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; + LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; + + // Run the auto-updater. + system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ + +#elif LL_LINUX || LL_SOLARIS + OSMessageBox("Automatic updating is not yet implemented for Linux.\n" + "Please download the latest version from www.secondlife.com.", + LLStringUtil::null, OSMB_OK); +#endif + + // *REMOVE:Mani - Saving for reference... + // LLAppViewer::instance()->forceQuit(); + + return false; +} + +std::string construct_start_string() +{ + std::string start; + if (LLURLSimString::parse()) + { + // a startup URL was specified + std::string unescaped_start = + STRINGIZE( "uri:" + << LLURLSimString::sInstance.mSimName << "&" + << LLURLSimString::sInstance.mX << "&" + << LLURLSimString::sInstance.mY << "&" + << LLURLSimString::sInstance.mZ); + start = xml_escape_string(unescaped_start); + } + else if (gSavedSettings.getBOOL("LoginLastLocation")) + { + start = "last"; + } + else + { + start = "home"; + } + return start; +} -- cgit v1.3 From 3975de991d2afa2ed903ac28bcc91246dfb22c20 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 May 2009 23:35:42 +0000 Subject: svn merge -r113003:119136 svn+ssh://svn.lindenlab.com/svn/linden/branches/login-api/login-api-2 svn+ssh://svn.lindenlab.com/svn/linden/branches/login-api/login-api-3 (finish) --- indra/llcommon/CMakeLists.txt | 2 +- indra/llcommon/tests/lleventcoro_test.cpp | 827 +++++++++++++++ indra/newview/lllogininstance.cpp | 14 +- indra/newview/llstartup.cpp | 1368 ++++++++----------------- indra/newview/tests/llxmlrpclistener_test.cpp | 2 +- 5 files changed, 1281 insertions(+), 932 deletions(-) create mode 100644 indra/llcommon/tests/lleventcoro_test.cpp (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index d3d75f78df..62476fd59d 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -228,4 +228,4 @@ target_link_libraries( ADD_BUILD_TEST(lllazy llcommon) ADD_BUILD_TEST(lleventfilter llcommon) -ADD_BUILD_TEST(coroutine llcommon) +ADD_BUILD_TEST(lleventcoro llcommon) diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp new file mode 100644 index 0000000000..cd39ac4df3 --- /dev/null +++ b/indra/llcommon/tests/lleventcoro_test.cpp @@ -0,0 +1,827 @@ +/** + * @file coroutine_test.cpp + * @author Nat Goodspeed + * @date 2009-04-22 + * @brief Test for coroutine. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +/*****************************************************************************/ +// test<1>() is cloned from a Boost.Coroutine example program whose copyright +// info is reproduced here: +/*---------------------------------------------------------------------------*/ +// Copyright (c) 2006, Giovanni P. Deretta +// +// This code may be used under either of the following two licences: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. OF SUCH DAMAGE. +// +// Or: +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +/*****************************************************************************/ + +// On some platforms, Boost.Coroutine must #define magic symbols before +// #including platform-API headers. Naturally, that's ineffective unless the +// Boost.Coroutine #include is the *first* #include of the platform header. +// That means that client code must generally #include Boost.Coroutine headers +// before anything else. +#include +// Normally, lleventcoro.h obviates future.hpp. We only include this because +// we implement a "by hand" test of future functionality. +#include +#include +#include +#include +#include + +#include "../test/lltut.h" +#include "llsd.h" +#include "llevents.h" +#include "tests/wrapllerrs.h" +#include "stringize.h" +#include "lleventcoro.h" + +/***************************************************************************** +* Debugging stuff +*****************************************************************************/ +// This class is intended to illuminate entry to a given block, exit from the +// same block and checkpoints along the way. It also provides a convenient +// place to turn std::cout output on and off. +class Debug +{ +public: + Debug(const std::string& block): + mBlock(block) + { + (*this)("entry"); + } + + ~Debug() + { + (*this)("exit"); + } + + void operator()(const std::string& status) + { +// std::cout << mBlock << ' ' << status << std::endl; + } + +private: + const std::string mBlock; +}; + +// It's often convenient to use the name of the enclosing function as the name +// of the Debug block. +#define DEBUG Debug debug(__FUNCTION__) + +// These BEGIN/END macros are specifically for debugging output -- please +// don't assume you must use such for coroutines in general! They only help to +// make control flow (as well as exception exits) explicit. +#define BEGIN \ +{ \ + DEBUG; \ + try + +#define END \ + catch (...) \ + { \ +/* std::cout << "*** exceptional " << std::flush; */ \ + throw; \ + } \ +} + +/***************************************************************************** +* from the banana.cpp example program borrowed for test<1>() +*****************************************************************************/ +namespace coroutines = boost::coroutines; +using coroutines::coroutine; + +template +bool match(Iter first, Iter last, std::string match) { + std::string::iterator i = match.begin(); + i != match.end(); + for(; (first != last) && (i != match.end()); ++i) { + if (*first != *i) + return false; + ++first; + } + return i == match.end(); +} + +template +BidirectionalIterator +match_substring(BidirectionalIterator begin, + BidirectionalIterator end, + std::string xmatch, + BOOST_DEDUCED_TYPENAME coroutine::self& self) { + BidirectionalIterator begin_ = begin; + for(; begin != end; ++begin) + if(match(begin, end, xmatch)) { + self.yield(begin); + } + return end; +} + +typedef coroutine match_coroutine_type; + +/***************************************************************************** +* Test helpers +*****************************************************************************/ +// I suspect this will be typical of coroutines used in Linden software +typedef boost::coroutines::coroutine coroutine_type; + +/// Simulate an event API whose response is immediate: sent on receipt of the +/// initial request, rather than after some delay. This is the case that +/// distinguishes postAndWait() from calling post(), then calling +/// waitForEventOn(). +class ImmediateAPI +{ +public: + ImmediateAPI(): + mPump("immediate", true) + { + mPump.listen("API", boost::bind(&ImmediateAPI::operator(), this, _1)); + } + + LLEventPump& getPump() { return mPump; } + + // Invoke this with an LLSD map containing: + // ["value"]: Integer value. We will reply with ["value"] + 1. + // ["reply"]: Name of LLEventPump on which to send success response. + // ["error"]: Name of LLEventPump on which to send error response. + // ["fail"]: Presence of this key selects ["error"], else ["success"] as + // the name of the pump on which to send the response. + bool operator()(const LLSD& event) const + { + LLSD::Integer value(event["value"]); + LLSD::String replyPumpName(event.has("fail")? "error" : "reply"); + LLEventPumps::instance().obtain(event[replyPumpName]).post(value + 1); + return false; + } + +private: + LLEventStream mPump; +}; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct coroutine_data + { + // Define coroutine bodies as methods here so they can use ensure*() + + void explicit_wait(coroutine_type::self& self) + { + BEGIN + { + // ... do whatever preliminary stuff must happen ... + + // declare the future + boost::coroutines::future future(self); + // tell the future what to wait for + LLTempBoundListener connection( + LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::coroutines::make_callback(future)))); + ensure("Not yet", ! future); + // attempting to dereference ("resolve") the future causes the calling + // coroutine to wait for it + debug("about to wait"); + result = *future; + ensure("Got it", future); + } + END + } + + void waitForEventOn1(coroutine_type::self& self) + { + BEGIN + { + result = waitForEventOn(self, "source"); + } + END + } + + void waitForEventOn2(coroutine_type::self& self) + { + BEGIN + { + LLEventWithID pair = waitForEventOn(self, "reply", "error"); + result = pair.first; + which = pair.second; + debug(STRINGIZE("result = " << result << ", which = " << which)); + } + END + } + + void postAndWait1(coroutine_type::self& self) + { + BEGIN + { + result = postAndWait(self, + LLSD().insert("value", 17), // request event + immediateAPI.getPump(), // requestPump + "reply1", // replyPump + "reply"); // request["reply"] = name + } + END + } + + void postAndWait2(coroutine_type::self& self) + { + BEGIN + { + LLEventWithID pair = ::postAndWait2(self, + LLSD().insert("value", 18), + immediateAPI.getPump(), + "reply2", + "error2", + "reply", + "error"); + result = pair.first; + which = pair.second; + debug(STRINGIZE("result = " << result << ", which = " << which)); + } + END + } + + void postAndWait2_1(coroutine_type::self& self) + { + BEGIN + { + LLEventWithID pair = ::postAndWait2(self, + LLSD().insert("value", 18).insert("fail", LLSD()), + immediateAPI.getPump(), + "reply2", + "error2", + "reply", + "error"); + result = pair.first; + which = pair.second; + debug(STRINGIZE("result = " << result << ", which = " << which)); + } + END + } + + void coroPump(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPump waiter; + replyName = waiter.getName(); + result = waiter.wait(self); + } + END + } + + void coroPumpPost(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPump waiter; + result = waiter.postAndWait(self, LLSD().insert("value", 17), + immediateAPI.getPump(), "reply"); + } + END + } + + void coroPumps(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + replyName = waiter.getName0(); + errorName = waiter.getName1(); + LLEventWithID pair(waiter.wait(self)); + result = pair.first; + which = pair.second; + } + END + } + + void coroPumpsNoEx(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + replyName = waiter.getName0(); + errorName = waiter.getName1(); + result = waiter.waitWithException(self); + } + END + } + + void coroPumpsEx(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + replyName = waiter.getName0(); + errorName = waiter.getName1(); + try + { + result = waiter.waitWithException(self); + debug("no exception"); + } + catch (const LLErrorEvent& e) + { + debug(STRINGIZE("exception " << e.what())); + errordata = e.getData(); + } + } + END + } + + void coroPumpsNoLog(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + replyName = waiter.getName0(); + errorName = waiter.getName1(); + result = waiter.waitWithLog(self); + } + END + } + + void coroPumpsLog(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + replyName = waiter.getName0(); + errorName = waiter.getName1(); + WrapLL_ERRS capture; + try + { + result = waiter.waitWithLog(self); + debug("no exception"); + } + catch (const WrapLL_ERRS::FatalException& e) + { + debug(STRINGIZE("exception " << e.what())); + threw = e.what(); + } + } + END + } + + void coroPumpsPost(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + LLEventWithID pair(waiter.postAndWait(self, LLSD().insert("value", 23), + immediateAPI.getPump(), "reply", "error")); + result = pair.first; + which = pair.second; + } + END + } + + void coroPumpsPost_1(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + LLEventWithID pair( + waiter.postAndWait(self, LLSD().insert("value", 23).insert("fail", LLSD()), + immediateAPI.getPump(), "reply", "error")); + result = pair.first; + which = pair.second; + } + END + } + + void coroPumpsPostNoEx(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + result = waiter.postAndWaitWithException(self, LLSD().insert("value", 8), + immediateAPI.getPump(), "reply", "error"); + } + END + } + + void coroPumpsPostEx(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + try + { + result = waiter.postAndWaitWithException(self, + LLSD().insert("value", 9).insert("fail", LLSD()), + immediateAPI.getPump(), "reply", "error"); + debug("no exception"); + } + catch (const LLErrorEvent& e) + { + debug(STRINGIZE("exception " << e.what())); + errordata = e.getData(); + } + } + END + } + + void coroPumpsPostNoLog(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + result = waiter.postAndWaitWithLog(self, LLSD().insert("value", 30), + immediateAPI.getPump(), "reply", "error"); + } + END + } + + void coroPumpsPostLog(coroutine_type::self& self) + { + BEGIN + { + LLCoroEventPumps waiter; + WrapLL_ERRS capture; + try + { + result = waiter.postAndWaitWithLog(self, + LLSD().insert("value", 31).insert("fail", LLSD()), + immediateAPI.getPump(), "reply", "error"); + debug("no exception"); + } + catch (const WrapLL_ERRS::FatalException& e) + { + debug(STRINGIZE("exception " << e.what())); + threw = e.what(); + } + } + END + } + + void ensure_done(coroutine_type& coro) + { + ensure("coroutine complete", ! coro); + } + + ImmediateAPI immediateAPI; + std::string replyName, errorName, threw; + LLSD result, errordata; + int which; + }; + typedef test_group coroutine_group; + typedef coroutine_group::object object; + coroutine_group coroutinegrp("coroutine"); + + template<> template<> + void object::test<1>() + { + set_test_name("From banana.cpp example program in Boost.Coroutine distro"); + std::string buffer = "banananana"; + std::string match = "nana"; + std::string::iterator begin = buffer.begin(); + std::string::iterator end = buffer.end(); + +#if defined(BOOST_CORO_POSIX_IMPL) +// std::cout << "Using Boost.Coroutine " << BOOST_CORO_POSIX_IMPL << '\n'; +#else +// std::cout << "Using non-Posix Boost.Coroutine implementation" << std::endl; +#endif + + typedef std::string::iterator signature(std::string::iterator, + std::string::iterator, + std::string, + match_coroutine_type::self&); + + coroutine matcher + (boost::bind(static_cast(match_substring), + begin, + end, + match, + _1)); + + std::string::iterator i = matcher(); +/*==========================================================================*| + while(matcher && i != buffer.end()) { + std::cout <<"Match at: "<< std::distance(buffer.begin(), i)<<'\n'; + i = matcher(); + } +|*==========================================================================*/ + size_t matches[] = { 2, 4, 6 }; + for (size_t *mi(boost::begin(matches)), *mend(boost::end(matches)); + mi != mend; ++mi, i = matcher()) + { + ensure("more", matcher); + ensure("found", i != buffer.end()); + ensure_equals("value", std::distance(buffer.begin(), i), *mi); + } + ensure("done", ! matcher); + } + + template<> template<> + void object::test<2>() + { + set_test_name("explicit_wait"); + DEBUG; + + // Construct the coroutine instance that will run explicit_wait. + // Pass the ctor a callable that accepts the coroutine_type::self + // param passed by the library. + coroutine_type coro(boost::bind(&coroutine_data::explicit_wait, this, _1)); + // Start the coroutine + coro(std::nothrow); + // When the coroutine waits for the event pump, it returns here. + debug("about to send"); + // Satisfy the wait. + LLEventPumps::instance().obtain("source").post("received"); + // Now wait for the coroutine to complete. + ensure_done(coro); + // ensure the coroutine ran and woke up again with the intended result + ensure_equals(result.asString(), "received"); + } + + template<> template<> + void object::test<3>() + { + set_test_name("waitForEventOn1"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn1, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain("source").post("received"); + debug("back from send"); + ensure_done(coro); + ensure_equals(result.asString(), "received"); + } + + template<> template<> + void object::test<4>() + { + set_test_name("waitForEventOn2 reply"); + { + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain("reply").post("received"); + debug("back from send"); + ensure_done(coro); + } + ensure_equals(result.asString(), "received"); + ensure_equals("which pump", which, 0); + } + + template<> template<> + void object::test<5>() + { + set_test_name("waitForEventOn2 error"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain("error").post("badness"); + debug("back from send"); + ensure_done(coro); + ensure_equals(result.asString(), "badness"); + ensure_equals("which pump", which, 1); + } + + template<> template<> + void object::test<6>() + { + set_test_name("coroPump"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPump, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain(replyName).post("received"); + debug("back from send"); + ensure_done(coro); + ensure_equals(result.asString(), "received"); + } + + template<> template<> + void object::test<7>() + { + set_test_name("coroPumps reply"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain(replyName).post("received"); + debug("back from send"); + ensure_done(coro); + ensure_equals(result.asString(), "received"); + ensure_equals("which pump", which, 0); + } + + template<> template<> + void object::test<8>() + { + set_test_name("coroPumps error"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain(errorName).post("badness"); + debug("back from send"); + ensure_done(coro); + ensure_equals(result.asString(), "badness"); + ensure_equals("which pump", which, 1); + } + + template<> template<> + void object::test<9>() + { + set_test_name("coroPumpsNoEx"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoEx, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain(replyName).post("received"); + debug("back from send"); + ensure_done(coro); + ensure_equals(result.asString(), "received"); + } + + template<> template<> + void object::test<10>() + { + set_test_name("coroPumpsEx"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsEx, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain(errorName).post("badness"); + debug("back from send"); + ensure_done(coro); + ensure("no result", result.isUndefined()); + ensure_equals("got error", errordata.asString(), "badness"); + } + + template<> template<> + void object::test<11>() + { + set_test_name("coroPumpsNoLog"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoLog, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain(replyName).post("received"); + debug("back from send"); + ensure_done(coro); + ensure_equals(result.asString(), "received"); + } + + template<> template<> + void object::test<12>() + { + set_test_name("coroPumpsLog"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsLog, this, _1)); + coro(std::nothrow); + debug("about to send"); + LLEventPumps::instance().obtain(errorName).post("badness"); + debug("back from send"); + ensure_done(coro); + ensure("no result", result.isUndefined()); + ensure_contains("got error", threw, "badness"); + } + + template<> template<> + void object::test<13>() + { + set_test_name("postAndWait1"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::postAndWait1, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 18); + } + + template<> template<> + void object::test<14>() + { + set_test_name("postAndWait2"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::postAndWait2, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 19); + ensure_equals(which, 0); + } + + template<> template<> + void object::test<15>() + { + set_test_name("postAndWait2_1"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::postAndWait2_1, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 19); + ensure_equals(which, 1); + } + + template<> template<> + void object::test<16>() + { + set_test_name("coroPumpPost"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpPost, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 18); + } + + template<> template<> + void object::test<17>() + { + set_test_name("coroPumpsPost reply"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 24); + ensure_equals("which pump", which, 0); + } + + template<> template<> + void object::test<18>() + { + set_test_name("coroPumpsPost error"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost_1, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 24); + ensure_equals("which pump", which, 1); + } + + template<> template<> + void object::test<19>() + { + set_test_name("coroPumpsPostNoEx"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoEx, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 9); + } + + template<> template<> + void object::test<20>() + { + set_test_name("coroPumpsPostEx"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostEx, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure("no result", result.isUndefined()); + ensure_equals("got error", errordata.asInteger(), 10); + } + + template<> template<> + void object::test<21>() + { + set_test_name("coroPumpsPostNoLog"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoLog, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure_equals(result.asInteger(), 31); + } + + template<> template<> + void object::test<22>() + { + set_test_name("coroPumpsPostLog"); + DEBUG; + coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostLog, this, _1)); + coro(std::nothrow); + ensure_done(coro); + ensure("no result", result.isUndefined()); + ensure_contains("got error", threw, "32"); + } +} // namespace tut diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 388bf38d61..606f145d3b 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -292,10 +292,9 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) { // store off config state, as we might quit soon gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); + gSavedSkinSettings.saveToFile(gSavedSettings.getString("SkinningSettingsFile"), TRUE); std::ostringstream message; - - //*TODO:translate std::string msg; if (!auth_msg.empty()) { @@ -409,6 +408,7 @@ bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); query_map["channel"] = gSavedSettings.getString("VersionChannelName"); // *TODO constantize this guy + // *NOTE: This URL is also used in win_setup/lldownloader.cpp LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); if(LLAppViewer::sUpdaterInfo) @@ -495,9 +495,7 @@ bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ #elif LL_LINUX || LL_SOLARIS - OSMessageBox("Automatic updating is not yet implemented for Linux.\n" - "Please download the latest version from www.secondlife.com.", - LLStringUtil::null, OSMB_OK); + OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK); #endif // *REMOVE:Mani - Saving for reference... @@ -520,13 +518,9 @@ std::string construct_start_string() << LLURLSimString::sInstance.mZ); start = xml_escape_string(unescaped_start); } - else if (gSavedSettings.getBOOL("LoginLastLocation")) - { - start = "last"; - } else { - start = "home"; + start = gSavedSettings.getString("LoginLocation"); } return start; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4cf94b5bc4..eddc23b0c4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -55,7 +55,6 @@ #include "llviewercontrol.h" #include "lldir.h" #include "llerrorcontrol.h" -#include "llfiltersd2xmlrpc.h" #include "llfloaterreg.h" #include "llfocusmgr.h" #include "llhttpsender.h" @@ -102,7 +101,6 @@ #include "llfloaterhud.h" #include "llfloaterland.h" #include "llfloatertopobjects.h" -#include "llfloatertos.h" #include "llfloaterworldmap.h" #include "llgesturemgr.h" #include "llgroupmgr.h" @@ -114,6 +112,7 @@ #include "llinventoryview.h" #include "llkeyboard.h" #include "llloginhandler.h" // gLoginHandler, SLURL support +#include "lllogininstance.h" // Host the login module. #include "llpanellogin.h" #include "llprefsim.h" #include "llmutelist.h" @@ -134,7 +133,6 @@ #include "llsecondlifeurls.h" #include "llselectmgr.h" #include "llsky.h" -#include "llsrv.h" #include "llstatview.h" #include "lltrans.h" #include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance @@ -147,7 +145,6 @@ #include "llurlsimstring.h" #include "llurlhistory.h" #include "llurlwhitelist.h" -#include "lluserauth.h" #include "llvieweraudio.h" #include "llviewerassetstorage.h" #include "llviewercamera.h" @@ -188,6 +185,8 @@ #include "llwearable.h" #include "llinventorybridge.h" +#include "lllogin.h" + #if LL_LIBXUL_ENABLED #include "llmozlib.h" #endif // LL_LIBXUL_ENABLED @@ -201,12 +200,12 @@ // exported globals // bool gAgentMovementCompleted = false; -std::string gInitialOutfit; -std::string gInitialOutfitGender; std::string SCREEN_HOME_FILENAME = "screen_home.bmp"; std::string SCREEN_LAST_FILENAME = "screen_last.bmp"; +LLPointer gStartImageGL; + // // Imported globals // @@ -216,12 +215,6 @@ extern S32 gStartImageHeight; // // local globals // - -LLPointer gStartImageGL; - -static LLHost gAgentSimHost; -static BOOL gSkipOptionalUpdate = FALSE; - static bool gGotUseCircuitCodeAck = false; static std::string sInitialOutfit; static std::string sInitialOutfitGender; // "male" or "female" @@ -230,6 +223,17 @@ static bool gUseCircuitCallbackCalled = false; EStartupState LLStartUp::gStartupState = STATE_FIRST; +// *NOTE:Mani - to reconcile with giab changes... +static std::string gFirstname; +static std::string gLastname; +static std::string gPassword; + +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"; + // // local function declaration @@ -242,8 +246,6 @@ 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 update_app(BOOL mandatory, const std::string& message); -bool update_dialog_callback(const LLSD& notification, const LLSD& response); void login_packet_failed(void**, S32 result); void use_circuit_callback(void**, S32 result); void register_viewer_callbacks(LLMessageSystem* msg); @@ -253,6 +255,7 @@ void init_start_screen(S32 location_id); void release_start_screen(); void reset_login(); void apply_udp_blacklist(const std::string& csv); +bool process_login_success_response(); void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group) { @@ -309,9 +312,6 @@ void update_texture_fetch() gImageList.updateImages(0.10f); } -static std::vector sAuthUris; -static S32 sAuthUriNum = -1; - // Returns false to skip other idle processing. Should only return // true when all initialization done. bool idle_startup() @@ -330,23 +330,11 @@ bool idle_startup() // auth/transform loop will do. static F32 progress = 0.10f; - static std::string auth_method; static std::string auth_desc; static std::string auth_message; - static std::string firstname; - static std::string lastname; - static LLUUID web_login_key; - static std::string password; - static std::vector requested_options; - - static U64 first_sim_handle = 0; - static LLHost first_sim; - static std::string first_sim_seed_cap; static LLVector3 initial_sun_direction(1.f, 0.f, 0.f); static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server - static LLVector3 agent_start_look_at(1.0f, 0.f, 0.f); - static std::string agent_start_location = "safe"; // last location by default static S32 agent_location_id = START_LOCATION_ID_LAST; @@ -354,7 +342,7 @@ bool idle_startup() static bool show_connect_box = true; - static bool stipend_since_login = false; + //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 @@ -375,12 +363,7 @@ bool idle_startup() LLStringUtil::setLocale (LLTrans::getString(system)); - if (gNoRender) - { - // HACK, skip optional updates if you're running drones - gSkipOptionalUpdate = TRUE; - } - else + if (!gNoRender) { // Update images? gImageList.updateImages(0.01f); @@ -675,24 +658,23 @@ bool idle_startup() || !gLoginHandler.getWebLoginKey().isNull() ) { // We have at least some login information on a SLURL - firstname = gLoginHandler.getFirstName(); - lastname = gLoginHandler.getLastName(); - web_login_key = gLoginHandler.getWebLoginKey(); + gFirstname = gLoginHandler.getFirstName(); + gLastname = gLoginHandler.getLastName(); // Show the login screen if we don't have everything show_connect_box = - firstname.empty() || lastname.empty() || web_login_key.isNull(); + gFirstname.empty() || gLastname.empty(); } else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3) { LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); - firstname = cmd_line_login[0].asString(); - lastname = cmd_line_login[1].asString(); + gFirstname = cmd_line_login[0].asString(); + gLastname = cmd_line_login[1].asString(); LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); char md5pass[33]; /* Flawfinder: ignore */ pass.hex_digest(md5pass); - password = md5pass; + gPassword = md5pass; #ifdef USE_VIEWER_AUTH show_connect_box = true; @@ -703,9 +685,9 @@ bool idle_startup() } else if (gSavedSettings.getBOOL("AutoLogin")) { - firstname = gSavedSettings.getString("FirstName"); - lastname = gSavedSettings.getString("LastName"); - password = LLStartUp::loadPasswordFromDisk(); + gFirstname = gSavedSettings.getString("FirstName"); + gLastname = gSavedSettings.getString("LastName"); + gPassword = LLStartUp::loadPasswordFromDisk(); gSavedSettings.setBOOL("RememberPassword", TRUE); #ifdef USE_VIEWER_AUTH @@ -718,9 +700,9 @@ bool idle_startup() { // if not automatically logging in, display login dialog // a valid grid is selected - firstname = gSavedSettings.getString("FirstName"); - lastname = gSavedSettings.getString("LastName"); - password = LLStartUp::loadPasswordFromDisk(); + gFirstname = gSavedSettings.getString("FirstName"); + gLastname = gSavedSettings.getString("LastName"); + gPassword = LLStartUp::loadPasswordFromDisk(); show_connect_box = true; } @@ -757,7 +739,7 @@ bool idle_startup() // 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. - // LLPanelLogin::getFields(firstname, lastname, password); + // LLPanelLogin::getFields(gFirstname, gLastname, gPassword); if (gNoRender) { @@ -769,7 +751,7 @@ bool idle_startup() // Show the login dialog login_show(); // connect dialog is already shown, so fill in the names - LLPanelLogin::setFields( firstname, lastname, password); + LLPanelLogin::setFields( gFirstname, gLastname, gPassword); LLPanelLogin::giveFocus(); @@ -826,37 +808,29 @@ bool idle_startup() if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) { - //reset the values that could have come in from a slurl - if (!gLoginHandler.getWebLoginKey().isNull()) - { - firstname = gLoginHandler.getFirstName(); - lastname = gLoginHandler.getLastName(); - web_login_key = gLoginHandler.getWebLoginKey(); - } - if (show_connect_box) { // TODO if not use viewer auth // Load all the name information out of the login view - LLPanelLogin::getFields(&firstname, &lastname, &password); + LLPanelLogin::getFields(&gFirstname, &gLastname, &gPassword); // end TODO // HACK: Try to make not jump on login gKeyboard->resetKeys(); } - if (!firstname.empty() && !lastname.empty()) + if (!gFirstname.empty() && !gLastname.empty()) { - gSavedSettings.setString("FirstName", firstname); - gSavedSettings.setString("LastName", lastname); + gSavedSettings.setString("FirstName", gFirstname); + gSavedSettings.setString("LastName", gLastname); - LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL; - gDebugInfo["LoginName"] = firstname + " " + lastname; + LL_INFOS("AppInit") << "Attempting login as: " << gFirstname << " " << gLastname << LL_ENDL; + gDebugInfo["LoginName"] = gFirstname + " " + gLastname; } // create necessary directories // *FIX: these mkdir's should error check - gDirUtilp->setLindenUserDir(firstname, lastname); + gDirUtilp->setLindenUserDir(gFirstname, gLastname); LLFile::mkdir(gDirUtilp->getLindenUserDir()); // Set PerAccountSettingsFile to the default value. @@ -887,7 +861,7 @@ bool idle_startup() gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath")); } - gDirUtilp->setPerAccountChatLogsDir(firstname, lastname); + gDirUtilp->setPerAccountChatLogsDir(gFirstname, gLastname); LLFile::mkdir(gDirUtilp->getChatLogsDir()); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); @@ -908,13 +882,6 @@ bool idle_startup() if (show_connect_box) { - if ( LLPanelLogin::isGridComboDirty() ) - { - // User picked a grid from the popup, so clear the - // stored uris and they will be reacquired from the grid choice. - sAuthUris.clear(); - } - std::string location; LLPanelLogin::getLocation( location ); LLURLSimString::setString( location ); @@ -944,7 +911,7 @@ bool idle_startup() agent_location_id = START_LOCATION_ID_URL; // doesn't really matter what location_which is, since - // agent_start_look_at will be overwritten when the + // gAgentStartLookAt will be overwritten when the // UserLoginLocationReply arrives location_which = START_LOCATION_ID_LAST; } @@ -977,594 +944,115 @@ bool idle_startup() gVFS->pokeFiles(); - // skipping over STATE_UPDATE_CHECK because that just waits for input LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); return FALSE; } - if (STATE_UPDATE_CHECK == LLStartUp::getStartupState()) - { - // wait for user to give input via dialog box - return FALSE; - } - if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState()) { -//#define LL_MINIMIAL_REQUESTED_OPTIONS gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); - // *Note: this is where gUserAuth used to be created. - requested_options.clear(); - requested_options.push_back("inventory-root"); - requested_options.push_back("inventory-skeleton"); - //requested_options.push_back("inventory-meat"); - //requested_options.push_back("inventory-skel-targets"); -#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS) - if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary")) - { - requested_options.push_back("inventory-lib-root"); - requested_options.push_back("inventory-lib-owner"); - requested_options.push_back("inventory-skel-lib"); - // requested_options.push_back("inventory-meat-lib"); - } - - requested_options.push_back("initial-outfit"); - requested_options.push_back("gestures"); - requested_options.push_back("event_categories"); - requested_options.push_back("event_notifications"); - requested_options.push_back("classified_categories"); - //requested_options.push_back("inventory-targets"); - requested_options.push_back("buddy-list"); - requested_options.push_back("ui-config"); -#endif - requested_options.push_back("tutorial_setting"); - requested_options.push_back("login-flags"); - requested_options.push_back("global-textures"); - if(gSavedSettings.getBOOL("ConnectAsGod")) - { - gSavedSettings.setBOOL("UseDebugMenus", TRUE); - requested_options.push_back("god-connect"); - } - std::vector uris; - LLViewerLogin::getInstance()->getLoginURIs(uris); - std::vector::const_iterator iter, end; - for (iter = uris.begin(), end = uris.end(); iter != end; ++iter) - { - std::vector rewritten; - rewritten = LLSRV::rewriteURI(*iter); - sAuthUris.insert(sAuthUris.end(), - rewritten.begin(), rewritten.end()); - } - sAuthUriNum = 0; - auth_method = "login_to_simulator"; - + // Update progress status and the display loop. auth_desc = LLTrans::getString("LoginInProgress"); - LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - } - - if (STATE_LOGIN_AUTHENTICATE == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_LOGIN_AUTHENTICATE" << LL_ENDL; set_startup_status(progress, auth_desc, auth_message); progress += 0.02f; display_startup(); - - std::stringstream start; - if (LLURLSimString::parse()) - { - // a startup URL was specified - std::stringstream unescaped_start; - unescaped_start << "uri:" - << LLURLSimString::sInstance.mSimName << "&" - << LLURLSimString::sInstance.mX << "&" - << LLURLSimString::sInstance.mY << "&" - << LLURLSimString::sInstance.mZ; - start << xml_escape_string(unescaped_start.str()); - - } - else - { - start << gSavedSettings.getString("LoginLocation"); - } - - char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ - LLMD5 hashed_mac; - hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); - hashed_mac.finalize(); - hashed_mac.hex_digest(hashed_mac_string); - - // TODO if statement here to use web_login_key - sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1); - LLUserAuth::getInstance()->authenticate( - sAuthUris[sAuthUriNum], - auth_method, - firstname, - lastname, - password, // web_login_key, - start.str(), - gSkipOptionalUpdate, - gAcceptTOS, - gAcceptCriticalMessage, - gLastExecEvent, - requested_options, - hashed_mac_string, - LLAppViewer::instance()->getSerialNumber()); - - // reset globals - gAcceptTOS = FALSE; - gAcceptCriticalMessage = FALSE; - LLStartUp::setStartupState( STATE_LOGIN_NO_DATA_YET ); - return FALSE; - } - if(STATE_LOGIN_NO_DATA_YET == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_LOGIN_NO_DATA_YET" << LL_ENDL; - // 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); - // Process messages to keep from dropping circuit. - LLMessageSystem* msg = gMessageSystem; - while (msg->checkAllMessages(gFrameCount, gServicePump)) + // Setting initial values... + if(gNoRender) { + // HACK, skip optional updates if you're running drones + LLLoginInstance::getInstance()->setSkipOptionalUpdate(true); } - msg->processAcks(); - LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse(); - if(LLUserAuth::E_NO_RESPONSE_YET == error) - { - LL_DEBUGS("AppInit") << "waiting..." << LL_ENDL; - return FALSE; - } - LLStartUp::setStartupState( STATE_LOGIN_DOWNLOADING ); - progress += 0.01f; - set_startup_status(progress, auth_desc, auth_message); - return FALSE; - } - if(STATE_LOGIN_DOWNLOADING == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_LOGIN_DOWNLOADING" << LL_ENDL; - // Process messages to keep from dropping circuit. - LLMessageSystem* msg = gMessageSystem; - while (msg->checkAllMessages(gFrameCount, gServicePump)) - { - } - msg->processAcks(); - LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse(); - if(LLUserAuth::E_DOWNLOADING == error) - { - LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL; - return FALSE; - } + LLLoginInstance::getInstance()->setUserInteraction(show_connect_box); + + // This call to LLLoginInstance::connect() starts the + // authentication process. + LLSD credentials; + credentials["first"] = gFirstname; + credentials["last"] = gLastname; + credentials["passwd"] = gPassword; + LLLoginInstance::getInstance()->connect(credentials); + LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); - progress += 0.01f; - set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message); return FALSE; } - if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) + if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) { - LL_DEBUGS("AppInit") << "STATE_LOGIN_PROCESS_RESPONSE" << LL_ENDL; + bool transitionBackToLoginPanel = false; std::ostringstream emsg; - bool quit = false; - bool update = false; - std::string login_response; - std::string reason_response; - std::string message_response; - bool successful_login = false; - LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse(); - // reset globals - gAcceptTOS = FALSE; - gAcceptCriticalMessage = FALSE; - switch(error) - { - case LLUserAuth::E_OK: - login_response = LLUserAuth::getInstance()->getResponse("login"); - if(login_response == "true") - { - // Yay, login! - successful_login = true; - } - else if(login_response == "indeterminate") + if(LLLoginInstance::getInstance()->authFailure()) + { + // Still have error conditions that may need some + // sort of handling. + emsg << "Login failed.\n"; + std::string reason_response = LLLoginInstance::getInstance()->getResponse("reason"); + std::string message_response = LLLoginInstance::getInstance()->getResponse("message"); + + if(!message_response.empty()) { - LL_INFOS("AppInit") << "Indeterminate login..." << LL_ENDL; - sAuthUris = LLSRV::rewriteURI(LLUserAuth::getInstance()->getResponse("next_url")); - sAuthUriNum = 0; - auth_method = LLUserAuth::getInstance()->getResponse("next_method"); - auth_message = LLUserAuth::getInstance()->getResponse("message"); - if(auth_method.substr(0, 5) == "login") + // XUI: fix translation for strings returned during login + // We need a generic table for translations + std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ]; + if ( big_reason.size() == 0 ) { - auth_desc.assign(LLTrans::getString("LoginAuthenticating")); + emsg << message_response; } else { - auth_desc.assign(LLTrans::getString("LoginMaintenance")); - } - // ignoring the duration & options array for now. - // Go back to authenticate. - LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - return FALSE; - } - else - { - emsg << "Login failed.\n"; - reason_response = LLUserAuth::getInstance()->getResponse("reason"); - message_response = LLUserAuth::getInstance()->getResponse("message"); - - if (!message_response.empty()) - { - // XUI: fix translation for strings returned during login - // We need a generic table for translations - std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ]; - if ( big_reason.size() == 0 ) - { - emsg << message_response; - } - else - { - emsg << big_reason; - } - } - - if(reason_response == "tos") - { - if (show_connect_box) - { - LL_DEBUGS("AppInit") << "Need tos agreement" << LL_ENDL; - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, - message_response); - tos_dialog->startModal(); - // LLFloaterTOS deletes itself. - return false; - } - else - { - quit = true; - } - } - if(reason_response == "critical") - { - if (show_connect_box) - { - LL_DEBUGS("AppInit") << "Need critical message" << LL_ENDL; - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, - message_response); - tos_dialog->startModal(); - // LLFloaterTOS deletes itself. - return false; - } - else - { - quit = true; - } - } - if(reason_response == "key") - { - // Couldn't login because user/password is wrong - // Clear the password - password = ""; - } - if(reason_response == "update") - { - auth_message = LLUserAuth::getInstance()->getResponse("message"); - update = true; - } - if(reason_response == "optional") - { - LL_DEBUGS("AppInit") << "Login got optional update" << LL_ENDL; - auth_message = LLUserAuth::getInstance()->getResponse("message"); - if (show_connect_box) - { - update_app(FALSE, auth_message); - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - gSkipOptionalUpdate = TRUE; - return false; - } + emsg << big_reason; } } - break; - case LLUserAuth::E_COULDNT_RESOLVE_HOST: - case LLUserAuth::E_SSL_PEER_CERTIFICATE: - case LLUserAuth::E_UNHANDLED_ERROR: - case LLUserAuth::E_SSL_CACERT: - case LLUserAuth::E_SSL_CONNECT_ERROR: - default: - if (sAuthUriNum >= (int) sAuthUris.size() - 1) - { - emsg << "Unable to connect to " << LLAppViewer::instance()->getSecondLifeTitle() << ".\n"; - emsg << LLUserAuth::getInstance()->errorMessage(); - } else { - sAuthUriNum++; - std::ostringstream s; - LLStringUtil::format_map_t args; - args["[NUMBER]"] = llformat("%d", sAuthUriNum + 1); - auth_desc = LLTrans::getString("LoginAttempt", args); - LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - return FALSE; - } - break; - } - - if (update || gSavedSettings.getBOOL("ForceMandatoryUpdate")) - { - gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE); - update_app(TRUE, auth_message); - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - return false; - } - - // Version update and we're not showing the dialog - if(quit) - { - LLUserAuth::getInstance()->reset(); - LLAppViewer::instance()->forceQuit(); - return false; - } - if(successful_login) - { - std::string text; - text = LLUserAuth::getInstance()->getResponse("udp_blacklist"); - if(!text.empty()) - { - apply_udp_blacklist(text); - } - - // unpack login data needed by the application - text = LLUserAuth::getInstance()->getResponse("agent_id"); - if(!text.empty()) gAgentID.set(text); - gDebugInfo["AgentID"] = text; - - text = LLUserAuth::getInstance()->getResponse("session_id"); - if(!text.empty()) gAgentSessionID.set(text); - gDebugInfo["SessionID"] = text; - - text = LLUserAuth::getInstance()->getResponse("secure_session_id"); - if(!text.empty()) gAgent.mSecureSessionID.set(text); - - text = LLUserAuth::getInstance()->getResponse("first_name"); - if(!text.empty()) + if(reason_response == "key") { - // Remove quotes from string. Login.cgi sends these to force - // names that look like numbers into strings. - firstname.assign(text); - LLStringUtil::replaceChar(firstname, '"', ' '); - LLStringUtil::trim(firstname); + // Couldn't login because user/password is wrong + // Clear the password + gPassword = ""; } - text = LLUserAuth::getInstance()->getResponse("last_name"); - if(!text.empty()) lastname.assign(text); - gSavedSettings.setString("FirstName", firstname); - gSavedSettings.setString("LastName", lastname); - if (gSavedSettings.getBOOL("RememberPassword")) + if(reason_response == "update" + || reason_response == "optional") { - // Successful login means the password is valid, so save it. - LLStartUp::savePasswordToDisk(password); + // In the case of a needed update, quit. + // Its either downloading or declined. + // If optional was skipped this case shouldn't + // be reached. + LLLoginInstance::getInstance()->disconnect(); + LLAppViewer::instance()->forceQuit(); } else { - // Don't leave password from previous session sitting around - // during this login session. - LLStartUp::deletePasswordFromDisk(); - } - - // this is their actual ability to access content - text = LLUserAuth::getInstance()->getResponse("agent_access_max"); - 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 = LLUserAuth::getInstance()->getResponse("agent_region_access"); - if (!text.empty()) - { - int preferredMaturity = LLAgent::convertTextToMaturity(text[0]); - gSavedSettings.setU32("PreferredMaturity", preferredMaturity); - } - // During the AO transition, this flag will be true. Then the flag will - // go away. After the AO transition, this code and all the code that - // uses it can be deleted. - text = LLUserAuth::getInstance()->getResponse("ao_transition"); - if (!text.empty()) - { - if (text == "1") - { - gAgent.setAOTransition(); - } - } - - text = LLUserAuth::getInstance()->getResponse("start_location"); - if(!text.empty()) agent_start_location.assign(text); - text = LLUserAuth::getInstance()->getResponse("circuit_code"); - if(!text.empty()) - { - gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10); - } - std::string sim_ip_str = LLUserAuth::getInstance()->getResponse("sim_ip"); - std::string sim_port_str = LLUserAuth::getInstance()->getResponse("sim_port"); - if(!sim_ip_str.empty() && !sim_port_str.empty()) - { - U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); - first_sim.set(sim_ip_str, sim_port); - if (first_sim.isOk()) - { - gMessageSystem->enableCircuit(first_sim, TRUE); - } - } - std::string region_x_str = LLUserAuth::getInstance()->getResponse("region_x"); - std::string region_y_str = LLUserAuth::getInstance()->getResponse("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); - first_sim_handle = to_region_handle(region_x, region_y); - } - - const std::string look_at_str = LLUserAuth::getInstance()->getResponse("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); - agent_start_look_at = ll_vector3_from_sd(sd); - } - - text = LLUserAuth::getInstance()->getResponse("seed_capability"); - if (!text.empty()) first_sim_seed_cap = text; - - text = LLUserAuth::getInstance()->getResponse("seconds_since_epoch"); - 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); - } - } - - std::string home_location = LLUserAuth::getInstance()->getResponse("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(LLUserAuth::getInstance()->getResponse("message")); - LLUserAuth::options_t options; - if(LLUserAuth::getInstance()->getOptions("inventory-root", options)) - { - LLUserAuth::response_t::iterator it; - it = options[0].find("folder_id"); - if(it != options[0].end()) - { - gAgent.mInventoryRootID.set((*it).second); - //gInventory.mock(gAgent.getInventoryRootID()); - } - } - - options.clear(); - if(LLUserAuth::getInstance()->getOptions("login-flags", options)) - { - LLUserAuth::response_t::iterator it; - LLUserAuth::response_t::iterator no_flag = options[0].end(); - it = options[0].find("ever_logged_in"); - if(it != no_flag) - { - if((*it).second == "N") gAgent.setFirstLogin(TRUE); - else gAgent.setFirstLogin(FALSE); - } - it = options[0].find("stipend_since_login"); - if(it != no_flag) - { - if((*it).second == "Y") stipend_since_login = true; - } - it = options[0].find("gendered"); - if(it != no_flag) - { - if((*it).second == "Y") gAgent.setGenderChosen(TRUE); - } - it = options[0].find("daylight_savings"); - if(it != no_flag) - { - if((*it).second == "Y") gPacificDaylightTime = TRUE; - else gPacificDaylightTime = FALSE; - } - - //setup map of datetime strings to codes and slt & local time offset from utc - LLStringOps::setupDatetimeInfo (gPacificDaylightTime); + transitionBackToLoginPanel = true; } - options.clear(); - if (LLUserAuth::getInstance()->getOptions("initial-outfit", options) - && !options.empty()) - { - LLUserAuth::response_t::iterator it; - LLUserAuth::response_t::iterator it_end = options[0].end(); - it = options[0].find("folder_name"); - if(it != it_end) - { - // Initial outfit is a folder in your inventory, - // must be an exact folder-name match. - sInitialOutfit = (*it).second; - } - it = options[0].find("gender"); - if (it != it_end) - { - sInitialOutfitGender = (*it).second; - } - } - - options.clear(); - if(LLUserAuth::getInstance()->getOptions("global-textures", options)) - { - // Extract sun and moon texture IDs. These are used - // in the LLVOSky constructor, but I can't figure out - // how to pass them in. JC - LLUserAuth::response_t::iterator it; - LLUserAuth::response_t::iterator no_texture = options[0].end(); - it = options[0].find("sun_texture_id"); - if(it != no_texture) - { - gSunTextureID.set((*it).second); - } - it = options[0].find("moon_texture_id"); - if(it != no_texture) - { - gMoonTextureID.set((*it).second); - } - it = options[0].find("cloud_texture_id"); - if(it != no_texture) - { - gCloudTextureID.set((*it).second); - } - } - - - // JC: gesture loading done below, when we have an asset system - // in place. Don't delete/clear user_credentials until then. - - if(gAgentID.notNull() - && gAgentSessionID.notNull() - && gMessageSystem->mOurCircuitCode - && first_sim.isOk() - && gAgent.mInventoryRootID.notNull()) + } + else if(LLLoginInstance::getInstance()->authSuccess()) + { + if(process_login_success_response()) { - LLStartUp::setStartupState( STATE_WORLD_INIT ); + // Pass the user information to the voice chat server interface. + gVoiceClient->userAuthorized(gFirstname, gLastname, gAgentID); + LLStartUp::setStartupState( STATE_WORLD_INIT); } else { - if (gNoRender) - { - LL_WARNS("AppInit") << "Bad login - missing return values" << LL_ENDL; - LL_WARNS("AppInit") << emsg << LL_ENDL; - exit(0); - } - // Bounce back to the login screen. - LLSD args; - args["ERROR_MESSAGE"] = emsg.str(); - LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done); - reset_login(); - gSavedSettings.setBOOL("AutoLogin", FALSE); - show_connect_box = true; + transitionBackToLoginPanel = false; } - - // Pass the user information to the voice chat server interface. - gVoiceClient->userAuthorized(firstname, lastname, gAgentID); } - else // if(successful_login) + else + { + // Still waiting for response. + // *TODO:Mani - Actually check for login progress. + // 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); + } + + if(transitionBackToLoginPanel) { if (gNoRender) { @@ -1572,11 +1060,12 @@ bool idle_startup() LL_WARNS("AppInit") << emsg << LL_ENDL; exit(0); } + // Bounce back to the login screen. LLSD args; args["ERROR_MESSAGE"] = emsg.str(); LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done); - reset_login(); + reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); gSavedSettings.setBOOL("AutoLogin", FALSE); show_connect_box = true; } @@ -1640,14 +1129,14 @@ bool idle_startup() // This is necessary because creating objects before this is set will result in a // bad mPositionAgent cache. - gAgent.initOriginGlobal(from_region_handle(first_sim_handle)); + gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); - LLWorld::getInstance()->addRegion(first_sim_handle, first_sim); + LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(first_sim_handle); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; - regionp->setSeedCapability(first_sim_seed_cap); + regionp->setSeedCapability(gFirstSimSeedCap); LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; // Set agent's initial region to be the one we just created. @@ -1818,7 +1307,7 @@ bool idle_startup() // the coordinates handed to us to fit in the local region. gAgent.setPositionAgent(agent_start_position_region); - gAgent.resetAxes(agent_start_look_at); + gAgent.resetAxes(gAgentStartLookAt); gAgent.stopCameraAnimation(); gAgent.resetCamera(); @@ -1857,18 +1346,18 @@ bool idle_startup() LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL; } - gUseCircuitCallbackCalled = FALSE; + gUseCircuitCallbackCalled = false; - msg->enableCircuit(first_sim, TRUE); + msg->enableCircuit(gFirstSim, TRUE); // now, use the circuit info to tell simulator about us! - LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << LL_ENDL; + 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( - first_sim, + gFirstSim, MAX_TIMEOUT_COUNT, FALSE, TIMEOUT_SECONDS, @@ -1979,122 +1468,113 @@ bool idle_startup() LLAgentLanguage::update(); // unpack thin inventory - LLUserAuth::options_t options; - options.clear(); + LLSD response = LLLoginInstance::getInstance()->getResponse(); //bool dump_buffer = false; - - if(LLUserAuth::getInstance()->getOptions("inventory-lib-root", options) - && !options.empty()) + + LLSD inv_lib_root = response["inventory-lib-root"]; + if(inv_lib_root.isDefined()) { // should only be one - LLUserAuth::response_t::iterator it; - it = options[0].find("folder_id"); - if(it != options[0].end()) + LLSD id = inv_lib_root[0]["folder_id"]; + if(id.isDefined()) { - gInventoryLibraryRoot.set((*it).second); + gInventoryLibraryRoot = id.asUUID(); } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("inventory-lib-owner", options) - && !options.empty()) + + LLSD inv_lib_owner = response["inventory-lib-owner"]; + if(inv_lib_owner.isDefined()) { // should only be one - LLUserAuth::response_t::iterator it; - it = options[0].find("agent_id"); - if(it != options[0].end()) + LLSD id = inv_lib_owner[0]["agent_id"]; + if(id.isDefined()) { - gInventoryLibraryOwner.set((*it).second); + gInventoryLibraryOwner = id.asUUID(); } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("inventory-skel-lib", options) - && gInventoryLibraryOwner.notNull()) + + LLSD inv_skel_lib = response["inventory-skel-lib"]; + if(inv_skel_lib.isDefined() && gInventoryLibraryOwner.notNull()) { - if(!gInventory.loadSkeleton(options, gInventoryLibraryOwner)) + if(!gInventory.loadSkeleton(inv_skel_lib, gInventoryLibraryOwner)) { LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("inventory-skeleton", options)) + + LLSD inv_skeleton = response["inventory-skeleton"]; + if(inv_skeleton.isDefined()) { - if(!gInventory.loadSkeleton(options, gAgent.getID())) + if(!gInventory.loadSkeleton(inv_skeleton, gAgent.getID())) { LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL; } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("buddy-list", options)) + LLSD buddy_list = response["buddy-list"]; + if(buddy_list.isDefined()) { - LLUserAuth::options_t::iterator it = options.begin(); - LLUserAuth::options_t::iterator end = options.end(); LLAvatarTracker::buddy_map_t list; LLUUID agent_id; S32 has_rights = 0, given_rights = 0; - for (; it != end; ++it) + for(LLSD::array_const_iterator it = buddy_list.beginArray(), + end = buddy_list.endArray(); it != end; ++it) { - LLUserAuth::response_t::const_iterator option_it; - option_it = (*it).find("buddy_id"); - if(option_it != (*it).end()) + LLSD buddy_id = (*it)["buddy_id"]; + if(buddy_id.isDefined()) { - agent_id.set((*option_it).second); + agent_id = buddy_id.asUUID(); } - option_it = (*it).find("buddy_rights_has"); - if(option_it != (*it).end()) + + LLSD buddy_rights_has = (*it)["buddy_rights_has"]; + if(buddy_rights_has.isDefined()) { - has_rights = atoi((*option_it).second.c_str()); + has_rights = buddy_rights_has.asInteger(); } - option_it = (*it).find("buddy_rights_given"); - if(option_it != (*it).end()) + + LLSD buddy_rights_given = (*it)["buddy_rights_given"]; + if(buddy_rights_given.isDefined()) { - given_rights = atoi((*option_it).second.c_str()); + given_rights = buddy_rights_given.asInteger(); } + list[agent_id] = new LLRelationship(given_rights, has_rights, false); } LLAvatarTracker::instance().addBuddyList(list); } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("ui-config", options)) + LLSD ui_config = response["ui-config"]; + if(ui_config.isDefined()) { - LLUserAuth::options_t::iterator it = options.begin(); - LLUserAuth::options_t::iterator end = options.end(); - for (; it != end; ++it) + for(LLSD::array_const_iterator it = ui_config.beginArray(), + end = ui_config.endArray(); it != end; ++it) { - LLUserAuth::response_t::const_iterator option_it; - option_it = (*it).find("allow_first_life"); - if(option_it != (*it).end()) + LLSD allow_first_life = (*it)["allow_first_life"]; + if(allow_first_life.asString() == "Y") { - if (option_it->second == "Y") - { - LLPanelAvatar::sAllowFirstLife = TRUE; - } + LLPanelAvatar::sAllowFirstLife = TRUE; } } } - options.clear(); + bool show_hud = false; - if(LLUserAuth::getInstance()->getOptions("tutorial_setting", options)) + LLSD tutorial_setting = response["tutorial_setting"]; + if(tutorial_setting.isDefined()) { - LLUserAuth::options_t::iterator it = options.begin(); - LLUserAuth::options_t::iterator end = options.end(); - for (; it != end; ++it) + for(LLSD::array_const_iterator it = tutorial_setting.beginArray(), + end = tutorial_setting.endArray(); it != end; ++it) { - LLUserAuth::response_t::const_iterator option_it; - option_it = (*it).find("tutorial_url"); - if(option_it != (*it).end()) + LLSD tutorial_url = (*it)["tutorial_url"]; + if(tutorial_url.isDefined()) { // Tutorial floater will append language code - gSavedSettings.setString("TutorialURL", option_it->second); + gSavedSettings.setString("TutorialURL", tutorial_url.asString()); } - option_it = (*it).find("use_tutorial"); - if(option_it != (*it).end()) + + LLSD use_tutorial = (*it)["use_tutorial"]; + if(use_tutorial.asString() == "true") { - if (option_it->second == "true") - { - show_hud = true; - } + show_hud = true; } } } @@ -2107,19 +1587,22 @@ bool idle_startup() LLFloaterHUD::showHUD(); } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("event_categories", options)) + LLSD event_categories = response["event_categories"]; + if(event_categories.isDefined()) { - LLEventInfo::loadCategories(options); + LLEventInfo::loadCategories(event_categories); } - if(LLUserAuth::getInstance()->getOptions("event_notifications", options)) + + LLSD event_notifications = response["event_notifications"]; + if(event_notifications.isDefined()) { - gEventNotifier.load(options); + gEventNotifier.load(event_notifications); } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("classified_categories", options)) + + LLSD classified_categories = response["classified_categories"]; + if(classified_categories.isDefined()) { - LLClassifiedInfo::loadCategories(options); + LLClassifiedInfo::loadCategories(classified_categories); } @@ -2176,7 +1659,7 @@ bool idle_startup() // 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 = LLUserAuth::getInstance()->getLastTransferRateBPS(); + 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(); @@ -2223,34 +1706,20 @@ bool idle_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. - LLUserAuth::options_t gesture_options; - if (LLUserAuth::getInstance()->getOptions("gestures", gesture_options)) + LLSD gesture_options + = LLLoginInstance::getInstance()->getResponse("gestures"); + if (gesture_options.isDefined()) { LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size() << LL_ENDL; std::vector item_ids; - LLUserAuth::options_t::iterator resp_it; - for (resp_it = gesture_options.begin(); - resp_it != gesture_options.end(); - ++resp_it) + for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(), + end = gesture_options.endArray(); resp_it != end; ++resp_it) { - const LLUserAuth::response_t& response = *resp_it; - LLUUID item_id; - LLUUID asset_id; - LLUserAuth::response_t::const_iterator option_it; - - option_it = response.find("item_id"); - if (option_it != response.end()) - { - const std::string& uuid_string = (*option_it).second; - item_id.set(uuid_string); - } - option_it = response.find("asset_id"); - if (option_it != response.end()) - { - const std::string& uuid_string = (*option_it).second; - asset_id.set(uuid_string); - } + // 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()) { @@ -2306,8 +1775,8 @@ bool idle_startup() if (!gAgent.isFirstLogin()) { bool url_ok = LLURLSimString::sInstance.parse(); - if ((url_ok && agent_start_location == "url") || - (!url_ok && ((agent_start_location == gSavedSettings.getString("LoginLocation"))))) + if ((url_ok && gAgentStartLocation == "url") || + (!url_ok && ((gAgentStartLocation == gSavedSettings.getString("LoginLocation"))))) { // Start location is OK // Disabled code to restore camera location and focus if logging in to default location @@ -2518,8 +1987,10 @@ bool idle_startup() // 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(); + // LLUserAuth::getInstance()->reset(); LLStartUp::setStartupState( STATE_STARTED ); @@ -2804,194 +2275,6 @@ bool login_alert_status(const LLSD& notification, const LLSD& response) return false; } -void update_app(BOOL mandatory, const std::string& auth_msg) -{ - // store off config state, as we might quit soon - gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - gSavedSkinSettings.saveToFile(gSavedSettings.getString("SkinningSettingsFile"), TRUE); - std::ostringstream message; - - std::string msg; - if (!auth_msg.empty()) - { - msg = "("+ auth_msg + ") \n"; - } - - LLSD args; - args["MESSAGE"] = msg; - - LLSD payload; - payload["mandatory"] = mandatory; - -/* - We're constructing one of the following 6 strings here: - "DownloadWindowsMandatory" - "DownloadWindowsReleaseForDownload" - "DownloadWindows" - "DownloadMacMandatory" - "DownloadMacReleaseForDownload" - "DownloadMac" - - I've called them out explicitly in this comment so that they can be grepped for. - - Also, we assume that if we're not Windows we're Mac. If we ever intend to support - Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but - we'd rather deliver the wrong message than no message, so until Linux is supported - we'll leave it alone. - */ - std::string notification_name = "Download"; - -#if LL_WINDOWS - notification_name += "Windows"; -#else - notification_name += "Mac"; -#endif - - if (mandatory) - { - notification_name += "Mandatory"; - } - else - { -#if LL_RELEASE_FOR_DOWNLOAD - notification_name += "ReleaseForDownload"; -#endif - } - - LLNotifications::instance().add(notification_name, args, payload, update_dialog_callback); - -} - -bool update_dialog_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - std::string update_exe_path; - bool mandatory = notification["payload"]["mandatory"].asBoolean(); - -#if !LL_RELEASE_FOR_DOWNLOAD - if (option == 2) - { - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); - return false; - } -#endif - - if (option == 1) - { - // ...user doesn't want to do it - if (mandatory) - { - LLAppViewer::instance()->forceQuit(); - // Bump them back to the login screen. - //reset_login(); - } - else - { - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); - } - return false; - } - - LLSD query_map = LLSD::emptyMap(); - // *TODO place os string in a global constant -#if LL_WINDOWS - query_map["os"] = "win"; -#elif LL_DARWIN - query_map["os"] = "mac"; -#elif LL_LINUX - query_map["os"] = "lnx"; -#elif LL_SOLARIS - query_map["os"] = "sol"; -#endif - // *TODO change userserver to be grid on both viewer and sim, since - // userserver no longer exists. - query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); - query_map["channel"] = gSavedSettings.getString("VersionChannelName"); - // *TODO constantize this guy - // *NOTE: This URL is also used in win_setup/lldownloader.cpp - LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); - - if(LLAppViewer::sUpdaterInfo) - { - delete LLAppViewer::sUpdaterInfo ; - } - LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; - -#if LL_WINDOWS - LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); - if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) - { - delete LLAppViewer::sUpdaterInfo ; - LLAppViewer::sUpdaterInfo = NULL ; - - // We're hosed, bail - LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); - return false; - } - - LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe"; - - std::string updater_source = gDirUtilp->getAppRODataDir(); - updater_source += gDirUtilp->getDirDelimiter(); - updater_source += "updater.exe"; - - LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source - << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath - << LL_ENDL; - - - if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE)) - { - delete LLAppViewer::sUpdaterInfo ; - LLAppViewer::sUpdaterInfo = NULL ; - - LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); - return false; - } - - // if a sim name was passed in via command line parameter (typically through a SLURL) - if ( LLURLSimString::sInstance.mSimString.length() ) - { - // record the location to start at next time - gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); - }; - - LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; - - LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; - - //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird. - LLAppViewer::instance()->removeMarkerFile(); // In case updater fails - -#elif LL_DARWIN - // if a sim name was passed in via command line parameter (typically through a SLURL) - if ( LLURLSimString::sInstance.mSimString.length() ) - { - // record the location to start at next time - gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); - }; - - LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; - LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; - LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; - LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; - - LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; - - // Run the auto-updater. - system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ - -#elif LL_LINUX || LL_SOLARIS - OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK); -#endif - LLAppViewer::instance()->forceQuit(); - return false; -} void use_circuit_callback(void**, S32 result) { @@ -3348,11 +2631,7 @@ std::string LLStartUp::startupStateToString(EStartupState state) RTNENUM( STATE_LOGIN_SHOW ); RTNENUM( STATE_LOGIN_WAIT ); RTNENUM( STATE_LOGIN_CLEANUP ); - RTNENUM( STATE_UPDATE_CHECK ); RTNENUM( STATE_LOGIN_AUTH_INIT ); - RTNENUM( STATE_LOGIN_AUTHENTICATE ); - RTNENUM( STATE_LOGIN_NO_DATA_YET ); - RTNENUM( STATE_LOGIN_DOWNLOADING ); RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); RTNENUM( STATE_WORLD_INIT ); RTNENUM( STATE_SEED_GRANTED_WAIT ); @@ -3493,3 +2772,252 @@ void apply_udp_blacklist(const std::string& csv) } +bool process_login_success_response() +{ + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + 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; + + text = response["session_id"].asString(); + if(!text.empty()) gAgentSessionID.set(text); + gDebugInfo["SessionID"] = text; + + text = response["secure_session_id"].asString(); + if(!text.empty()) gAgent.mSecureSessionID.set(text); + + text = response["first_name"].asString(); + if(!text.empty()) + { + // Remove quotes from string. Login.cgi sends these to force + // names that look like numbers into strings. + gFirstname.assign(text); + LLStringUtil::replaceChar(gFirstname, '"', ' '); + LLStringUtil::trim(gFirstname); + } + text = response["last_name"].asString(); + if(!text.empty()) + { + gLastname.assign(text); + } + gSavedSettings.setString("FirstName", gFirstname); + gSavedSettings.setString("LastName", gLastname); + + if (gSavedSettings.getBOOL("RememberPassword")) + { + // Successful login means the password is valid, so save it. + LLStartUp::savePasswordToDisk(gPassword); + } + else + { + // Don't leave password from previous session sitting around + // during this login session. + LLStartUp::deletePasswordFromDisk(); + } + + // 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()) + { + int preferredMaturity = LLAgent::convertTextToMaturity(text[0]); + gSavedSettings.setU32("PreferredMaturity", preferredMaturity); + } + // During the AO transition, this flag will be true. Then the flag will + // go away. After the AO transition, this code and all the code that + // uses it can be deleted. + text = response["ao_transition"].asString(); + if (!text.empty()) + { + if (text == "1") + { + gAgent.setAOTransition(); + } + } + + 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); + } + } + + 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()) + { + gAgent.mInventoryRootID = 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") ? TRUE : FALSE); + } + + /* 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") + { + gAgent.setGenderChosen(TRUE); + } + + flag = login_flags["daylight_savings"].asString(); + if(flag == "Y") + { + gPacificDaylightTime = (flag == "Y") ? TRUE : FALSE; + } + + //setup map of datetime strings to codes and slt & local time offset from utc + LLStringOps::setupDatetimeInfo (gPacificDaylightTime); + } + + 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; + } + } + + LLSD global_textures = response["global-textures"][0]; + if(global_textures.size()) + { + // Extract sun and moon texture IDs. These are used + // in the LLVOSky constructor, but I can't figure out + // how to pass them in. JC + LLUUID id = global_textures["sun_texture_id"]; + if(id.notNull()) + { + gSunTextureID = id; + } + + id = global_textures["moon_texture_id"]; + if(id.notNull()) + { + gMoonTextureID = id; + } + + id = global_textures["cloud_texture_id"]; + if(id.notNull()) + { + gCloudTextureID = id; + } + } + + + bool success = false; + // JC: gesture loading done below, when we have an asset system + // in place. Don't delete/clear user_credentials until then. + if(gAgentID.notNull() + && gAgentSessionID.notNull() + && gMessageSystem->mOurCircuitCode + && gFirstSim.isOk() + && gAgent.mInventoryRootID.notNull()) + { + success = true; + } + + return success; +} diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp index 0c1ee42ffc..c94ba0a3e8 100644 --- a/indra/newview/tests/llxmlrpclistener_test.cpp +++ b/indra/newview/tests/llxmlrpclistener_test.cpp @@ -26,7 +26,7 @@ #include "llcontrol.h" #include "tests/wrapllerrs.h" -LLControlGroup gSavedSettings; +LLControlGroup gSavedSettings("Global"); /***************************************************************************** * TUT -- cgit v1.3 From d4330d33964bb5888b5f1eb3ec389b03dadd826d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 23 Jun 2009 20:20:01 +0000 Subject: QAR-1619: fix Linux-only missing #include (Linux-only reference to LLTrans) --- indra/newview/lllogininstance.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 606f145d3b..22497ed291 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -52,6 +52,9 @@ #include "llurlsimstring.h" #include "llfloatertos.h" #include "llwindow.h" +#if LL_LINUX || LL_SOLARIS +#include "lltrans.h" +#endif std::string construct_start_string(); -- cgit v1.3 From db7f15df68cda2850c3d8a7ffcc59fc136de6f95 Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Wed, 22 Jul 2009 14:53:55 -0700 Subject: Adding LLLoginInstance unit test --- indra/llui/llnotificationslistener.cpp | 29 +++++- indra/llui/llnotificationslistener.h | 5 +- indra/newview/CMakeLists.txt | 1 + indra/newview/llappviewer.cpp | 110 +++++++++++++++++++- indra/newview/llappviewer.h | 4 +- indra/newview/llfloatertos.cpp | 2 + indra/newview/lllogininstance.cpp | 183 ++++++++++----------------------- indra/newview/lllogininstance.h | 33 ++++-- indra/newview/llpanellogin.cpp | 3 +- indra/newview/llstartup.cpp | 10 +- indra/newview/llviewermenu.cpp | 2 +- 11 files changed, 230 insertions(+), 152 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index d6e552ca5c..6ebbee68ac 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -24,5 +24,32 @@ LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications void LLNotificationsListener::requestAdd(const LLSD& event_data) const { - mNotifications.add(event_data["name"], event_data["substitutions"], event_data["payload"]); + if(event_data.has("reply")) + { + mNotifications.add(event_data["name"], + event_data["substitutions"], + event_data["payload"], + boost::bind(&LLNotificationListener::Responder, + this, + event_data["reply"].asString(), + _1, _2 + ) + ); + } + else + { + mNotifications.add(event_data["name"], + event_data["substitutions"], + event_data["payload"]); + } +} + +void LLNotificationsListener::Responder(const std::string& reply_pump, + const LLSD& notification, + const LLSD& response) +{ + LLSD reponse_event; + reponse_event["notification"] = notification; + reponse_event["response"] = response; + mEventPumps.obtain(reply_pump).post(reponse_event); } diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index 3576cacbdb..d11aed1b52 100644 --- a/indra/llui/llnotificationslistener.h +++ b/indra/llui/llnotificationslistener.h @@ -25,7 +25,10 @@ public: void requestAdd(LLSD const & event_data) const; private: - LLNotifications & mNotifications; + void NotificationResponder(const std::string& replypump, + const LLSD& notification, + const LLSD& response); + LLNotifications & mNotifications; }; #endif // LL_LLNOTIFICATIONSLISTENER_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0836a4b016..a908b058f0 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1480,6 +1480,7 @@ endif (INSTALL) include(LLAddBuildTest) SET(viewer_TEST_SOURCE_FILES llagentaccess.cpp + lllogininstance.cpp # Not *actually* a unit test, it's an integration test. # Because it won't work in the new unit test iface, i've commented out # and notified Nat. Delete this when it's replaced! diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8492644b2d..17984b8eae 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3986,7 +3986,7 @@ void LLAppViewer::forceErrorBadMemoryAccess() return; } -void LLAppViewer::forceErrorInifiniteLoop() +void LLAppViewer::forceErrorInfiniteLoop() { while(true) { @@ -4152,3 +4152,111 @@ void LLAppViewer::loadEventHostModule(S32 listen_port) mPlugins.insert(eventhost_dso_handle); } + +void LLAppViewer::launchUpdater() +{ + LLSD query_map = LLSD::emptyMap(); + // *TODO place os string in a global constant +#if LL_WINDOWS + query_map["os"] = "win"; +#elif LL_DARWIN + query_map["os"] = "mac"; +#elif LL_LINUX + query_map["os"] = "lnx"; +#elif LL_SOLARIS + query_map["os"] = "sol"; +#endif + // *TODO change userserver to be grid on both viewer and sim, since + // userserver no longer exists. + query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); + query_map["channel"] = gSavedSettings.getString("VersionChannelName"); + // *TODO constantize this guy + // *NOTE: This URL is also used in win_setup/lldownloader.cpp + LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); + + if(LLAppViewer::sUpdaterInfo) + { + delete LLAppViewer::sUpdaterInfo; + } + LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; + +#if LL_WINDOWS + LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); + if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + // We're hosed, bail + LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL; + return; + } + + LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe"; + + std::string updater_source = gDirUtilp->getAppRODataDir(); + updater_source += gDirUtilp->getDirDelimiter(); + updater_source += "updater.exe"; + + LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source + << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath + << LL_ENDL; + + + if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE)) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL; + + return; + } + + // if a sim name was passed in via command line parameter (typically through a SLURL) + if ( LLURLSimString::sInstance.mSimString.length() ) + { + // record the location to start at next time + gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); + }; + + LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; + + //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird. + LLAppViewer::instance()->removeMarkerFile(); // In case updater fails + + // *NOTE:Mani The updater is spawned as the last thing before the WinMain exit. + // see LLAppViewerWin32.cpp + +#elif LL_DARWIN + // if a sim name was passed in via command line parameter (typically through a SLURL) + if ( LLURLSimString::sInstance.mSimString.length() ) + { + // record the location to start at next time + gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); + }; + + LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; + LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; + + // Run the auto-updater. + system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ + +#elif LL_LINUX || LL_SOLARIS + OSMessageBox("Automatic updating is not yet implemented for Linux.\n" + "Please download the latest version from www.secondlife.com.", + LLStringUtil::null, OSMB_OK); +#endif + + // *REMOVE:Mani - Saving for reference... + // LLAppViewer::instance()->forceQuit(); +} \ No newline at end of file diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 69f2a074aa..08bd94563d 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -126,7 +126,7 @@ public: virtual void forceErrorLLError(); virtual void forceErrorBreakpoint(); virtual void forceErrorBadMemoryAccess(); - virtual void forceErrorInifiniteLoop(); + virtual void forceErrorInfiniteLoop(); virtual void forceErrorSoftwareException(); virtual void forceErrorDriverCrash(); @@ -262,6 +262,8 @@ public: std::ostringstream mParams; }LLUpdaterInfo ; static LLUpdaterInfo *sUpdaterInfo ; + + void launchUpdater(); }; // consts from viewer.h diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index c79e96a5e5..d75640ccb4 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -74,6 +74,8 @@ LLFloaterTOS* LLFloaterTOS::show(ETOSType type, LLUICtrlFactory::getInstance()->buildFloater(LLFloaterTOS::sInstance, "floater_critical.xml"); } + sInstance->startModal(); + return LLFloaterTOS::sInstance; } diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 22497ed291..bf42129fc1 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -47,7 +47,6 @@ // newview #include "llviewernetwork.h" -#include "llappviewer.h" // Wish I didn't have to, but... #include "llviewercontrol.h" #include "llurlsimstring.h" #include "llfloatertos.h" @@ -74,7 +73,6 @@ LLLoginInstance::~LLLoginInstance() { } - void LLLoginInstance::connect(const LLSD& credentials) { std::vector uris; @@ -84,6 +82,7 @@ void LLLoginInstance::connect(const LLSD& credentials) void LLLoginInstance::connect(const std::string& uri, const LLSD& credentials) { + mAttemptComplete = false; // Reset attempt complete at this point! constructAuthParams(credentials); mLoginModule->connect(uri, mRequestData); } @@ -99,6 +98,7 @@ void LLLoginInstance::reconnect() void LLLoginInstance::disconnect() { + mAttemptComplete = false; // Reset attempt complete at this point! mRequestData.clear(); mLoginModule->disconnect(); } @@ -162,12 +162,13 @@ void LLLoginInstance::constructAuthParams(const LLSD& credentials) request_params["skipoptional"] = mSkipOptionalUpdate; request_params["agree_to_tos"] = false; // Always false here. Set true in request_params["read_critical"] = false; // handleTOSResponse - request_params["last_exec_event"] = gLastExecEvent; + request_params["last_exec_event"] = mLastExecEvent; request_params["mac"] = hashed_mac_string; request_params["version"] = gCurrentVersion; // Includes channel name request_params["channel"] = gSavedSettings.getString("VersionChannelName"); - request_params["id0"] = LLAppViewer::instance()->getSerialNumber(); + request_params["id0"] = mSerialNumber; + mRequestData.clear(); mRequestData["method"] = "login_to_simulator"; mRequestData["params"] = request_params; mRequestData["options"] = requested_options; @@ -219,21 +220,18 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) // to reconnect or to end the attempt in failure. if(reason_response == "tos") { - LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "agree_to_tos") - ); - tos_dialog->startModal(); + LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "agree_to_tos")); } else if(reason_response == "critical") { - LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "read_critical") + LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical") ); - tos_dialog->startModal(); } else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) { @@ -259,12 +257,14 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) bool LLLoginInstance::handleLoginSuccess(const LLSD& event) { - LLSD response = event["data"]; - std::string message_response = response["message"].asString(); if(gSavedSettings.getBOOL("ForceMandatoryUpdate")) { + LLSD response = event["data"]; + std::string message_response = response["message"].asString(); + // Testing update... gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE); + // Don't confuse startup by leaving login "online". mLoginModule->disconnect(); updateApp(true, message_response); @@ -281,7 +281,7 @@ void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) if(accepted) { // Set the request data to true and retry login. - mRequestData[key] = true; + mRequestData["params"][key] = true; reconnect(); } else @@ -344,13 +344,36 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) notification_name += "ReleaseForDownload"; #endif } - - LLNotifications::instance().add(notification_name, args, payload, - boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2)); + + // *NOTE:Mani - for reference +// LLNotifications::instance().add(notification_name, args, payload, +// boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2)); + + if(!mUpdateAppResponse) + { + bool make_unique = true; + mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique)); + mUpdateAppResponse->listen("diaupdateDialogCallback", + boost::bind(&LLLoginInstance::updateDialogCallback, + this, _1 + ) + ); + } + + LLSD event; + event["op"] = "requestAdd"; + event["name"] = notification_name; + event["substitutions"] = args; + event["payload"] = payload; + event["reply"] = mUpdateAppResponse->getName(); + + LLEventPumps::getInstance()->obtain("LLNotifications").post(event); } -bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response) +bool LLLoginInstance::updateDialogCallback(const LLSD& event) { + LLSD notification = event["notification"]; + LLSD response = event["response"]; S32 option = LLNotification::getSelectedOption(notification, response); std::string update_exe_path; bool mandatory = notification["payload"]["mandatory"].asBoolean(); @@ -395,114 +418,12 @@ bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& return false; } - LLSD query_map = LLSD::emptyMap(); - // *TODO place os string in a global constant -#if LL_WINDOWS - query_map["os"] = "win"; -#elif LL_DARWIN - query_map["os"] = "mac"; -#elif LL_LINUX - query_map["os"] = "lnx"; -#elif LL_SOLARIS - query_map["os"] = "sol"; -#endif - // *TODO change userserver to be grid on both viewer and sim, since - // userserver no longer exists. - query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); - query_map["channel"] = gSavedSettings.getString("VersionChannelName"); - // *TODO constantize this guy - // *NOTE: This URL is also used in win_setup/lldownloader.cpp - LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); - - if(LLAppViewer::sUpdaterInfo) - { - delete LLAppViewer::sUpdaterInfo; - } - LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; - -#if LL_WINDOWS - LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); - if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) - { - delete LLAppViewer::sUpdaterInfo ; - LLAppViewer::sUpdaterInfo = NULL ; - - // We're hosed, bail - LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL; - - attemptComplete(); - // *REMOVE:Mani - Saving for reference... - // LLAppViewer::instance()->forceQuit(); - return false; - } - - LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe"; - - std::string updater_source = gDirUtilp->getAppRODataDir(); - updater_source += gDirUtilp->getDirDelimiter(); - updater_source += "updater.exe"; - - LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source - << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath - << LL_ENDL; - - - if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE)) - { - delete LLAppViewer::sUpdaterInfo ; - LLAppViewer::sUpdaterInfo = NULL ; - - LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL; - attemptComplete(); - // *REMOVE:Mani - Saving for reference... - // LLAppViewer::instance()->forceQuit(); - return false; - } - - // if a sim name was passed in via command line parameter (typically through a SLURL) - if ( LLURLSimString::sInstance.mSimString.length() ) - { - // record the location to start at next time - gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); - }; - - LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; - - LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; - - //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird. - LLAppViewer::instance()->removeMarkerFile(); // In case updater fails - - // *NOTE:Mani The updater is spawned as the last thing before the WinMain exit. - // see LLAppViewerWin32.cpp - -#elif LL_DARWIN - // if a sim name was passed in via command line parameter (typically through a SLURL) - if ( LLURLSimString::sInstance.mSimString.length() ) - { - // record the location to start at next time - gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); - }; - - LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; - LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; - LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; - LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; - - LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; - - // Run the auto-updater. - system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ - -#elif LL_LINUX || LL_SOLARIS - OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK); -#endif - - // *REMOVE:Mani - Saving for reference... - // LLAppViewer::instance()->forceQuit(); + if(mUpdaterLauncher) + { + mUpdaterLauncher(); + } + + attemptComplete(); return false; } @@ -526,4 +447,4 @@ std::string construct_start_string() start = gSavedSettings.getString("LoginLocation"); } return start; -} +} \ No newline at end of file diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index da70fec40e..afe96acd1e 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -34,7 +34,9 @@ #define LL_LLLOGININSTANCE_H #include +#include class LLLogin; +class LLEventStream; // This class hosts the login module and is used to // negotiate user authentication attempts. @@ -49,16 +51,6 @@ public: void reconnect(); // reconnect using the current credentials. void disconnect(); - // Set whether this class will drive user interaction. - // If not, login failures like 'need tos agreement' will - // end the login attempt. - void setUserInteraction(bool state) { mUserInteraction = state; } - bool getUserInteraction() { return mUserInteraction; } - - // Whether to tell login to skip optional update request. - // False by default. - void setSkipOptionalUpdate(bool state) { mSkipOptionalUpdate = state; } - bool authFailure() { return mAttemptComplete && mLoginState == "offline"; } bool authSuccess() { return mAttemptComplete && mLoginState == "online"; } @@ -69,10 +61,25 @@ public: // Only valid when authSuccess == true. const F64 getLastTransferRateBPS() { return mTransferRate; } + // Set whether this class will drive user interaction. + // If not, login failures like 'need tos agreement' will + // end the login attempt. + void setUserInteraction(bool state) { mUserInteraction = state; } + bool getUserInteraction() { return mUserInteraction; } + + // Whether to tell login to skip optional update request. + // False by default. + void setSkipOptionalUpdate(bool state) { mSkipOptionalUpdate = state; } + void setSerialNumber(const std::string& sn) { mSerialNumber = sn; } + void setLastExecEvent(int lee) { mLastExecEvent = lee; } + + typedef boost::function UpdaterLauncherCallback; + void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; } + private: void constructAuthParams(const LLSD& credentials); void updateApp(bool mandatory, const std::string& message); - bool updateDialogCallback(const LLSD& notification, const LLSD& response); + bool updateDialogCallback(const LLSD& event); bool handleLoginEvent(const LLSD& event); bool handleLoginFailure(const LLSD& event); @@ -90,6 +97,10 @@ private: bool mSkipOptionalUpdate; bool mAttemptComplete; F64 mTransferRate; + std::string mSerialNumber; + int mLastExecEvent; + UpdaterLauncherCallback mUpdaterLauncher; + boost::scoped_ptr mUpdateAppResponse; }; #endif diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 9afb8468ef..7af1cbf51f 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -432,8 +432,7 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask) if ( KEY_F2 == key ) { llinfos << "Spawning floater TOS window" << llendl; - LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,"", 0); - tos_dialog->startModal(); + LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,"", NULL); return TRUE; } #endif diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f0f056652a..dac6f8423a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -965,13 +965,17 @@ bool idle_startup() display_startup(); // Setting initial values... + LLLoginInstance* login = LLLoginInstance::getInstance(); if(gNoRender) { // HACK, skip optional updates if you're running drones - LLLoginInstance::getInstance()->setSkipOptionalUpdate(true); + login->setSkipOptionalUpdate(true); } - LLLoginInstance::getInstance()->setUserInteraction(show_connect_box); + login->setUserInteraction(show_connect_box); + login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); + login->setLastExecEvent(gLastExecEvent); + login->setUpdaterLauncher(boost::bind(LLAppViewer::launchUpdater, LLAppViewer::instance())); // This call to LLLoginInstance::connect() starts the // authentication process. @@ -979,7 +983,7 @@ bool idle_startup() credentials["first"] = gFirstname; credentials["last"] = gLastname; credentials["passwd"] = gPassword; - LLLoginInstance::getInstance()->connect(credentials); + login->connect(credentials); LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); return FALSE; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 826aca5e64..1ab10b2f27 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7103,7 +7103,7 @@ void force_error_bad_memory_access(void *) void force_error_infinite_loop(void *) { - LLAppViewer::instance()->forceErrorInifiniteLoop(); + LLAppViewer::instance()->forceErrorInfiniteLoop(); } void force_error_software_exception(void *) -- cgit v1.3 From 9538328d5f7cf0f0be5dd77b8e27032e09104fff Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Fri, 24 Jul 2009 15:08:16 -0700 Subject: Adding LLLoginInstance unit test. - Added LLNotificationsInterface class. - Removed LLLoginInstance use of LLNotifications EventAPI --- indra/llui/llnotifications.h | 13 +- indra/llui/llnotificationslistener.cpp | 8 +- indra/llui/llnotificationslistener.h | 2 +- indra/newview/lllogininstance.cpp | 15 +- indra/newview/lllogininstance.h | 7 +- indra/newview/llstartup.cpp | 3 +- indra/newview/tests/lllogininstance_test.cpp | 413 +++++++++++++++++++++++++++ 7 files changed, 447 insertions(+), 14 deletions(-) create mode 100644 indra/newview/tests/lllogininstance_test.cpp (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 93cdcbeefd..c534267fca 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -799,8 +799,19 @@ private: LLNotificationComparator mComparator; }; +// An interface class to provide a clean linker seam to the LLNotifications class. +// Extend this interface as needed for your use of LLNotifications. +class LLNotificationsInterface +{ +public: + virtual LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + LLNotificationFunctorRegistry::ResponseFunctor functor) = 0; +}; class LLNotifications : + public LLNotificationsInterface, public LLSingleton, public LLNotificationChannelBase { @@ -824,7 +835,7 @@ public: const LLSD& substitutions, const LLSD& payload, const std::string& functor_name); - LLNotificationPtr add(const std::string& name, + /* virtual */ LLNotificationPtr add(const std::string& name, const LLSD& substitutions, const LLSD& payload, LLNotificationFunctorRegistry::ResponseFunctor functor); diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 6ebbee68ac..75f4d6177d 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -29,7 +29,7 @@ void LLNotificationsListener::requestAdd(const LLSD& event_data) const mNotifications.add(event_data["name"], event_data["substitutions"], event_data["payload"], - boost::bind(&LLNotificationListener::Responder, + boost::bind(&LLNotificationsListener::NotificationResponder, this, event_data["reply"].asString(), _1, _2 @@ -44,12 +44,12 @@ void LLNotificationsListener::requestAdd(const LLSD& event_data) const } } -void LLNotificationsListener::Responder(const std::string& reply_pump, +void LLNotificationsListener::NotificationResponder(const std::string& reply_pump, const LLSD& notification, - const LLSD& response) + const LLSD& response) const { LLSD reponse_event; reponse_event["notification"] = notification; reponse_event["response"] = response; - mEventPumps.obtain(reply_pump).post(reponse_event); + LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); } diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index d11aed1b52..6f71a7c781 100644 --- a/indra/llui/llnotificationslistener.h +++ b/indra/llui/llnotificationslistener.h @@ -27,7 +27,7 @@ public: private: void NotificationResponder(const std::string& replypump, const LLSD& notification, - const LLSD& response); + const LLSD& response) const; LLNotifications & mNotifications; }; diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index bf42129fc1..c08cc2baae 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -59,6 +59,7 @@ std::string construct_start_string(); LLLoginInstance::LLLoginInstance() : mLoginModule(new LLLogin()), + mNotifications(NULL), mLoginState("offline"), mUserInteraction(true), mSkipOptionalUpdate(false), @@ -345,10 +346,13 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) #endif } - // *NOTE:Mani - for reference -// LLNotifications::instance().add(notification_name, args, payload, -// boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2)); + if(mNotifications) + { + mNotifications->add(notification_name, args, payload, + boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2)); + } + /* *NOTE:Mani Experiment with Event API interface. if(!mUpdateAppResponse) { bool make_unique = true; @@ -368,12 +372,11 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) event["reply"] = mUpdateAppResponse->getName(); LLEventPumps::getInstance()->obtain("LLNotifications").post(event); + */ } -bool LLLoginInstance::updateDialogCallback(const LLSD& event) +bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response) { - LLSD notification = event["notification"]; - LLSD response = event["response"]; S32 option = LLNotification::getSelectedOption(notification, response); std::string update_exe_path; bool mandatory = notification["payload"]["mandatory"].asBoolean(); diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index afe96acd1e..47d52a6184 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -37,6 +37,7 @@ #include class LLLogin; class LLEventStream; +class LLNotificationsInterface; // This class hosts the login module and is used to // negotiate user authentication attempts. @@ -73,13 +74,15 @@ public: void setSerialNumber(const std::string& sn) { mSerialNumber = sn; } void setLastExecEvent(int lee) { mLastExecEvent = lee; } + void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; } + typedef boost::function UpdaterLauncherCallback; void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; } private: void constructAuthParams(const LLSD& credentials); void updateApp(bool mandatory, const std::string& message); - bool updateDialogCallback(const LLSD& event); + bool updateDialogCallback(const LLSD& notification, const LLSD& response); bool handleLoginEvent(const LLSD& event); bool handleLoginFailure(const LLSD& event); @@ -90,6 +93,8 @@ private: void attemptComplete() { mAttemptComplete = true; } // In the future an event? boost::scoped_ptr mLoginModule; + LLNotificationsInterface* mNotifications; + std::string mLoginState; LLSD mRequestData; LLSD mResponseData; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index dac6f8423a..eb585f8fe3 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -966,6 +966,7 @@ bool idle_startup() // Setting initial values... LLLoginInstance* login = LLLoginInstance::getInstance(); + login->setNotificationsInterface(LLNotifications::getInstance()); if(gNoRender) { // HACK, skip optional updates if you're running drones @@ -975,7 +976,7 @@ bool idle_startup() login->setUserInteraction(show_connect_box); login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); login->setLastExecEvent(gLastExecEvent); - login->setUpdaterLauncher(boost::bind(LLAppViewer::launchUpdater, LLAppViewer::instance())); + login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance())); // This call to LLLoginInstance::connect() starts the // authentication process. diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp new file mode 100644 index 0000000000..19cf9cd961 --- /dev/null +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -0,0 +1,413 @@ +/** + * @file lllogininstance_test.cpp + * @brief Test for lllogininstance.cpp. + * + * $LicenseInfo:firstyear=2008&license=internal$ + * Copyright (c) 2008, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "../llviewerprecompiledheaders.h" +// Own header +#include "../lllogininstance.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "llevents.h" + +#if defined(LL_WINDOWS) +#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr +#endif + +// Constants +const std::string VIEWERLOGIN_URI("viewerlogin_uri"); +const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid"); + +const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno"); + +// Link seams. + +//----------------------------------------------------------------------------- +static LLEventStream gTestPump("test_pump"); + +#include "lllogin.h" +static std::string gLoginURI; +static LLSD gLoginCreds; +static bool gDisconnectCalled = false; +class LLLogin::Impl +{ +}; +LLLogin::LLLogin() {} +LLLogin::~LLLogin() {} +LLEventPump& LLLogin::getEventPump() { return gTestPump; } +void LLLogin::connect(const std::string& uri, const LLSD& credentials) +{ + gLoginURI = uri; + gLoginCreds = credentials; +} + +void LLLogin::disconnect() +{ + gDisconnectCalled = true; +} + +//----------------------------------------------------------------------------- +#include "../llviewernetwork.h" +unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'}; /* Flawfinder: ignore */ + +LLViewerLogin::LLViewerLogin() {} +LLViewerLogin::~LLViewerLogin() {} +void LLViewerLogin::getLoginURIs(std::vector& uris) const +{ + uris.push_back(VIEWERLOGIN_URI); +} +std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; } + +//----------------------------------------------------------------------------- +#include "../llviewercontrol.h" +LLControlGroup gSavedSettings("Global"); +LLControlGroup gSavedSkinSettings("Skinning"); +std::string gCurrentVersion = "invalid_version"; + +LLControlGroup::LLControlGroup(const std::string& name) : + LLInstanceTracker(name){} +LLControlGroup::~LLControlGroup() {} +void LLControlGroup::setBOOL(const std::string& name, BOOL val) {} +BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; } +U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; } +void LLControlGroup::setString(const std::string& name, const std::string& val) {} +std::string LLControlGroup::getString(const std::string& name) { return "test_string"; } +BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; } +BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; } + +//----------------------------------------------------------------------------- +#include "../llurlsimstring.h" +LLURLSimString LLURLSimString::sInstance; +bool LLURLSimString::parse() { return true; } + +//----------------------------------------------------------------------------- +#include "../llfloatertos.h" +static LLFloaterTOS::ETOSType gTOSType; +static LLFloaterTOS::YesNoCallback gTOSCallback; +LLFloaterTOS* LLFloaterTOS::show(LLFloaterTOS::ETOSType type, + const std::string & message, + const YesNoCallback& callback) +{ + gTOSType = type; + gTOSCallback = callback; + return NULL; +} + +//----------------------------------------------------------------------------- +// LLNotifications +class MockNotifications : public LLNotificationsInterface +{ + boost::function mResponder; + int mAddedCount; + +public: + MockNotifications() : + mResponder(0), + mAddedCount(0) + { + } + + virtual ~MockNotifications() {} + + /* virtual */ LLNotificationPtr add( + const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + LLNotificationFunctorRegistry::ResponseFunctor functor) + { + mResponder = functor; + mAddedCount++; + return LLNotificationPtr((LLNotification*)NULL); + } + + void sendYesResponse() + { + LLSD notification; + LLSD response; + response = 1; + mResponder(notification, response); + } + + void sendNoResponse() + { + LLSD notification; + LLSD response; + response = 2; + mResponder(notification, response); + } + + void sendBogusResponse() + { + LLSD notification; + LLSD response; + response = 666; + mResponder(notification, response); + } + + int addedCount() { return mAddedCount; } +}; + +S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response) +{ + return response.asInteger(); +} + +// misc +std::string xml_escape_string(const std::string& in) +{ + return in; +} + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct lllogininstance_data + { + lllogininstance_data() : logininstance(LLLoginInstance::getInstance()) + { + // Global initialization + gLoginURI.clear(); + gLoginCreds.clear(); + gDisconnectCalled = false; + + // gTOSType = -1; // Set to invalid value. + gTOSCallback = 0; // clear the callback. + + + gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); + gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE); + gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE); + gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE); + gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE); + gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE); + gSavedSettings.declareString("NextLoginLocation", "", "", FALSE); + gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE); + + credentials["first"] = "testfirst"; + credentials["last"] = "testlast"; + credentials["passwd"] = "testpass"; + + logininstance->setNotificationsInterface(¬ifications); + } + + LLLoginInstance* logininstance; + LLSD credentials; + MockNotifications notifications; + }; + + typedef test_group lllogininstance_group; + typedef lllogininstance_group::object lllogininstance_object; + lllogininstance_group llsdmgr("lllogininstance"); + + template<> template<> + void lllogininstance_object::test<1>() + { + set_test_name("Test Simple Success And Disconnect"); + + // Test default connect. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Dummy success response. + LLSD response; + response["state"] = "online"; + response["progress"] = 1.0; + response["transfer_rate"] = 7; + response["data"] = "test_data"; + + gTestPump.post(response); + + ensure("Success response", logininstance->authSuccess()); + ensure_equals("Test Response Data", logininstance->getResponse().asString(), "test_data"); + + logininstance->disconnect(); + + ensure_equals("Called Login Module Disconnect", gDisconnectCalled, true); + + response.clear(); + response["state"] = "offline"; + response["progress"] = 0.0; + response["transfer_rate"] = 0; + response["data"] = "test_data"; + + gTestPump.post(response); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<2>() + { + set_test_name("Test User TOS/Critical message Interaction"); + + const std::string test_uri = "testing-uri"; + + // Test default connect. + logininstance->connect(test_uri, credentials); + + // connect should call LLLogin::connect to init gLoginURI and gLoginCreds. + ensure_equals("Default connect uri", gLoginURI, "testing-uri"); + ensure_equals("Default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false); + ensure_equals("Default for read critical", gLoginCreds["params"]["read_critical"].asBoolean(), false); + + // TOS failure response. + LLSD response; + response["state"] = "offline"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "tos"; + gTestPump.post(response); + + ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_TOS); + ensure("TOS callback given", gTOSCallback != 0); + gTOSCallback(false); // Call callback denying TOS. + ensure("No TOS, failed auth", logininstance->authFailure()); + + // Start again. + logininstance->connect(test_uri, credentials); + gTestPump.post(response); // Fail for tos again. + gTOSCallback(true); // Accept tos, should reconnect w/ agree_to_tos. + ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true); + ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); + + // Fail connection, attempt connect again. + // The new request should have reset agree to tos to default. + response["data"]["reason"] = "key"; // bad creds. + gTestPump.post(response); + ensure("TOS auth failure", logininstance->authFailure()); + + logininstance->connect(test_uri, credentials); + ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false); + + // Critical Message failure response. + logininstance->connect(test_uri, credentials); + response["data"]["reason"] = "critical"; // Change response to "critical message" + gTestPump.post(response); + + ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_CRITICAL_MESSAGE); + ensure("TOS callback given", gTOSCallback != 0); + gTOSCallback(true); + ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); + ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); + + // Fail then attempt new connection + response["data"]["reason"] = "key"; // bad creds. + gTestPump.post(response); + ensure("TOS auth failure", logininstance->authFailure()); + logininstance->connect(test_uri, credentials); + ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false); + } + + template<> template<> + void lllogininstance_object::test<3>() + { + set_test_name("Test Mandatory Update User Accepts"); + + // Part 1 - Mandatory Update, with User accepts response. + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "update"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + + notifications.sendYesResponse(); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<4>() + { + set_test_name("Test Mandatory Update User Decline"); + + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "update"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + notifications.sendNoResponse(); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<6>() + { + set_test_name("Test Optional Update User Accept"); + + // Part 3 - Mandatory Update, with bogus response. + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "optional"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + notifications.sendYesResponse(); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<7>() + { + set_test_name("Test Optional Update User Denies"); + + // Part 3 - Mandatory Update, with bogus response. + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "optional"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + notifications.sendNoResponse(); + + // User skips, should be reconnecting. + ensure_equals("reconnect uri", gLoginURI, VIEWERLOGIN_URI); + ensure_equals("skipping optional update", gLoginCreds["params"]["skipoptional"].asBoolean(), true); + } +} -- cgit v1.3 From 91497c40c53f145749ae418c8f49e05916d87f5b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 28 Jul 2009 13:46:34 -0700 Subject: Fix Linux compile problem --- indra/newview/lllogininstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index c08cc2baae..16192079a2 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -450,4 +450,4 @@ std::string construct_start_string() start = gSavedSettings.getString("LoginLocation"); } return start; -} \ No newline at end of file +} -- cgit v1.3 From ec2219724023144a0098199229aee7947a29af08 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 31 Jul 2009 15:32:03 -0700 Subject: Fixups for conflicts that got dropped in the changeset 486d51877332 merge of viewer-2.0.0-3 with login-api. Mostly code that had been modified in viewer-2.0.0-3 that had been moved elsewhere in login-api. --- indra/newview/lllogininstance.cpp | 2 +- indra/newview/llstartup.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 16192079a2..f967fcaf97 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -296,7 +296,7 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) { // store off config state, as we might quit soon gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - gSavedSkinSettings.saveToFile(gSavedSettings.getString("SkinningSettingsFile"), TRUE); + LLUIColorTable::instance().saveUserSettings(); std::ostringstream message; std::string msg; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 822c12536e..cc933fbf1e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -204,7 +204,7 @@ bool gAgentMovementCompleted = false; std::string SCREEN_HOME_FILENAME = "screen_home.bmp"; std::string SCREEN_LAST_FILENAME = "screen_last.bmp"; -LLPointer gStartImageGL; +LLPointer gStartTexture; // // Imported globals @@ -1487,7 +1487,7 @@ bool idle_startup() LLSD id = inv_lib_owner[0]["agent_id"]; if(id.isDefined()) { - gInventory.setLibraryOwnerID( LLUUID(id.asUUID()); + gInventory.setLibraryOwnerID( LLUUID(id.asUUID())); } } @@ -2915,7 +2915,7 @@ bool process_login_success_response() LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"]; if(inv_root_folder_id.notNull()) { - gAgent.getInventoryRootID() = inv_root_folder_id; + gInventory.setRootFolderID(inv_root_folder_id); //gInventory.mock(gAgent.getInventoryRootID()); } @@ -3003,7 +3003,7 @@ bool process_login_success_response() && gAgentSessionID.notNull() && gMessageSystem->mOurCircuitCode && gFirstSim.isOk() - && gAgent.getInventoryRootID().notNull()) + && gInventory.getRootFolderID().notNull()) { success = true; } -- cgit v1.3 From 0bf8a15cc03b48432a5b9e0011a01908ef903960 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Wed, 5 Aug 2009 18:39:02 -0700 Subject: Fixups after the latest merge with viewer-2.0.0-3. Updated LLLoginInstance to use the new LLFloaterReg way of getting hold of floaters. --- indra/newview/llfloatertos.cpp | 7 ++++++- indra/newview/llfloatertos.h | 3 +++ indra/newview/lllogininstance.cpp | 18 ++++++++++-------- indra/newview/tests/lllogininstance_test.cpp | 24 ++++++++++++++++-------- 4 files changed, 35 insertions(+), 17 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 40bd6360ed..9859d34284 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -57,7 +57,7 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& message) mMessage(message.asString()), mWebBrowserWindowId( 0 ), mLoadCompleteCount( 0 ), - mCallback(callback) + mCallback() { } @@ -240,3 +240,8 @@ void LLFloaterTOS::onNavigateComplete( const EventType& eventIn ) tos_agreement->setEnabled( true ); }; } + +void LLFloaterTOS::setTOSCallback(LLFloaterTOS::YesNoCallback const & callback) +{ + mCallback = callback; +} diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 0be440d92b..0b15c24bc8 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -66,6 +66,9 @@ public: virtual void onNavigateComplete( const EventType& eventIn ); + // *TODO - consider getting rid of this in favor of using an event pump. -brad + void setTOSCallback(YesNoCallback const & callback); + private: std::string mMessage; int mWebBrowserWindowId; diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index f967fcaf97..3c59cb83cd 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -49,6 +49,7 @@ #include "llviewernetwork.h" #include "llviewercontrol.h" #include "llurlsimstring.h" +#include "llfloaterreg.h" #include "llfloatertos.h" #include "llwindow.h" #if LL_LINUX || LL_SOLARIS @@ -221,18 +222,19 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) // to reconnect or to end the attempt in failure. if(reason_response == "tos") { - LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, + LLFloaterTOS * tos = + LLFloaterReg::showTypedInstance("message_tos", LLSD(message_response)); + + tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, this, _1, "agree_to_tos")); } else if(reason_response == "critical") { - LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "read_critical") - ); + LLFloaterTOS * tos = + LLFloaterReg::showTypedInstance("message_critical",LLSD(message_response)); + + tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical")); } else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) { diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 5af8acebaf..d3080d6e4a 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -91,15 +91,23 @@ LLURLSimString LLURLSimString::sInstance; bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- +#include "llfloaterreg.h" #include "../llfloatertos.h" -static LLFloaterTOS::ETOSType gTOSType; +static std::string gTOSType; static LLFloaterTOS::YesNoCallback gTOSCallback; -LLFloaterTOS* LLFloaterTOS::show(LLFloaterTOS::ETOSType type, - const std::string & message, - const YesNoCallback& callback) + +void LLFloaterTOS::setTOSCallback(YesNoCallback const & callback) { - gTOSType = type; gTOSCallback = callback; +} + +//static +LLFloater* LLFloaterReg::showInstance(const std::string & name, + const LLSD & key, + BOOL focus) +{ + gTOSType = name; + gTOSCallback = LLFloaterTOS::YesNoCallback(); return NULL; } @@ -182,7 +190,7 @@ namespace tut gLoginCreds.clear(); gDisconnectCalled = false; - // gTOSType = -1; // Set to invalid value. + gTOSType = ""; // Set to invalid value. gTOSCallback = 0; // clear the callback. @@ -271,7 +279,7 @@ namespace tut response["data"]["reason"] = "tos"; gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_TOS); + ensure_equals("TOS Dialog type", gTOSType, "message_tos"); ensure("TOS callback given", gTOSCallback != 0); gTOSCallback(false); // Call callback denying TOS. ensure("No TOS, failed auth", logininstance->authFailure()); @@ -297,7 +305,7 @@ namespace tut response["data"]["reason"] = "critical"; // Change response to "critical message" gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_CRITICAL_MESSAGE); + ensure_equals("TOS Dialog type", gTOSType, "message_critical"); ensure("TOS callback given", gTOSCallback != 0); gTOSCallback(true); ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); -- cgit v1.3 From e6c9f944380d3a9b6562cf580e8c43a69c060dfd Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 6 Aug 2009 18:45:37 -0700 Subject: Backed out changeset bfb246df4655: rolling back LLFloaterTOS post-merge fixups because they didn't work on linux. --- indra/newview/llfloatertos.cpp | 7 +------ indra/newview/llfloatertos.h | 3 --- indra/newview/lllogininstance.cpp | 18 ++++++++---------- indra/newview/tests/lllogininstance_test.cpp | 24 ++++++++---------------- 4 files changed, 17 insertions(+), 35 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 9859d34284..40bd6360ed 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -57,7 +57,7 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& message) mMessage(message.asString()), mWebBrowserWindowId( 0 ), mLoadCompleteCount( 0 ), - mCallback() + mCallback(callback) { } @@ -240,8 +240,3 @@ void LLFloaterTOS::onNavigateComplete( const EventType& eventIn ) tos_agreement->setEnabled( true ); }; } - -void LLFloaterTOS::setTOSCallback(LLFloaterTOS::YesNoCallback const & callback) -{ - mCallback = callback; -} diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 0b15c24bc8..0be440d92b 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -66,9 +66,6 @@ public: virtual void onNavigateComplete( const EventType& eventIn ); - // *TODO - consider getting rid of this in favor of using an event pump. -brad - void setTOSCallback(YesNoCallback const & callback); - private: std::string mMessage; int mWebBrowserWindowId; diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 3c59cb83cd..f967fcaf97 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -49,7 +49,6 @@ #include "llviewernetwork.h" #include "llviewercontrol.h" #include "llurlsimstring.h" -#include "llfloaterreg.h" #include "llfloatertos.h" #include "llwindow.h" #if LL_LINUX || LL_SOLARIS @@ -222,19 +221,18 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) // to reconnect or to end the attempt in failure. if(reason_response == "tos") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_tos", LLSD(message_response)); - - tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, + LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, this, _1, "agree_to_tos")); } else if(reason_response == "critical") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_critical",LLSD(message_response)); - - tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "read_critical")); + LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical") + ); } else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) { diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index d3080d6e4a..5af8acebaf 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -91,23 +91,15 @@ LLURLSimString LLURLSimString::sInstance; bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- -#include "llfloaterreg.h" #include "../llfloatertos.h" -static std::string gTOSType; +static LLFloaterTOS::ETOSType gTOSType; static LLFloaterTOS::YesNoCallback gTOSCallback; - -void LLFloaterTOS::setTOSCallback(YesNoCallback const & callback) +LLFloaterTOS* LLFloaterTOS::show(LLFloaterTOS::ETOSType type, + const std::string & message, + const YesNoCallback& callback) { + gTOSType = type; gTOSCallback = callback; -} - -//static -LLFloater* LLFloaterReg::showInstance(const std::string & name, - const LLSD & key, - BOOL focus) -{ - gTOSType = name; - gTOSCallback = LLFloaterTOS::YesNoCallback(); return NULL; } @@ -190,7 +182,7 @@ namespace tut gLoginCreds.clear(); gDisconnectCalled = false; - gTOSType = ""; // Set to invalid value. + // gTOSType = -1; // Set to invalid value. gTOSCallback = 0; // clear the callback. @@ -279,7 +271,7 @@ namespace tut response["data"]["reason"] = "tos"; gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, "message_tos"); + ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_TOS); ensure("TOS callback given", gTOSCallback != 0); gTOSCallback(false); // Call callback denying TOS. ensure("No TOS, failed auth", logininstance->authFailure()); @@ -305,7 +297,7 @@ namespace tut response["data"]["reason"] = "critical"; // Change response to "critical message" gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, "message_critical"); + ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_CRITICAL_MESSAGE); ensure("TOS callback given", gTOSCallback != 0); gTOSCallback(true); ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); -- cgit v1.3 From 8f4811f3fd7f252a5f5bc50ed11fecd8e42f3e68 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Tue, 11 Aug 2009 12:09:18 -0400 Subject: Better solution for fixing up the LLFloaterTOS callback after the last viewer-2.0.0-3 merge. LLFloaterTOS and LLLoginInstance now communicate through an event pump "lllogininstance_tos_callback". reviewed by Mani. --- indra/newview/llfloatertos.cpp | 17 +++++------ indra/newview/llfloatertos.h | 6 ++-- indra/newview/lllogininstance.cpp | 42 ++++++++++++++++------------ indra/newview/lllogininstance.h | 2 +- indra/newview/tests/lllogininstance_test.cpp | 33 +++++++++++----------- 5 files changed, 53 insertions(+), 47 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 11f35bedad..e43c3ecde7 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -52,12 +52,12 @@ #include "message.h" -LLFloaterTOS::LLFloaterTOS(const LLSD& message) -: LLModalDialog( message, 100, 100 ), - mMessage(message.asString()), +LLFloaterTOS::LLFloaterTOS(const LLSD& data) +: LLModalDialog( data["message"].asString(), 100, 100 ), + mMessage(data["message"].asString()), mWebBrowserWindowId( 0 ), mLoadCompleteCount( 0 ), - mCallback() + mReplyPumpName(data["reply_pump"].asString()) { } @@ -205,9 +205,9 @@ void LLFloaterTOS::onContinue( void* userdata ) LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User agrees with TOS." << llendl; - if(self->mCallback) + if(self->mReplyPumpName != "") { - self->mCallback(true); + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(true)); } self->closeFloater(); // destroys this object @@ -219,9 +219,9 @@ void LLFloaterTOS::onCancel( void* userdata ) LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User disagrees with TOS." << llendl; - if(self->mCallback) + if(self->mReplyPumpName != "") { - self->mCallback(false); + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false)); } self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS @@ -240,3 +240,4 @@ void LLFloaterTOS::onNavigateComplete( const EventType& eventIn ) tos_agreement->setEnabled( true ); }; } + diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 0be440d92b..89ad29170c 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -49,11 +49,9 @@ class LLFloaterTOS : public LLWebBrowserCtrlObserver { public: - LLFloaterTOS(const LLSD& message); + LLFloaterTOS(const LLSD& data); virtual ~LLFloaterTOS(); - typedef boost::function YesNoCallback; - BOOL postBuild(); virtual void draw(); @@ -70,7 +68,7 @@ private: std::string mMessage; int mWebBrowserWindowId; int mLoadCompleteCount; - YesNoCallback mCallback; + std::string mReplyPumpName; }; #endif // LL_LLFLOATERTOS_H diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 428bed7b72..cb7dbc2de0 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -56,6 +56,9 @@ #include "lltrans.h" #endif +static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback"; +static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; + std::string construct_start_string(); LLLoginInstance::LLLoginInstance() : @@ -222,26 +225,25 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) // to reconnect or to end the attempt in failure. if(reason_response == "tos") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_tos", LLSD(message_response)); - /* - LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "agree_to_tos")); - */ + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_tos", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "agree_to_tos")); } else if(reason_response == "critical") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_critical",LLSD(message_response)); - /* - LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "read_critical") - ); - */ + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_critical", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical")); } else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) { @@ -286,7 +288,7 @@ bool LLLoginInstance::handleLoginSuccess(const LLSD& event) return false; } -void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) +bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { if(accepted) { @@ -298,6 +300,9 @@ void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { attemptComplete(); } + + LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME); + return true; } @@ -460,3 +465,4 @@ std::string construct_start_string() } return start; } + diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 47d52a6184..6a2ccf919e 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -88,7 +88,7 @@ private: bool handleLoginFailure(const LLSD& event); bool handleLoginSuccess(const LLSD& event); - void handleTOSResponse(bool v, const std::string& key); + bool handleTOSResponse(bool v, const std::string& key); void attemptComplete() { mAttemptComplete = true; } // In the future an event? diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 5af8acebaf..a84e796159 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -92,14 +92,15 @@ bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- #include "../llfloatertos.h" -static LLFloaterTOS::ETOSType gTOSType; -static LLFloaterTOS::YesNoCallback gTOSCallback; -LLFloaterTOS* LLFloaterTOS::show(LLFloaterTOS::ETOSType type, - const std::string & message, - const YesNoCallback& callback) +#include "llfloaterreg.h" +static std::string gTOSType; +static LLEventPump * gTOSReplyPump = NULL; + +//static +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) { - gTOSType = type; - gTOSCallback = callback; + gTOSType = name; + gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]); return NULL; } @@ -182,8 +183,8 @@ namespace tut gLoginCreds.clear(); gDisconnectCalled = false; - // gTOSType = -1; // Set to invalid value. - gTOSCallback = 0; // clear the callback. + gTOSType = ""; // Set to invalid value. + gTOSReplyPump = 0; // clear the callback. gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); @@ -271,15 +272,15 @@ namespace tut response["data"]["reason"] = "tos"; gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_TOS); - ensure("TOS callback given", gTOSCallback != 0); - gTOSCallback(false); // Call callback denying TOS. + ensure_equals("TOS Dialog type", gTOSType, "message_tos"); + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(false); // Call callback denying TOS. ensure("No TOS, failed auth", logininstance->authFailure()); // Start again. logininstance->connect(test_uri, credentials); gTestPump.post(response); // Fail for tos again. - gTOSCallback(true); // Accept tos, should reconnect w/ agree_to_tos. + gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos. ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true); ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); @@ -297,9 +298,9 @@ namespace tut response["data"]["reason"] = "critical"; // Change response to "critical message" gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_CRITICAL_MESSAGE); - ensure("TOS callback given", gTOSCallback != 0); - gTOSCallback(true); + ensure_equals("TOS Dialog type", gTOSType, "message_critical"); + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(true); ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); -- cgit v1.3 From 81d3f7ec6b348a08ad8c330d8d9ba90cd10ee816 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Mon, 31 Aug 2009 20:00:09 -0400 Subject: Post-merge cleanups (ported llstartup.cpp changes to where the surrounding code has been moved to in LLLoginInstance and LLAppViewer) --- indra/newview/llappviewer.cpp | 72 ++++++++++++++++++++++++++++----------- indra/newview/lllogininstance.cpp | 7 ++-- indra/newview/llstartup.cpp | 1 - 3 files changed, 58 insertions(+), 22 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index dd00001cd4..d67dd3adcb 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4186,7 +4186,14 @@ void LLAppViewer::launchUpdater() delete LLAppViewer::sUpdaterInfo; } LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; - + + // if a sim name was passed in via command line parameter (typically through a SLURL) + if ( LLURLSimString::sInstance.mSimString.length() ) + { + // record the location to start at next time + gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); + }; + #if LL_WINDOWS LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) @@ -4220,13 +4227,6 @@ void LLAppViewer::launchUpdater() return; } - // if a sim name was passed in via command line parameter (typically through a SLURL) - if ( LLURLSimString::sInstance.mSimString.length() ) - { - // record the location to start at next time - gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); - }; - LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; @@ -4238,13 +4238,6 @@ void LLAppViewer::launchUpdater() // see LLAppViewerWin32.cpp #elif LL_DARWIN - // if a sim name was passed in via command line parameter (typically through a SLURL) - if ( LLURLSimString::sInstance.mSimString.length() ) - { - // record the location to start at next time - gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); - }; - LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; @@ -4258,10 +4251,51 @@ void LLAppViewer::launchUpdater() // Run the auto-updater. system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ -#elif LL_LINUX || LL_SOLARIS - OSMessageBox("Automatic updating is not yet implemented for Linux.\n" - "Please download the latest version from www.secondlife.com.", - LLStringUtil::null, OSMB_OK); +#elif (LL_LINUX || LL_SOLARIS) && LL_GTK + // we tell the updater where to find the xml containing string + // translations which it can use for its own UI + std::string xml_strings_file = "strings.xml"; + std::vector xui_path_vec = LLUI::getXUIPaths(); + std::string xml_search_paths; + std::vector::const_iterator iter; + // build comma-delimited list of xml paths to pass to updater + for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); ) + { + std::string this_skin_dir = gDirUtilp->getDefaultSkinDir() + + gDirUtilp->getDirDelimiter() + + (*iter); + llinfos << "Got a XUI path: " << this_skin_dir << llendl; + xml_search_paths.append(this_skin_dir); + ++iter; + if (iter != xui_path_vec.end()) + xml_search_paths.append(","); // comma-delimit + } + // build the overall command-line to run the updater correctly + update_exe_path = + gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + + " --url \"" + update_url.asString() + "\"" + + " --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" + + " --dest \"" + gDirUtilp->getAppRODataDir() + "\"" + + " --stringsdir \"" + xml_search_paths + "\"" + + " --stringsfile \"" + xml_strings_file + "\""; + + LL_INFOS("AppInit") << "Calling updater: " + << update_exe_path << LL_ENDL; + + // *TODO: we could use the gdk equivilant to ensure the updater + // gets started on the same screen. + GError *error = NULL; + if (!g_spawn_command_line_async(update_exe_path.c_str(), &error)) + { + llerrs << "Failed to launch updater: " + << error->message + << llendl; + } + if (error) { + g_error_free(error); + } +#else + OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK); #endif // *REMOVE:Mani - Saving for reference... diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index cb7dbc2de0..2f4d00786c 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -137,6 +137,7 @@ void LLLoginInstance::constructAuthParams(const LLSD& credentials) requested_options.append("event_categories"); requested_options.append("event_notifications"); requested_options.append("classified_categories"); + requested_options.append("adult_compliant"); //requested_options.append("inventory-targets"); requested_options.append("buddy-list"); requested_options.append("ui-config"); @@ -345,8 +346,10 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) #if LL_WINDOWS notification_name += "Windows"; -#else - notification_name += "Mac"; +#elif LL_DARWIN + notification_name += "Mac"; +#else + notification_name += "Linux"; #endif if (mandatory) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8859f1ffb5..6bd0f8d6fa 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1031,7 +1031,6 @@ bool idle_startup() gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); // Update progress status and the display loop. - requested_options.push_back("adult_compliant"); auth_desc = LLTrans::getString("LoginInProgress"); set_startup_status(progress, auth_desc, auth_message); progress += 0.02f; -- cgit v1.3 From 5e4edfb83fbc2dd20415514efa33ba80c7fa1e94 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Tue, 1 Sep 2009 13:12:17 -0400 Subject: Fixups for eol-style copy pasta... --- indra/newview/llappviewer.cpp | 82 +++++++++++++++++++-------------------- indra/newview/lllogininstance.cpp | 6 +-- 2 files changed, 44 insertions(+), 44 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0d4b7d027c..d3c5cfc390 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4251,47 +4251,47 @@ void LLAppViewer::launchUpdater() // Run the auto-updater. system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ -#elif (LL_LINUX || LL_SOLARIS) && LL_GTK - // we tell the updater where to find the xml containing string - // translations which it can use for its own UI - std::string xml_strings_file = "strings.xml"; - std::vector xui_path_vec = LLUI::getXUIPaths(); - std::string xml_search_paths; - std::vector::const_iterator iter; - // build comma-delimited list of xml paths to pass to updater - for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); ) - { - std::string this_skin_dir = gDirUtilp->getDefaultSkinDir() - + gDirUtilp->getDirDelimiter() - + (*iter); - llinfos << "Got a XUI path: " << this_skin_dir << llendl; - xml_search_paths.append(this_skin_dir); - ++iter; - if (iter != xui_path_vec.end()) - xml_search_paths.append(","); // comma-delimit - } - // build the overall command-line to run the updater correctly - update_exe_path = - gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + - " --url \"" + update_url.asString() + "\"" + - " --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" + - " --dest \"" + gDirUtilp->getAppRODataDir() + "\"" + - " --stringsdir \"" + xml_search_paths + "\"" + - " --stringsfile \"" + xml_strings_file + "\""; - - LL_INFOS("AppInit") << "Calling updater: " - << update_exe_path << LL_ENDL; - - // *TODO: we could use the gdk equivilant to ensure the updater - // gets started on the same screen. - GError *error = NULL; - if (!g_spawn_command_line_async(update_exe_path.c_str(), &error)) - { - llerrs << "Failed to launch updater: " - << error->message - << llendl; - } - if (error) { +#elif (LL_LINUX || LL_SOLARIS) && LL_GTK + // we tell the updater where to find the xml containing string + // translations which it can use for its own UI + std::string xml_strings_file = "strings.xml"; + std::vector xui_path_vec = LLUI::getXUIPaths(); + std::string xml_search_paths; + std::vector::const_iterator iter; + // build comma-delimited list of xml paths to pass to updater + for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); ) + { + std::string this_skin_dir = gDirUtilp->getDefaultSkinDir() + + gDirUtilp->getDirDelimiter() + + (*iter); + llinfos << "Got a XUI path: " << this_skin_dir << llendl; + xml_search_paths.append(this_skin_dir); + ++iter; + if (iter != xui_path_vec.end()) + xml_search_paths.append(","); // comma-delimit + } + // build the overall command-line to run the updater correctly + update_exe_path = + gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + + " --url \"" + update_url.asString() + "\"" + + " --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" + + " --dest \"" + gDirUtilp->getAppRODataDir() + "\"" + + " --stringsdir \"" + xml_search_paths + "\"" + + " --stringsfile \"" + xml_strings_file + "\""; + + LL_INFOS("AppInit") << "Calling updater: " + << update_exe_path << LL_ENDL; + + // *TODO: we could use the gdk equivilant to ensure the updater + // gets started on the same screen. + GError *error = NULL; + if (!g_spawn_command_line_async(update_exe_path.c_str(), &error)) + { + llerrs << "Failed to launch updater: " + << error->message + << llendl; + } + if (error) { g_error_free(error); } #else diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 2f4d00786c..e56d28e066 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -346,9 +346,9 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) #if LL_WINDOWS notification_name += "Windows"; -#elif LL_DARWIN - notification_name += "Mac"; -#else +#elif LL_DARWIN + notification_name += "Mac"; +#else notification_name += "Linux"; #endif -- cgit v1.3 From 08f3ea28f5681bbbd755947ec09970c11410bd0a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 11 Sep 2009 22:12:34 -0400 Subject: QAR-1619: Remove unneeded llfloatertos.h #includes. Neither lllogininstance.cpp nor lllogininstance_test.cpp need llfloatertos.h any more, since LLLoginInstance talks to LLFloaterTOS only via LLFloaterReg and LLEventPumps. However, both sources depended on llfloatertos.h dragging in llnotifications.h, so include that explicitly instead of llfloatertos.h. --- indra/newview/lllogininstance.cpp | 2 +- indra/newview/tests/lllogininstance_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index e56d28e066..8bf769a132 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -50,7 +50,7 @@ #include "llviewercontrol.h" #include "llurlsimstring.h" #include "llfloaterreg.h" -#include "llfloatertos.h" +#include "llnotifications.h" #include "llwindow.h" #if LL_LINUX || LL_SOLARIS #include "lltrans.h" diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index a84e796159..75db76df27 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -91,7 +91,7 @@ LLURLSimString LLURLSimString::sInstance; bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- -#include "../llfloatertos.h" +#include "llnotifications.h" #include "llfloaterreg.h" static std::string gTOSType; static LLEventPump * gTOSReplyPump = NULL; -- cgit v1.3 From e3a4e3dc10a96b0822674cea262f41774e55a660 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 9 Oct 2009 19:42:59 -0400 Subject: DEV-40930: Added ["change"] key to login-module status events. Changed existing event calls to use state as "offline" or "online", with "change" indicating the reason for this status event. Changed disconnect() to send state "offline", change "disconnect" -- instead of replaying last auth failure. Changed unit tests accordingly. Changed LLLoginInstance::handleLoginEvent() to use LLEventDispatcher to route calls to handleLoginFailure() et al. Added LLEventDispatcher::get() to allow retrieving Callable by name and testing for empty(). --- indra/llcommon/lleventdispatcher.cpp | 10 +++++++ indra/llcommon/lleventdispatcher.h | 4 +++ indra/newview/lllogininstance.cpp | 34 ++++++++++++---------- indra/newview/lllogininstance.h | 7 +++-- indra/newview/tests/lllogininstance_test.cpp | 7 +++++ indra/viewer_components/login/lllogin.cpp | 29 +++++++++++------- .../viewer_components/login/tests/lllogin_test.cpp | 16 +++++----- 7 files changed, 71 insertions(+), 36 deletions(-) (limited to 'indra/newview/lllogininstance.cpp') diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp index 2dbd59b156..6b1413d054 100644 --- a/indra/llcommon/lleventdispatcher.cpp +++ b/indra/llcommon/lleventdispatcher.cpp @@ -109,6 +109,16 @@ bool LLEventDispatcher::attemptCall(const std::string& name, const LLSD& event) return true; // tell caller we were able to call } +LLEventDispatcher::Callable LLEventDispatcher::get(const std::string& name) const +{ + DispatchMap::const_iterator found = mDispatch.find(name); + if (found == mDispatch.end()) + { + return Callable(); + } + return found->second.first; +} + LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key): LLEventDispatcher(pumpname, key), mPump(pumpname, true), // allow tweaking for uniqueness diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index ef83ebabc1..671f2a4d1c 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -80,6 +80,10 @@ public: /// @a required prototype specified at add() time, die with LL_ERRS. void operator()(const LLSD& event) const; + /// Fetch the Callable for the specified name. If no such name was + /// registered, return an empty() Callable. + Callable get(const std::string& name) const; + private: template void addMethod(const std::string& name, const METHOD& method, const LLSD& required) diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 8bf769a132..e5f347ddc4 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -68,10 +68,14 @@ LLLoginInstance::LLLoginInstance() : mUserInteraction(true), mSkipOptionalUpdate(false), mAttemptComplete(false), - mTransferRate(0.0f) + mTransferRate(0.0f), + mDispatcher("LLLoginInstance", "change") { mLoginModule->getEventPump().listen("lllogininstance", boost::bind(&LLLoginInstance::handleLoginEvent, this, _1)); + mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1)); + mDispatcher.add("connect", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1)); + mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1)); } LLLoginInstance::~LLLoginInstance() @@ -185,9 +189,9 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event) std::cout << "LoginListener called!: \n"; std::cout << event << "\n"; - if(!(event.has("state") && event.has("progress"))) + if(!(event.has("state") && event.has("change") && event.has("progress"))) { - llerrs << "Unknown message from LLLogin!" << llendl; + llerrs << "Unknown message from LLLogin: " << event << llendl; } mLoginState = event["state"].asString(); @@ -198,19 +202,17 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event) mTransferRate = event["transfer_rate"].asReal(); } - if(mLoginState == "offline") + // Call the method registered in constructor, if any, for more specific + // handling + LLEventDispatcher::Callable method(mDispatcher.get(event["change"])); + if (! method.empty()) { - handleLoginFailure(event); + method(event); } - else if(mLoginState == "online") - { - handleLoginSuccess(event); - } - return false; } -bool LLLoginInstance::handleLoginFailure(const LLSD& event) +void LLLoginInstance::handleLoginFailure(const LLSD& event) { // Login has failed. // Figure out why and respond... @@ -264,11 +266,9 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) { attemptComplete(); } - - return false; } -bool LLLoginInstance::handleLoginSuccess(const LLSD& event) +void LLLoginInstance::handleLoginSuccess(const LLSD& event) { if(gSavedSettings.getBOOL("ForceMandatoryUpdate")) { @@ -286,7 +286,11 @@ bool LLLoginInstance::handleLoginSuccess(const LLSD& event) { attemptComplete(); } - return false; +} + +void LLLoginInstance::handleDisconnect(const LLSD& event) +{ + // placeholder } bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 6a2ccf919e..19d7449bc1 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -33,6 +33,7 @@ #ifndef LL_LLLOGININSTANCE_H #define LL_LLLOGININSTANCE_H +#include "lleventdispatcher.h" #include #include class LLLogin; @@ -85,8 +86,9 @@ private: bool updateDialogCallback(const LLSD& notification, const LLSD& response); bool handleLoginEvent(const LLSD& event); - bool handleLoginFailure(const LLSD& event); - bool handleLoginSuccess(const LLSD& event); + void handleLoginFailure(const LLSD& event); + void handleLoginSuccess(const LLSD& event); + void handleDisconnect(const LLSD& event); bool handleTOSResponse(bool v, const std::string& key); @@ -106,6 +108,7 @@ private: int mLastExecEvent; UpdaterLauncherCallback mUpdaterLauncher; boost::scoped_ptr mUpdateAppResponse; + LLEventDispatcher mDispatcher; }; #endif diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 75db76df27..009be35f64 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -225,6 +225,7 @@ namespace tut // Dummy success response. LLSD response; response["state"] = "online"; + response["change"] = "connect"; response["progress"] = 1.0; response["transfer_rate"] = 7; response["data"] = "test_data"; @@ -240,6 +241,7 @@ namespace tut response.clear(); response["state"] = "offline"; + response["change"] = "disconnect"; response["progress"] = 0.0; response["transfer_rate"] = 0; response["data"] = "test_data"; @@ -267,6 +269,7 @@ namespace tut // TOS failure response. LLSD response; response["state"] = "offline"; + response["change"] = "fail.login"; response["progress"] = 0.0; response["transfer_rate"] = 7; response["data"]["reason"] = "tos"; @@ -326,6 +329,7 @@ namespace tut // Update needed failure response. LLSD response; response["state"] = "offline"; + response["change"] = "fail.login"; response["progress"] = 0.0; response["transfer_rate"] = 7; response["data"]["reason"] = "update"; @@ -351,6 +355,7 @@ namespace tut // Update needed failure response. LLSD response; response["state"] = "offline"; + response["change"] = "fail.login"; response["progress"] = 0.0; response["transfer_rate"] = 7; response["data"]["reason"] = "update"; @@ -376,6 +381,7 @@ namespace tut // Update needed failure response. LLSD response; response["state"] = "offline"; + response["change"] = "fail.login"; response["progress"] = 0.0; response["transfer_rate"] = 7; response["data"]["reason"] = "optional"; @@ -401,6 +407,7 @@ namespace tut // Update needed failure response. LLSD response; response["state"] = "offline"; + response["change"] = "fail.login"; response["progress"] = 0.0; response["transfer_rate"] = 7; response["data"]["reason"] = "optional"; diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index c0d35f31d3..7a30315b9a 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -70,10 +70,12 @@ public: LLEventPump& getEventPump() { return mPump; } private: - void sendProgressEvent(const std::string& desc, const LLSD& data = LLSD::emptyMap()) + void sendProgressEvent(const std::string& state, const std::string& change, + const LLSD& data = LLSD()) { LLSD status_data; - status_data["state"] = desc; + status_data["state"] = state; + status_data["change"] = change; status_data["progress"] = 0.0f; if(mAuthResponse.has("transfer_rate")) @@ -81,7 +83,7 @@ private: status_data["transfer_rate"] = mAuthResponse["transfer_rate"]; } - if(data.size() != 0) + if(data.isDefined()) { status_data["data"] = data; } @@ -133,7 +135,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential LLSD rewrittenURIs; { LLEventTimeout filter(replyPump); - sendProgressEvent("srvrequest"); + sendProgressEvent("offline", "srvrequest"); // Request SRV record. LL_INFOS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL; @@ -172,7 +174,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential LLSD progress_data; progress_data["attempt"] = attempts; progress_data["request"] = request; - sendProgressEvent("authenticating", progress_data); + sendProgressEvent("offline", "authenticating", progress_data); // We expect zero or more "Downloading" status events, followed by // exactly one event with some other status. Use postAndWait() the @@ -187,7 +189,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential waitForEventOn(self, replyPump))) { // Still Downloading -- send progress update. - sendProgressEvent("downloading"); + sendProgressEvent("offline", "downloading"); } status = mAuthResponse["status"].asString(); @@ -215,9 +217,14 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential // StatusComplete does not imply auth success. Check the // actual outcome of the request. We've already handled the // "indeterminate" case in the loop above. - sendProgressEvent((mAuthResponse["responses"]["login"].asString() == "true")? - "online" : "offline", - mAuthResponse["responses"]); + if (mAuthResponse["responses"]["login"].asString() == "true") + { + sendProgressEvent("online", "connect", mAuthResponse["responses"]); + } + else + { + sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); + } return; // Done! } // If we don't recognize status at all, trouble @@ -236,12 +243,12 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential // Here we got through all the rewrittenURIs without succeeding. Tell // caller this didn't work out so well. Of course, the only failure data // we can reasonably show are from the last of the rewrittenURIs. - sendProgressEvent("offline", mAuthResponse["responses"]); + sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); } void LLLogin::Impl::disconnect() { - sendProgressEvent("offline", mAuthResponse["responses"]); + sendProgressEvent("offline", "disconnect"); } //********************* diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp index 51f00c8344..a8ae2883d5 100644 --- a/indra/viewer_components/login/tests/lllogin_test.cpp +++ b/indra/viewer_components/login/tests/lllogin_test.cpp @@ -265,12 +265,12 @@ namespace tut login.connect("login.bar.com", credentials); - ensure_equals("SRV state", listener.lastEvent()["state"].asString(), "srvrequest"); + ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); dummyLLAres.sendReply(); // Test Authenticating State prior to first response. - ensure_equals("Auth state 1", listener.lastEvent()["state"].asString(), "authenticating"); + ensure_equals("Auth state 1", listener.lastEvent()["change"].asString(), "authenticating"); ensure_equals("Attempt 1", listener.lastEvent()["data"]["attempt"].asInteger(), 1); ensure_equals("URI 1", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.foo.com"); @@ -285,7 +285,7 @@ namespace tut dummyXMLRPC.setResponse(data); dummyXMLRPC.sendReply(); - ensure_equals("Fail back to authenticate 1", listener.lastEvent()["state"].asString(), "authenticating"); + ensure_equals("Fail back to authenticate 1", listener.lastEvent()["change"].asString(), "authenticating"); ensure_equals("Attempt 2", listener.lastEvent()["data"]["attempt"].asInteger(), 2); ensure_equals("URI 2", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com"); @@ -301,7 +301,7 @@ namespace tut dummyXMLRPC.setResponse(data); dummyXMLRPC.sendReply(); - ensure_equals("Fail back to authenticate 2", listener.lastEvent()["state"].asString(), "authenticating"); + ensure_equals("Fail back to authenticate 2", listener.lastEvent()["change"].asString(), "authenticating"); ensure_equals("Attempt 3", listener.lastEvent()["data"]["attempt"].asInteger(), 3); ensure_equals("URI 3", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.indeterminate.com"); @@ -350,11 +350,11 @@ namespace tut login.connect("login.bar.com", credentials); - ensure_equals("SRV state", listener.lastEvent()["state"].asString(), "srvrequest"); + ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); dummyLLAres.sendReply(); - ensure_equals("Auth state", listener.lastEvent()["state"].asString(), "authenticating"); + ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); // Send the failed auth request reponse LLSD data; @@ -397,11 +397,11 @@ namespace tut login.connect("login.bar.com", credentials); - ensure_equals("SRV state", listener.lastEvent()["state"].asString(), "srvrequest"); + ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); dummyLLAres.sendReply(); - ensure_equals("Auth state", listener.lastEvent()["state"].asString(), "authenticating"); + ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); // Send the failed auth request reponse LLSD data; -- cgit v1.3