summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llnotifications.h13
-rw-r--r--indra/llui/llnotificationslistener.cpp29
-rw-r--r--indra/llui/llnotificationslistener.h5
-rw-r--r--indra/newview/CMakeLists.txt1
-rw-r--r--indra/newview/llappviewer.cpp110
-rw-r--r--indra/newview/llappviewer.h4
-rw-r--r--indra/newview/llfloatertos.cpp2
-rw-r--r--indra/newview/lllogininstance.cpp184
-rw-r--r--indra/newview/lllogininstance.h34
-rw-r--r--indra/newview/llpanellogin.cpp3
-rw-r--r--indra/newview/llstartup.cpp11
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp413
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(&notifications);
+ }
+
+ 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);
+ }
+}