CHOP-151 Adding startup updater flow to drive update installation and resume.

meow-7.2.2
Mark Palange (Mani) 2010-11-10 14:26:14 -08:00
parent f42bb00627
commit b2e84d739b
6 changed files with 195 additions and 21 deletions

View File

@ -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"))
{

View File

@ -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}")

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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();