diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llui/llnotifications.h | 13 | ||||
-rw-r--r-- | indra/llui/llnotificationslistener.cpp | 29 | ||||
-rw-r--r-- | indra/llui/llnotificationslistener.h | 5 | ||||
-rw-r--r-- | indra/newview/CMakeLists.txt | 1 | ||||
-rw-r--r-- | indra/newview/llappviewer.cpp | 110 | ||||
-rw-r--r-- | indra/newview/llappviewer.h | 4 | ||||
-rw-r--r-- | indra/newview/llfloatertos.cpp | 2 | ||||
-rw-r--r-- | indra/newview/lllogininstance.cpp | 184 | ||||
-rw-r--r-- | indra/newview/lllogininstance.h | 34 | ||||
-rw-r--r-- | indra/newview/llpanellogin.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llstartup.cpp | 11 | ||||
-rw-r--r-- | indra/newview/llviewermenu.cpp | 2 | ||||
-rw-r--r-- | indra/newview/tests/lllogininstance_test.cpp | 413 |
13 files changed, 661 insertions, 150 deletions
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<LLNotifications>, 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 d6e552ca5c..75f4d6177d 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(&LLNotificationsListener::NotificationResponder, + this, + event_data["reply"].asString(), + _1, _2 + ) + ); + } + else + { + mNotifications.add(event_data["name"], + event_data["substitutions"], + event_data["payload"]); + } +} + +void LLNotificationsListener::NotificationResponder(const std::string& reply_pump, + const LLSD& notification, + const LLSD& response) const +{ + LLSD reponse_event; + reponse_event["notification"] = notification; + reponse_event["response"] = response; + LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); } diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index 3576cacbdb..6f71a7c781 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) const; + 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 844a72378c..d0a934c87e 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..c08cc2baae 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" @@ -60,6 +59,7 @@ std::string construct_start_string(); LLLoginInstance::LLLoginInstance() : mLoginModule(new LLLogin()), + mNotifications(NULL), mLoginState("offline"), mUserInteraction(true), mSkipOptionalUpdate(false), @@ -74,7 +74,6 @@ LLLoginInstance::~LLLoginInstance() { } - void LLLoginInstance::connect(const LLSD& credentials) { std::vector<std::string> uris; @@ -84,6 +83,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 +99,7 @@ void LLLoginInstance::reconnect() void LLLoginInstance::disconnect() { + mAttemptComplete = false; // Reset attempt complete at this point! mRequestData.clear(); mLoginModule->disconnect(); } @@ -162,12 +163,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 +221,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 +258,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 +282,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,9 +345,34 @@ 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)); + + 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; + 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) @@ -395,114 +421,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 +450,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..47d52a6184 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -34,7 +34,10 @@ #define LL_LLLOGININSTANCE_H #include <boost/scoped_ptr.hpp> +#include <boost/function.hpp> class LLLogin; +class LLEventStream; +class LLNotificationsInterface; // This class hosts the login module and is used to // negotiate user authentication attempts. @@ -49,7 +52,17 @@ public: void reconnect(); // reconnect using the current credentials. void disconnect(); - // Set whether this class will drive user interaction. + bool authFailure() { return mAttemptComplete && mLoginState == "offline"; } + bool authSuccess() { return mAttemptComplete && mLoginState == "online"; } + + const std::string& getLoginState() { return mLoginState; } + LLSD getResponse(const std::string& key) { return getResponse()[key]; } + LLSD getResponse(); + + // 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; } @@ -58,16 +71,13 @@ public: // 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"; } + void setSerialNumber(const std::string& sn) { mSerialNumber = sn; } + void setLastExecEvent(int lee) { mLastExecEvent = lee; } - const std::string& getLoginState() { return mLoginState; } - LLSD getResponse(const std::string& key) { return getResponse()[key]; } - LLSD getResponse(); + void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; } - // Only valid when authSuccess == true. - const F64 getLastTransferRateBPS() { return mTransferRate; } + typedef boost::function<void()> UpdaterLauncherCallback; + void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; } private: void constructAuthParams(const LLSD& credentials); @@ -83,6 +93,8 @@ private: void attemptComplete() { mAttemptComplete = true; } // In the future an event? boost::scoped_ptr<LLLogin> mLoginModule; + LLNotificationsInterface* mNotifications; + std::string mLoginState; LLSD mRequestData; LLSD mResponseData; @@ -90,6 +102,10 @@ private: bool mSkipOptionalUpdate; bool mAttemptComplete; F64 mTransferRate; + std::string mSerialNumber; + int mLastExecEvent; + UpdaterLauncherCallback mUpdaterLauncher; + boost::scoped_ptr<LLEventStream> 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..eb585f8fe3 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -965,13 +965,18 @@ bool idle_startup() display_startup(); // Setting initial values... + LLLoginInstance* login = LLLoginInstance::getInstance(); + login->setNotificationsInterface(LLNotifications::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 +984,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 *) 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<std::string>& 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<LLControlGroup, std::string>(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<void (const LLSD&, const LLSD&)> 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_data> 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);
+ }
+}
|