summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Palange (Mani) <palange@lindenlab.com>2010-11-10 14:26:14 -0800
committerMark Palange (Mani) <palange@lindenlab.com>2010-11-10 14:26:14 -0800
commitb2e84d739b4f5c00b497e57e892fc10d78af8b76 (patch)
treef035b0be5134c0286f4af7d4f5835ea533ec2e3f
parentf42bb00627f756b277496ec203d567cac31b3438 (diff)
CHOP-151 Adding startup updater flow to drive update installation and resume.
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/viewer_components/updater/CMakeLists.txt7
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.h5
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp111
-rw-r--r--indra/viewer_components/updater/llupdaterservice.h20
-rw-r--r--indra/viewer_components/updater/tests/llupdaterservice_test.cpp71
6 files changed, 195 insertions, 21 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 6bb25969a6..335998767c 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2341,7 +2341,7 @@ void LLAppViewer::initUpdater()
std::string service_path = gSavedSettings.getString("UpdaterServicePath");
U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");
- mUpdater->setParams(protocol_version, url, service_path, channel, version);
+ mUpdater->initialize(protocol_version, url, service_path, channel, version);
mUpdater->setCheckPeriod(check_period);
if(gSavedSettings.getBOOL("UpdaterServiceActive"))
{
diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt
index 64a0f98c2a..980599dd48 100644
--- a/indra/viewer_components/updater/CMakeLists.txt
+++ b/indra/viewer_components/updater/CMakeLists.txt
@@ -57,10 +57,13 @@ if(LL_TESTS)
llupdaterservice.cpp
)
-# set_source_files_properties(
+# *NOTE:Mani - I was trying to use the preprocessor seam to mock out
+# llifstream (and other) llcommon classes. I didn't work
+# because of the windows declspec(dllimport)attribute.
+#set_source_files_properties(
# llupdaterservice.cpp
# PROPERTIES
-# LL_TEST_ADDITIONAL_LIBRARIES "${PTH_LIBRARIES}"
+# LL_TEST_ADDITIONAL_CFLAGS "-Dllifstream=llus_mock_llifstream"
# )
LL_ADD_PROJECT_UNIT_TESTS(llupdaterservice "${llupdater_service_TEST_SOURCE_FILES}")
diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h
index dc8ecc378a..fb628c99eb 100644
--- a/indra/viewer_components/updater/llupdatedownloader.h
+++ b/indra/viewer_components/updater/llupdatedownloader.h
@@ -71,6 +71,11 @@ class LLUpdateDownloader::Client {
public:
// The download has completed successfully.
+ // data is a map containing the following items:
+ // url - source (remote) location
+ // hash - the md5 sum that should match the installer file.
+ // path - destination (local) location
+ // size - the size of the installer in bytes
virtual void downloadComplete(LLSD const & data) = 0;
// The download failed.
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 4292da1528..4eb317e668 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -33,12 +33,26 @@
#include <boost/scoped_ptr.hpp>
#include <boost/weak_ptr.hpp>
+#include "lldir.h"
+#include "llsdserialize.h"
+#include "llfile.h"
#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif
-boost::weak_ptr<LLUpdaterServiceImpl> gUpdater;
+
+namespace
+{
+ boost::weak_ptr<LLUpdaterServiceImpl> gUpdater;
+
+ const std::string UPDATE_MARKER_FILENAME("SecondLifeUpdateReady.xml");
+ std::string update_marker_path()
+ {
+ return gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+ UPDATE_MARKER_FILENAME);
+ }
+}
class LLUpdaterServiceImpl :
public LLUpdateChecker::Client,
@@ -59,7 +73,7 @@ class LLUpdaterServiceImpl :
LLUpdateDownloader mUpdateDownloader;
LLTimer mTimer;
- void retry(void);
+ LLUpdaterService::app_exit_callback_t mAppExitCallback;
LOG_CLASS(LLUpdaterServiceImpl);
@@ -67,7 +81,7 @@ public:
LLUpdaterServiceImpl();
virtual ~LLUpdaterServiceImpl();
- void setParams(const std::string& protocol_version,
+ void initialize(const std::string& protocol_version,
const std::string& url,
const std::string& path,
const std::string& channel,
@@ -79,6 +93,11 @@ public:
void stopChecking();
bool isChecking();
+ void setAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { mAppExitCallback = aecb;}
+
+ bool checkForInstall(); // Test if a local install is ready.
+ bool checkForResume(); // Test for resumeable d/l.
+
// LLUpdateChecker::Client:
virtual void error(std::string const & message);
virtual void optionalUpdate(std::string const & newVersion,
@@ -90,10 +109,14 @@ public:
virtual void upToDate(void);
// LLUpdateDownloader::Client
- void downloadComplete(LLSD const & data) { retry(); }
- void downloadError(std::string const & message) { retry(); }
+ void downloadComplete(LLSD const & data);
+ void downloadError(std::string const & message);
bool onMainLoop(LLSD const & event);
+
+private:
+ void retry(void);
+
};
const std::string LLUpdaterServiceImpl::sListenerName = "LLUpdaterServiceImpl";
@@ -112,8 +135,8 @@ LLUpdaterServiceImpl::~LLUpdaterServiceImpl()
LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
}
-void LLUpdaterServiceImpl::setParams(const std::string& protocol_version,
- const std::string& url,
+void LLUpdaterServiceImpl::initialize(const std::string& protocol_version,
+ const std::string& url,
const std::string& path,
const std::string& channel,
const std::string& version)
@@ -129,6 +152,12 @@ void LLUpdaterServiceImpl::setParams(const std::string& protocol_version,
mPath = path;
mChannel = channel;
mVersion = version;
+
+ // Check to see if an install is ready.
+ if(!checkForInstall())
+ {
+ checkForResume();
+ }
}
void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds)
@@ -146,7 +175,7 @@ void LLUpdaterServiceImpl::startChecking()
"LLUpdaterService::startCheck().");
}
mIsChecking = true;
-
+
mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion);
}
}
@@ -164,6 +193,45 @@ bool LLUpdaterServiceImpl::isChecking()
return mIsChecking;
}
+bool LLUpdaterServiceImpl::checkForInstall()
+{
+ bool result = false; // return true if install is found.
+
+ llifstream update_marker(update_marker_path(),
+ std::ios::in | std::ios::binary);
+
+ if(update_marker.is_open())
+ {
+ // Found an update info - now lets see if its valid.
+ LLSD update_info;
+ LLSDSerialize::fromXMLDocument(update_info, update_marker);
+
+ // Get the path to the installer file.
+ LLSD path = update_info.get("path");
+ if(path.isDefined() && !path.asString().empty())
+ {
+ // install!
+ }
+
+ update_marker.close();
+ LLFile::remove(update_marker_path());
+ result = true;
+ }
+ return result;
+}
+
+bool LLUpdaterServiceImpl::checkForResume()
+{
+ bool result = false;
+ llstat stat_info;
+ if(0 == LLFile::stat(mUpdateDownloader.downloadMarkerPath(), &stat_info))
+ {
+ mUpdateDownloader.resume();
+ result = true;
+ }
+ return false;
+}
+
void LLUpdaterServiceImpl::error(std::string const & message)
{
retry();
@@ -188,6 +256,24 @@ void LLUpdaterServiceImpl::upToDate(void)
retry();
}
+void LLUpdaterServiceImpl::downloadComplete(LLSD const & data)
+{
+ // Save out the download data to the SecondLifeUpdateReady
+ // marker file.
+ llofstream update_marker(update_marker_path());
+ LLSDSerialize::toPrettyXML(data, update_marker);
+
+ // Stop checking.
+ stopChecking();
+
+ // Wait for restart...?
+}
+
+void LLUpdaterServiceImpl::downloadError(std::string const & message)
+{
+ retry();
+}
+
void LLUpdaterServiceImpl::retry(void)
{
LL_INFOS("UpdaterService") << "will check for update again in " <<
@@ -233,13 +319,13 @@ LLUpdaterService::~LLUpdaterService()
{
}
-void LLUpdaterService::setParams(const std::string& protocol_version,
+void LLUpdaterService::initialize(const std::string& protocol_version,
const std::string& url,
const std::string& path,
const std::string& channel,
const std::string& version)
{
- mImpl->setParams(protocol_version, url, path, channel, version);
+ mImpl->initialize(protocol_version, url, path, channel, version);
}
void LLUpdaterService::setCheckPeriod(unsigned int seconds)
@@ -261,3 +347,8 @@ bool LLUpdaterService::isChecking()
{
return mImpl->isChecking();
}
+
+void LLUpdaterService::setImplAppExitCallback(LLUpdaterService::app_exit_callback_t aecb)
+{
+ return mImpl->setAppExitCallback(aecb);
+}
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
index 04adf461b6..42ec3a2cab 100644
--- a/indra/viewer_components/updater/llupdaterservice.h
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -27,6 +27,7 @@
#define LL_UPDATERSERVICE_H
#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
class LLUpdaterServiceImpl;
@@ -42,11 +43,11 @@ public:
LLUpdaterService();
~LLUpdaterService();
- void setParams(const std::string& protocol_version,
- const std::string& url,
- const std::string& path,
- const std::string& channel,
- const std::string& version);
+ void initialize(const std::string& protocol_version,
+ const std::string& url,
+ const std::string& path,
+ const std::string& channel,
+ const std::string& version);
void setCheckPeriod(unsigned int seconds);
@@ -54,8 +55,17 @@ public:
void stopChecking();
bool isChecking();
+ typedef boost::function<void (void)> app_exit_callback_t;
+ template <typename F>
+ void setAppExitCallback(F const &callable)
+ {
+ app_exit_callback_t aecb = callable;
+ setImplAppExitCallback(aecb);
+ }
+
private:
boost::shared_ptr<LLUpdaterServiceImpl> mImpl;
+ void setImplAppExitCallback(app_exit_callback_t aecb);
};
#endif // LL_UPDATERSERVICE_H
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
index 7f45ae51fb..57732ad0a5 100644
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -36,6 +36,7 @@
#include "../../../test/debug.h"
#include "llevents.h"
+#include "lldir.h"
/*****************************************************************************
* MOCK'd
@@ -48,6 +49,70 @@ void LLUpdateChecker::check(std::string const & protocolVersion, std::string con
LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
void LLUpdateDownloader::download(LLURI const & , std::string const &){}
+class LLDir_Mock : public LLDir
+{
+ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir = "") {}
+ U32 countFilesInDir(const std::string &dirname, const std::string &mask)
+ {
+ return 0;
+ }
+
+ BOOL getNextFileInDir(const std::string &dirname,
+ const std::string &mask,
+ std::string &fname, BOOL wrap)
+ {
+ return false;
+ }
+ void getRandomFileInDir(const std::string &dirname,
+ const std::string &mask,
+ std::string &fname) {}
+ std::string getCurPath() { return ""; }
+ BOOL fileExists(const std::string &filename) const { return false; }
+ std::string getLLPluginLauncher() { return ""; }
+ std::string getLLPluginFilename(std::string base_name) { return ""; }
+
+} gDirUtil;
+LLDir* gDirUtilp = &gDirUtil;
+LLDir::LLDir() {}
+LLDir::~LLDir() {}
+S32 LLDir::deleteFilesInDir(const std::string &dirname,
+ const std::string &mask)
+{ return 0; }
+
+void LLDir::setChatLogsDir(const std::string &path){}
+void LLDir::setPerAccountChatLogsDir(const std::string &username){}
+void LLDir::setLindenUserDir(const std::string &username){}
+void LLDir::setSkinFolder(const std::string &skin_folder){}
+bool LLDir::setCacheDir(const std::string &path){ return true; }
+void LLDir::dumpCurrentDirectories() {}
+
+std::string LLDir::getExpandedFilename(ELLPath location,
+ const std::string &filename) const
+{
+ return "";
+}
+
+std::string LLUpdateDownloader::downloadMarkerPath(void)
+{
+ return "";
+}
+
+void LLUpdateDownloader::resume(void) {}
+
+/*
+#pragma warning(disable: 4273)
+llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename,
+ ios_base::openmode _Mode,
+ int _Prot) :
+ std::basic_istream<char,std::char_traits< char > >(NULL,true)
+{}
+
+llus_mock_llifstream::~llus_mock_llifstream() {}
+bool llus_mock_llifstream::is_open() const {return true;}
+void llus_mock_llifstream::close() {}
+*/
+
/*****************************************************************************
* TUT
*****************************************************************************/
@@ -96,9 +161,9 @@ namespace tut
bool got_usage_error = false;
try
{
- updater.setParams("1.0",test_url, "update" ,test_channel, test_version);
+ updater.initialize("1.0",test_url, "update" ,test_channel, test_version);
updater.startChecking();
- updater.setParams("1.0", "other_url", "update", test_channel, test_version);
+ updater.initialize("1.0", "other_url", "update", test_channel, test_version);
}
catch(LLUpdaterService::UsageError)
{
@@ -112,7 +177,7 @@ namespace tut
{
DEBUG;
LLUpdaterService updater;
- updater.setParams("1.0", test_url, "update", test_channel, test_version);
+ updater.initialize("1.0", test_url, "update", test_channel, test_version);
updater.startChecking();
ensure(updater.isChecking());
updater.stopChecking();