diff options
33 files changed, 1654 insertions, 72 deletions
| diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 8d4969a49e..d01e1869b6 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -22,7 +22,10 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")  include(Variables)  if (DARWIN) -  cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR) +  # 2.6.4 fixes a Mac bug in get_target_property(... "SLPlugin" LOCATION): +  # before that version it returns "pathname/SLPlugin", whereas the correct +  # answer is "pathname/SLPlugin.app/Contents/MacOS/SLPlugin". +  cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)  endif (DARWIN)  if (NOT CMAKE_BUILD_TYPE) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index a114d6e778..db2cdb5ff8 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -38,10 +38,10 @@ if (WINDOWS)    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP"        CACHE STRING "C++ compiler debug options" FORCE)    set(CMAKE_CXX_FLAGS_RELWITHDEBINFO  -      "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP" +      "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP /Ob2"        CACHE STRING "C++ compiler release-with-debug options" FORCE)    set(CMAKE_CXX_FLAGS_RELEASE -      "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP" +      "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /Ob2"        CACHE STRING "C++ compiler release options" FORCE)    set(CMAKE_CXX_STANDARD_LIBRARIES "") diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bf885e5934..f18107f673 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -64,6 +64,7 @@ include_directories(      ${LSCRIPT_INCLUDE_DIRS}      ${LSCRIPT_INCLUDE_DIRS}/lscript_compile      ${LLLOGIN_INCLUDE_DIRS} +    ${UPDATER_INCLUDE_DIRS}      )  set(viewer_SOURCE_FILES @@ -1679,6 +1680,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}      ${OPENSSL_LIBRARIES}      ${CRYPTO_LIBRARIES}      ${LLLOGIN_LIBRARIES} +    ${UPDATER_LIBRARIES}      ${GOOGLE_PERFTOOLS_LIBRARIES}      ) @@ -1829,10 +1831,18 @@ if (PACKAGE)      set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)    endif (LINUX) +  if(CMAKE_CONFIGURATION_TYPES) +      # set LLBUILD_CONFIG to be a shell variable evaluated at build time +      # reflecting the configuration we are currently building. +      set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR}) +  else(CMAKE_CONFIGURATION_TYPES) +      set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) +  endif(CMAKE_CONFIGURATION_TYPES)    add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"      COMMAND "${PYTHON_EXECUTABLE}"      ARGS        "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" +      "${LLBUILD_CONFIG}"        "${VIEWER_DIST_DIR}"        "${VIEWER_EXE_GLOBS}"        "${VIEWER_LIB_GLOB}" @@ -1841,7 +1851,7 @@ if (PACKAGE)      DEPENDS generate_breakpad_symbols.py      VERBATIM    ) -  add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}") +  add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}")    add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}")    add_dependencies(package generate_breakpad_symbols)  endif (PACKAGE) @@ -1856,6 +1866,7 @@ if (LL_TESTS)      llmediadataclient.cpp      lllogininstance.cpp      llviewerhelputil.cpp +    llversioninfo.cpp    )    ################################################## diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index ba3b6a42a4..dcd574d6b8 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -361,8 +361,7 @@      <map>        <key>count</key>        <integer>1</integer> -      <key>map-to</key> -      <string>VersionChannelName</string> +      <!-- Special case. Not mapped to a setting. -->      </map>      <key>loginpage</key> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 3f23fee865..99c731d77f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11046,7 +11046,62 @@        <key>Value</key>        <integer>15</integer>      </map> -	<key>UploadBakedTexOld</key> +    <key>UpdaterServiceActive</key> +    <map> +      <key>Comment</key> +      <string>Enable or disable the updater service.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map> +    <key>UpdaterServiceCheckPeriod</key> +    <map> +      <key>Comment</key> +      <string>Default period between update checking.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>3600</integer> +    </map> +    <key>UpdaterServiceURL</key> +    <map> +      <key>Comment</key> +      <string>Default location for the updater service.</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://update.secondlife.com</string> +    </map> +    <key>UpdaterServicePath</key> +    <map> +      <key>Comment</key> +      <string>Path on the update server host.</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>update</string> +    </map> +    <key>UpdaterServiceProtocolVersion</key> +    <map> +      <key>Comment</key> +      <string>The update protocol version to use.</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>v1.0</string> +    </map> +    <key>UploadBakedTexOld</key>      <map>        <key>Comment</key>        <string>Forces the baked texture pipeline to upload using the old method.</string> @@ -11377,17 +11432,6 @@        <key>Value</key>        <integer>0</integer>      </map> -    <key>VersionChannelName</key> -    <map> -      <key>Comment</key> -      <string>Versioning Channel Name.</string> -      <key>Persist</key> -      <integer>0</integer> -      <key>Type</key> -      <string>String</string> -      <key>Value</key> -      <string>Second Life Release</string> -    </map>      <key>VertexShaderEnable</key>      <map>        <key>Comment</key> diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index 8f2dfd2348..0e61bee1ef 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -45,8 +45,12 @@ class MissingModuleError(Exception):          Exception.__init__(self, "Failed to find required modules: %r" % modules)          self.modules = modules -def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): -    print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) +def main(configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): +    print "generate_breakpad_symbols run with args: %s" % str((configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + +    if configuration != "Release": +        print "skipping breakpad symbol generation for non-release build." +        return 0      # split up list of viewer_exes      # "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin'] @@ -122,7 +126,7 @@ def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_fil      return 0  if __name__ == "__main__": -    if len(sys.argv) != 6: +    if len(sys.argv) != 7:          usage()          sys.exit(1)      sys.exit(main(*sys.argv[1:])) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 60ed37bdfb..c0ec15f436 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -83,6 +83,7 @@  #include "llweb.h"  #include "llsecondlifeurls.h" +#include "llupdaterservice.h"  // Linden library includes  #include "llavatarnamecache.h" @@ -581,7 +582,8 @@ LLAppViewer::LLAppViewer() :  	mAgentRegionLastAlive(false),  	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),  	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)), -	mFastTimerLogThread(NULL) +	mFastTimerLogThread(NULL), +	mUpdater(new LLUpdaterService())  {  	if(NULL != sInstance)  	{ @@ -657,11 +659,6 @@ bool LLAppViewer::init()      initThreads();      writeSystemInfo(); -	// Build a string representing the current version number. -    gCurrentVersion = llformat("%s %s",  -							   gSavedSettings.getString("VersionChannelName").c_str(), -							   LLVersionInfo::getVersion().c_str()); -  	//////////////////////////////////////////////////////////////////////////////  	//////////////////////////////////////////////////////////////////////////////  	////////////////////////////////////////////////////////////////////////////// @@ -900,7 +897,8 @@ bool LLAppViewer::init()  	gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();  	// Save the current version to the prefs file -	gSavedSettings.setString("LastRunVersion", gCurrentVersion); +	gSavedSettings.setString("LastRunVersion",  +							 LLVersionInfo::getVersionAndChannel());  	gSimLastTime = gRenderStartTime.getElapsedTimeF32();  	gSimFrames = (F32)gFrameCount; @@ -975,7 +973,10 @@ bool LLAppViewer::mainLoop()  	gServicePump = new LLPumpIO(gAPRPoolp);  	LLHTTPClient::setPump(*gServicePump);  	LLCurl::setCAFile(gDirUtilp->getCAFile()); - +	 +	// Initialize updater service (now that we have an io pump) +	initUpdater(); +	  	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.  	LLVoiceChannel::initClass(); @@ -1964,8 +1965,6 @@ bool LLAppViewer::initConfiguration()  	gSavedSettings.setString("ClientSettingsFile",           gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global"))); -	gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel()); -  #ifndef	LL_RELEASE_FOR_DOWNLOAD  	// provide developer build only overrides for these control variables that are not  	// persisted to settings.xml @@ -2106,6 +2105,11 @@ bool LLAppViewer::initConfiguration()          }      } +    if(clp.hasOption("channel")) +    { +		LLVersionInfo::resetChannel(clp.getOption("channel")[0]); +	} +	  	// If we have specified crash on startup, set the global so we'll trigger the crash at the right time  	if(clp.hasOption("crashonstartup")) @@ -2361,6 +2365,26 @@ bool LLAppViewer::initConfiguration()  	return true; // Config was successful.  } +void LLAppViewer::initUpdater() +{ +	// Initialize the updater service. +	// Generate URL to the udpater service +	// Get Channel +	// Get Version +	std::string url = gSavedSettings.getString("UpdaterServiceURL"); +	std::string channel = LLVersionInfo::getChannel(); +	std::string version = LLVersionInfo::getVersion(); +	std::string protocol_version = gSavedSettings.getString("UpdaterServiceProtocolVersion"); +	std::string service_path = gSavedSettings.getString("UpdaterServicePath"); +	U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod"); + +	mUpdater->setParams(protocol_version, url, service_path, channel, version); +	mUpdater->setCheckPeriod(check_period); +	if(gSavedSettings.getBOOL("UpdaterServiceActive")) +	{ +		mUpdater->startChecking(); +	} +}  void LLAppViewer::checkForCrash(void)  { @@ -2552,7 +2576,7 @@ void LLAppViewer::writeSystemInfo()  {  	gDebugInfo["SLLog"] = LLError::logFileName(); -	gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); +	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();  	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();  	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();  	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch(); @@ -2655,7 +2679,7 @@ void LLAppViewer::handleViewerCrash()  	//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version  	//to check against no matter what -	gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); +	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();  	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();  	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); @@ -4382,7 +4406,7 @@ void LLAppViewer::handleLoginComplete()  	initMainloopTimeout("Mainloop Init");  	// Store some data to DebugInfo in case of a freeze. -	gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); +	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();  	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();  	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); @@ -4488,7 +4512,7 @@ void LLAppViewer::launchUpdater()  	// *TODO change userserver to be grid on both viewer and sim, since  	// userserver no longer exists.  	query_map["userserver"] = LLGridManager::getInstance()->getGridLabel(); -	query_map["channel"] = gSavedSettings.getString("VersionChannelName"); +	query_map["channel"] = LLVersionInfo::getChannel();  	// *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); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index a40cd83182..118f1c6dad 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -39,7 +39,7 @@ class LLTextureCache;  class LLImageDecodeThread;  class LLTextureFetch;  class LLWatchdogTimeout; -class LLCommandLineParser; +class LLUpdaterService;  struct apr_dso_handle_t; @@ -186,7 +186,7 @@ private:  	bool initThreads(); // Initialize viewer threads, return false on failure.  	bool initConfiguration(); // Initialize settings from the command line/config file. - +	void initUpdater(); // Initialize the updater service.  	bool initCache(); // Initialize local client cache. @@ -262,7 +262,14 @@ private:  	U32 mAvailPhysicalMemInKB ;  	U32 mAvailVirtualMemInKB ; +	 +	boost::scoped_ptr<LLUpdaterService> mUpdater; + +	//--------------------------------------------- +	//*NOTE: Mani - legacy updater stuff +	// Still useable?  public: +  	//some information for updater  	typedef struct  	{ @@ -272,6 +279,7 @@ public:  	static LLUpdaterInfo *sUpdaterInfo ;  	void launchUpdater(); +	//---------------------------------------------  };  // consts from viewer.h diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index 2b92b228b3..b4a1457f47 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -166,7 +166,7 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo()  		gAgent.getSecureSessionID().asString());  	keywordArgs.appendString("language", LLUI::getLanguage());  	keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy); -	keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName")); +	keywordArgs.appendString("viewerChannel", LLVersionInfo::getChannel());  	keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());  	keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());  	keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch()); @@ -241,7 +241,7 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)  	{  		keywordArgs.appendString("password", password);  	} -	keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName")); +	keywordArgs.appendString("viewerChannel", LLVersionInfo::getChannel());  	keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());  	keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());  	keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch()); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 135137069c..8ae3ccbae3 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -213,7 +213,7 @@ LLSD LLFloaterAbout::getInfo()  	info["VIEWER_VERSION_STR"] = LLVersionInfo::getVersion();  	info["BUILD_DATE"] = __DATE__;  	info["BUILD_TIME"] = __TIME__; -	info["CHANNEL"] = gSavedSettings.getString("VersionChannelName"); +	info["CHANNEL"] = LLVersionInfo::getChannel();  	info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url(); @@ -291,7 +291,7 @@ static std::string get_viewer_release_notes_url()  	std::string url = LLTrans::getString("RELEASE_NOTES_BASE_URL");  	if (! LLStringUtil::endsWith(url, "/"))  		url += "/"; -	url += gSavedSettings.getString("VersionChannelName") + "/"; +	url += LLVersionInfo::getChannel() + "/";  	url += LLVersionInfo::getShortVersion();  	return LLWeb::escapeURL(url);  } diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 029e700c4c..fe84aca147 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -42,6 +42,7 @@  // newview  #include "llviewernetwork.h"  #include "llviewercontrol.h" +#include "llversioninfo.h"  #include "llslurl.h"  #include "llstartup.h"  #include "llfloaterreg.h" @@ -181,8 +182,8 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia  	request_params["read_critical"] = false; // handleTOSResponse  	request_params["last_exec_event"] = mLastExecEvent;  	request_params["mac"] = hashed_unique_id_string; -	request_params["version"] = gCurrentVersion; // Includes channel name -	request_params["channel"] = gSavedSettings.getString("VersionChannelName"); +	request_params["version"] = LLVersionInfo::getVersionAndChannel(); // Includes channel name +	request_params["channel"] = LLVersionInfo::getChannel();  	request_params["id0"] = mSerialNumber;  	mRequestData.clear(); diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 6658e1d7e8..d38bb5aa4a 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -552,7 +552,7 @@ LLPanelStandStopFlying::LLPanelStandStopFlying() :  }  // static -inline LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance() +LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()  {  	static LLPanelStandStopFlying* panel = getStandStopFlyingPanel();  	return panel; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 467aefc60f..cf567fb208 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -230,7 +230,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  	getChild<LLPanel>("login")->setDefaultBtn("connect_btn"); -	std::string channel = gSavedSettings.getString("VersionChannelName"); +	std::string channel = LLVersionInfo::getChannel();  	std::string version = llformat("%s (%d)",  								   LLVersionInfo::getShortVersion().c_str(),  								   LLVersionInfo::getBuild()); @@ -817,7 +817,7 @@ void LLPanelLogin::loadLoginPage()  								   LLVersionInfo::getShortVersion().c_str(),  								   LLVersionInfo::getBuild()); -	char* curl_channel = curl_escape(gSavedSettings.getString("VersionChannelName").c_str(), 0); +	char* curl_channel = curl_escape(LLVersionInfo::getChannel().c_str(), 0);  	char* curl_version = curl_escape(version.c_str(), 0);  	oStr << "&channel=" << curl_channel; diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 050e34ade9..8ccfdb071b 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -36,7 +36,7 @@  #include "llbufferstream.h"  #include "llui.h" -#include "llversionviewer.h" +#include "llversioninfo.h"  #include "llviewercontrol.h"  #include "jsoncpp/reader.h" @@ -64,11 +64,11 @@ void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std  	getTranslateUrl(url, from_lang, to_lang, mesg);      std::string user_agent = llformat("%s %d.%d.%d (%d)", -		LL_CHANNEL, -		LL_VERSION_MAJOR, -		LL_VERSION_MINOR, -		LL_VERSION_PATCH, -		LL_VERSION_BUILD ); +		LLVersionInfo::getChannel().c_str(), +		LLVersionInfo::getMajor(), +		LLVersionInfo::getMinor(), +		LLVersionInfo::getPatch(), +		LLVersionInfo::getBuild());  	if (!m_Header.size())  	{ diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index 733d05834a..53994c68f2 100644 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -95,9 +95,42 @@ const std::string &LLVersionInfo::getShortVersion()  	return version;  } +namespace +{ +	/// Storage of the channel name the viewer is using. +	//  The channel name is set by hardcoded constant,  +	//  or by calling LLVersionInfo::resetChannel() +	std::string sWorkingChannelName(LL_CHANNEL); + +	// Storage for the "version and channel" string. +	// This will get reset too. +	std::string sVersionChannel(""); +} + +//static +const std::string &LLVersionInfo::getVersionAndChannel() +{ +	if (sVersionChannel.empty()) +	{ +		// cache the version string +		std::ostringstream stream; +		stream << LLVersionInfo::getVersion()  +			   << " " +			   << LLVersionInfo::getChannel(); +		sVersionChannel = stream.str(); +	} + +	return sVersionChannel; +} +  //static  const std::string &LLVersionInfo::getChannel()  { -	static std::string name(LL_CHANNEL); -	return name; +	return sWorkingChannelName; +} + +void LLVersionInfo::resetChannel(const std::string& channel) +{ +	sWorkingChannelName = channel; +	sVersionChannel.clear(); // Reset version and channel string til next use.  } diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h index e468b6ae4e..36defbcd68 100644 --- a/indra/newview/llversioninfo.h +++ b/indra/newview/llversioninfo.h @@ -58,8 +58,15 @@ public:  	/// return the viewer version as a string like "2.0.0"  	static const std::string &getShortVersion(); +	/// return the viewer version and channel as a string +	/// like "2.0.0.200030 Second Life Release" +	static const std::string &getVersionAndChannel(); +  	/// return the channel name, e.g. "Second Life"  	static const std::string &getChannel(); +	 +	/// reset the channel name used by the viewer. +	static void resetChannel(const std::string& channel);  };  #endif diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index fbec2a7b9e..f579c433e1 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -82,7 +82,6 @@ LLControlGroup gCrashSettings("CrashSettings");	// saved at end of session  LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warnings  std::string gLastRunVersion; -std::string gCurrentVersion;  extern BOOL gResizeScreenTexture;  extern BOOL gDebugGL; diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h index 22b48f8906..d7191f5c8d 100644 --- a/indra/newview/llviewercontrol.h +++ b/indra/newview/llviewercontrol.h @@ -57,7 +57,5 @@ extern LLControlGroup gCrashSettings;  // Set after settings loaded  extern std::string gLastRunVersion; -extern std::string gCurrentVersion; -  #endif // LL_LLVIEWERCONTROL_H diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 48ab122edf..13fbce910b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -492,7 +492,7 @@ std::string LLViewerMedia::getCurrentUserAgent()  	// Just in case we need to check browser differences in A/B test  	// builds. -	std::string channel = gSavedSettings.getString("VersionChannelName"); +	std::string channel = LLVersionInfo::getChannel();  	// append our magic version number string to the browser user agent id  	// See the HTTP 1.0 and 1.1 specifications for allowed formats: diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 46c78e2bb4..402f00c5e7 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -48,6 +48,7 @@  #include "llagent.h"  #include "llagentcamera.h"  #include "llviewercontrol.h" +#include "llversioninfo.h"  #include "llfloatertools.h"  #include "lldebugview.h"  #include "llfasttimerview.h" @@ -749,7 +750,7 @@ void send_stats()  	// send fps only for time app spends in foreground  	agent["fps"] = (F32)gForegroundFrameCount / gForegroundTime.getElapsedTimeF32(); -	agent["version"] = gCurrentVersion; +	agent["version"] = LLVersionInfo::getVersionAndChannel();  	std::string language = LLUI::getLanguage();  	agent["language"] = language; diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index db50b89620..b902c7ab09 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -48,6 +48,9 @@ const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");  const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno"); +const std::string VIEWERLOGIN_CHANNEL("invalid_channel"); +const std::string VIEWERLOGIN_VERSION_CHANNEL("invalid_version"); +  // Link seams.  //----------------------------------------------------------------------------- @@ -160,7 +163,6 @@ std::string LLGridManager::getAppSLURLBase(const std::string& grid_name)  //-----------------------------------------------------------------------------  #include "../llviewercontrol.h"  LLControlGroup gSavedSettings("Global"); -std::string gCurrentVersion = "invalid_version";  LLControlGroup::LLControlGroup(const std::string& name) :  	LLInstanceTracker<LLControlGroup, std::string>(name){} @@ -177,6 +179,10 @@ BOOL LLControlGroup::declareString(const std::string& name, const std::string &i  #include "lluicolortable.h"  void LLUIColorTable::saveUserSettings(void)const {} +//----------------------------------------------------------------------------- +#include "../llversioninfo.h" +const std::string &LLVersionInfo::getVersionAndChannel() { return VIEWERLOGIN_VERSION_CHANNEL; } +const std::string &LLVersionInfo::getChannel() { return VIEWERLOGIN_CHANNEL; }  //-----------------------------------------------------------------------------  #include "llnotifications.h" @@ -290,7 +296,6 @@ namespace tut  			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); diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp new file mode 100644 index 0000000000..8855a24ead --- /dev/null +++ b/indra/newview/tests/llversioninfo_test.cpp @@ -0,0 +1,114 @@ +/**  + * @file llversioninfo_test.cpp + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "../test/lltut.h" + +#include "../llversioninfo.h" +#include "llversionviewer.h" + +namespace tut +{ +    struct versioninfo +    { +		versioninfo() +			: mResetChannel("Reset Channel") +		{ +			std::ostringstream stream; +			stream << LL_VERSION_MAJOR << "." +				   << LL_VERSION_MINOR << "." +				   << LL_VERSION_PATCH << "." +				   << LL_VERSION_BUILD; +			mVersion = stream.str(); +			stream.str(""); + +			stream << LL_VERSION_MAJOR << "." +				   << LL_VERSION_MINOR << "." +				   << LL_VERSION_PATCH; +			mShortVersion = stream.str(); +			stream.str(""); + +			stream << mVersion +				   << " " +				   << LL_CHANNEL; +			mVersionAndChannel = stream.str(); +			stream.str(""); + +			stream << mVersion +				   << " " +				   << mResetChannel; +			mResetVersionAndChannel = stream.str(); +		} +		std::string mResetChannel; +		std::string mVersion; +		std::string mShortVersion; +		std::string mVersionAndChannel; +		std::string mResetVersionAndChannel; +    }; +     +	typedef test_group<versioninfo> versioninfo_t; +	typedef versioninfo_t::object versioninfo_object_t; +	tut::versioninfo_t tut_versioninfo("LLVersionInfo"); + +	template<> template<> +	void versioninfo_object_t::test<1>() +	{ +		ensure_equals("Major version",  +					  LLVersionInfo::getMajor(),  +					  LL_VERSION_MAJOR); +		ensure_equals("Minor version",  +					  LLVersionInfo::getMinor(),  +					  LL_VERSION_MINOR); +		ensure_equals("Patch version",  +					  LLVersionInfo::getPatch(),  +					  LL_VERSION_PATCH); +		ensure_equals("Build version",  +					  LLVersionInfo::getBuild(),  +					  LL_VERSION_BUILD); +		ensure_equals("Channel version",  +					  LLVersionInfo::getChannel(),  +					  LL_CHANNEL); + +		ensure_equals("Version String",  +					  LLVersionInfo::getVersion(),  +					  mVersion); +		ensure_equals("Short Version String",  +					  LLVersionInfo::getShortVersion(),  +					  mShortVersion); +		ensure_equals("Version and channel String",  +					  LLVersionInfo::getVersionAndChannel(),  +					  mVersionAndChannel); + +		LLVersionInfo::resetChannel(mResetChannel); +		ensure_equals("Reset channel version",  +					  LLVersionInfo::getChannel(),  +					  mResetChannel); + +		ensure_equals("Reset Version and channel String",  +					  LLVersionInfo::getVersionAndChannel(),  +					  mResetVersionAndChannel); +	} +} diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index a0f1d1c3c3..b425b50c8b 100644 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -72,16 +72,13 @@ static void substitute_string(std::string &input, const std::string &search, con  	}  } -class LLAgent -{ -public: -	LLAgent() {} -	~LLAgent() {} -#ifdef __GNUC__ -	__attribute__ ((noinline)) -#endif -	bool isGodlike() const { return FALSE; } -}; +#include "../llagent.h" +LLAgent::LLAgent() : mAgentAccess(gSavedSettings) { } +LLAgent::~LLAgent() { } +bool LLAgent::isGodlike() const { return FALSE; } +LLAgentAccess::LLAgentAccess(LLControlGroup& settings) : mSavedSettings(settings) { } +LLUIColor::LLUIColor() {} +  LLAgent gAgent;  std::string LLWeb::expandURLSubstitutions(const std::string &url, diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 6861f02bfb..4596938775 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -743,6 +743,11 @@ class DarwinManifest(ViewerManifest):              devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()              volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip() +            if devfile != '/dev/disk1': +                # adding more debugging info based upon nat's hunches to the +                # logs to help track down 'SetFile -a V' failures -brad +                print "WARNING: 'SetFile -a V' command below is probably gonna fail" +              # Copy everything in to the mounted .dmg              if self.default_channel() and not self.default_grid(): @@ -897,6 +902,9 @@ class LinuxManifest(ViewerManifest):                          'dir': self.get_build_prefix(),                          'inst_name': installer_name,                          'inst_path':self.build_path_of(installer_name)}) +            else: +                print "Skipping %s.tar.bz2 for non-Release build (%s)" % \ +                      (installer_name, self.args['buildtype'])          finally:              self.run_command("mv %(inst)s %(dst)s" % {                  'dst': self.get_dst_prefix(), diff --git a/indra/viewer_components/CMakeLists.txt b/indra/viewer_components/CMakeLists.txt index 0993b64b14..74c9b4568d 100644 --- a/indra/viewer_components/CMakeLists.txt +++ b/indra/viewer_components/CMakeLists.txt @@ -1,4 +1,4 @@  # -*- cmake -*-  add_subdirectory(login) - +add_subdirectory(updater) diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt new file mode 100644 index 0000000000..64a0f98c2a --- /dev/null +++ b/indra/viewer_components/updater/CMakeLists.txt @@ -0,0 +1,77 @@ +# -*- cmake -*- + +project(updater_service) + +include(00-Common) +if(LL_TESTS) +  include(LLAddBuildTest) +endif(LL_TESTS) +include(CURL) +include(LLCommon) +include(LLMessage) +include(LLPlugin) +include(LLVFS) + +include_directories( +    ${LLCOMMON_INCLUDE_DIRS} +    ${LLMESSAGE_INCLUDE_DIRS} +    ${LLPLUGIN_INCLUDE_DIRS} +	${LLVFS_INCLUDE_DIRS} +	${CURL_INCLUDE_DIRS} +    ) + +set(updater_service_SOURCE_FILES +    llupdaterservice.cpp +    llupdatechecker.cpp +    llupdatedownloader.cpp +    ) + +set(updater_service_HEADER_FILES +    llupdaterservice.h +    llupdatechecker.h +    llupdatedownloader.h +    ) + +set_source_files_properties(${updater_service_HEADER_FILES} +                            PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND  +    updater_service_SOURCE_FILES  +    ${updater_service_HEADER_FILES}  +    ) + +add_library(llupdaterservice +            ${updater_service_SOURCE_FILES} +            ) + +target_link_libraries(llupdaterservice +    ${LLCOMMON_LIBRARIES} +    ${LLMESSAGE_LIBRARIES} +    ${LLPLUGIN_LIBRARIES} +	${LLVFS_LIBRARIES} +	${CURL_LIBRARIES} +    ) + +if(LL_TESTS) +  SET(llupdater_service_TEST_SOURCE_FILES +      llupdaterservice.cpp +      ) + +#  set_source_files_properties( +#    llupdaterservice.cpp +#    PROPERTIES +#      LL_TEST_ADDITIONAL_LIBRARIES "${PTH_LIBRARIES}" +#    ) + +  LL_ADD_PROJECT_UNIT_TESTS(llupdaterservice "${llupdater_service_TEST_SOURCE_FILES}") +endif(LL_TESTS) + +set(UPDATER_INCLUDE_DIRS  +  ${LIBS_OPEN_DIR}/viewer_components/updater  +  CACHE INTERNAL "" +) + +set(UPDATER_LIBRARIES  +  llupdaterservice +  CACHE INTERNAL "" +) diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp new file mode 100644 index 0000000000..d31244cc9b --- /dev/null +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -0,0 +1,194 @@ +/**  + * @file llupdaterservice.cpp + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include <stdexcept> +#include <boost/format.hpp> +#include "llhttpclient.h" +#include "llsd.h" +#include "llupdatechecker.h" +#include "lluri.h" + + +#if LL_WINDOWS +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + + +class LLUpdateChecker::CheckError: +	public std::runtime_error +{ +public: +	CheckError(const char * message): +		std::runtime_error(message) +	{ +		; // No op. +	} +}; + + +class LLUpdateChecker::Implementation: +	public LLHTTPClient::Responder +{ +public: +	Implementation(Client & client); +	~Implementation(); +	void check(std::string const & protocolVersion, std::string const & hostUrl,  +			   std::string const & servicePath, std::string channel, std::string version); +	 +	// Responder: +	virtual void completed(U32 status, +						   const std::string & reason, +						   const LLSD& content); +	virtual void error(U32 status, const std::string & reason); +	 +private:	 +	static const char * sProtocolVersion; +	 +	Client & mClient; +	LLHTTPClient mHttpClient; +	bool mInProgress; +	LLHTTPClient::ResponderPtr mMe;  +	std::string mVersion; +	 +	std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl,  +						 std::string const & servicePath, std::string channel, std::string version); + +	LOG_CLASS(LLUpdateChecker::Implementation); +}; + + + +// LLUpdateChecker +//----------------------------------------------------------------------------- + + +LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client): +	mImplementation(new LLUpdateChecker::Implementation(client)) +{ +	; // No op. +} + + +void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,  +							std::string const & servicePath, std::string channel, std::string version) +{ +	mImplementation->check(protocolVersion, hostUrl, servicePath, channel, version); +} + + + +// LLUpdateChecker::Implementation +//----------------------------------------------------------------------------- + + +const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0"; + + +LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client): +	mClient(client), +	mInProgress(false), +	mMe(this) +{ +	; // No op. +} + + +LLUpdateChecker::Implementation::~Implementation() +{ +	mMe.reset(0); +} + + +void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string const & hostUrl,  +											std::string const & servicePath, std::string channel, std::string version) +{ +	llassert(!mInProgress); +	 +	if(protocolVersion != sProtocolVersion) throw CheckError("unsupported protocol"); +		 +	mInProgress = true; +	mVersion = version; +	std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version); +	LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl; +	 +	// The HTTP client will wrap a raw pointer in a boost::intrusive_ptr causing the +	// passed object to be silently and automatically deleted.  We pass a self- +	// referential intrusive pointer stored as an attribute of this class to keep +	// the client from deletig the update checker implementation instance. +	mHttpClient.get(checkUrl, mMe); +} + +void LLUpdateChecker::Implementation::completed(U32 status, +							  const std::string & reason, +							  const LLSD & content) +{ +	mInProgress = false;	 +	 +	if(status != 200) { +		LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl; +		mClient.error(reason); +	} else if(!content.asBoolean()) { +		LL_INFOS("UpdateCheck") << "up to date" << llendl; +		mClient.upToDate(); +	} else if(content["required"].asBoolean()) { +		LL_INFOS("UpdateCheck") << "version invalid" << llendl; +		LLURI uri(content["url"].asString()); +		mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString()); +	} else { +		LL_INFOS("UpdateCheck") << "newer version " << content["version"].asString() << " available" << llendl; +		LLURI uri(content["url"].asString()); +		mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString()); +	} +} + + +void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason) +{ +	mInProgress = false; +	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl; +	mClient.error(reason); +} + + +std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protocolVersion, std::string const & hostUrl,  +													  std::string const & servicePath, std::string channel, std::string version) +{	 +#ifdef LL_WINDOWS +	static const char * platform = "win"; +#elif LL_DARWIN +	static const char * platform = "mac"; +#else +	static const char * platform = "lnx"; +#endif +	 +	LLSD path; +	path.append(servicePath); +	path.append(protocolVersion); +	path.append(channel); +	path.append(version); +	path.append(platform); +	return LLURI::buildHTTP(hostUrl, path).asString(); +} diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h new file mode 100644 index 0000000000..cea1f13647 --- /dev/null +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -0,0 +1,82 @@ +/**  + * @file llupdatechecker.h + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_UPDATERCHECKER_H +#define LL_UPDATERCHECKER_H + + +#include <boost/shared_ptr.hpp> + + +// +// Implements asynchronous checking for updates. +// +class LLUpdateChecker { +public: +	class Client; +	class Implementation; +	 +	// An exception that may be raised on check errors. +	class CheckError; +	 +	LLUpdateChecker(Client & client); +	 +	// Check status of current app on the given host for the channel and version provided. +	void check(std::string const & protocolVersion, std::string const & hostUrl,  +			   std::string const & servicePath, std::string channel, std::string version); +	 +private: +	boost::shared_ptr<Implementation> mImplementation; +}; + + +class LLURI; // From lluri.h + + +// +// The client interface implemented by a requestor checking for an update. +// +class LLUpdateChecker::Client +{ +public: +	// An error occurred while checking for an update. +	virtual void error(std::string const & message) = 0; +	 +	// A newer version is available, but the current version may still be used. +	virtual void optionalUpdate(std::string const & newVersion, +								LLURI const & uri, +								std::string const & hash) = 0; +	 +	// A newer version is available, and the current version is no longer valid.  +	virtual void requiredUpdate(std::string const & newVersion, +								LLURI const & uri, +								std::string const & hash) = 0; +	 +	// The checked version is up to date; no newer version exists. +	virtual void upToDate(void) = 0; +}; + + +#endif diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp new file mode 100644 index 0000000000..ca1d2d25de --- /dev/null +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -0,0 +1,398 @@ +/**  + * @file llupdatedownloader.cpp + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include <stdexcept> +#include <boost/format.hpp> +#include <boost/lexical_cast.hpp> +#include <curl/curl.h> +#include "lldir.h" +#include "llfile.h" +#include "llmd5.h" +#include "llsd.h" +#include "llsdserialize.h" +#include "llthread.h" +#include "llupdatedownloader.h" + + +class LLUpdateDownloader::Implementation: +	public LLThread +{ +public: +	Implementation(LLUpdateDownloader::Client & client); +	~Implementation(); +	void cancel(void); +	void download(LLURI const & uri, std::string const & hash); +	bool isDownloading(void); +	size_t onHeader(void * header, size_t size); +	size_t onBody(void * header, size_t size); +	void resume(void); +	 +private: +	bool mCancelled; +	LLUpdateDownloader::Client & mClient; +	CURL * mCurl; +	LLSD mDownloadData; +	llofstream mDownloadStream; +	std::string mDownloadRecordPath; +	 +	void initializeCurlGet(std::string const & url, bool processHeader); +	void resumeDownloading(size_t startByte); +	void run(void); +	void startDownloading(LLURI const & uri, std::string const & hash); +	void throwOnCurlError(CURLcode code); +	bool validateDownload(void); + +	LOG_CLASS(LLUpdateDownloader::Implementation); +}; + + +namespace { +	class DownloadError: +		public std::runtime_error +	{ +	public: +		DownloadError(const char * message): +			std::runtime_error(message) +		{ +			; // No op. +		} +	}; + +		 +	const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml"; +}; + + + +// LLUpdateDownloader +//----------------------------------------------------------------------------- + + + +std::string LLUpdateDownloader::downloadMarkerPath(void) +{ +	return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, gSecondLifeUpdateRecord); +} + + +LLUpdateDownloader::LLUpdateDownloader(Client & client): +	mImplementation(new LLUpdateDownloader::Implementation(client)) +{ +	; // No op. +} + + +void LLUpdateDownloader::cancel(void) +{ +	mImplementation->cancel(); +} + + +void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash) +{ +	mImplementation->download(uri, hash); +} + + +bool LLUpdateDownloader::isDownloading(void) +{ +	return mImplementation->isDownloading(); +} + + +void LLUpdateDownloader::resume(void) +{ +	mImplementation->resume(); +} + + + +// LLUpdateDownloader::Implementation +//----------------------------------------------------------------------------- + + +namespace { +	size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader) +	{ +		size_t bytes = blockSize * blocks; +		return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onBody(data, bytes); +	} + + +	size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader) +	{ +		size_t bytes = blockSize * blocks; +		return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes); +	} +} + + +LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): +	LLThread("LLUpdateDownloader"), +	mCancelled(false), +	mClient(client), +	mCurl(0), +	mDownloadRecordPath(LLUpdateDownloader::downloadMarkerPath()) +{ +	CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. +	llverify(code == CURLE_OK); // TODO: real error handling here.  +} + + +LLUpdateDownloader::Implementation::~Implementation() +{ +	if(mCurl) curl_easy_cleanup(mCurl); +} + + +void LLUpdateDownloader::Implementation::cancel(void) +{ +	mCancelled = true; +} +	 + +void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash) +{ +	if(isDownloading()) mClient.downloadError("download in progress"); +	 +	mDownloadData = LLSD(); +	try { +		startDownloading(uri, hash); +	} catch(DownloadError const & e) { +		mClient.downloadError(e.what()); +	} +} + + +bool LLUpdateDownloader::Implementation::isDownloading(void) +{ +	return !isStopped(); +} + + +void LLUpdateDownloader::Implementation::resume(void) +{ +	llifstream dataStream(mDownloadRecordPath); +	if(!dataStream) { +		mClient.downloadError("no download marker"); +		return; +	} +	 +	LLSDSerialize::fromXMLDocument(mDownloadData, dataStream); +	 +	if(!mDownloadData.asBoolean()) { +		mClient.downloadError("no download information in marker"); +		return; +	} +	 +	std::string filePath = mDownloadData["path"].asString(); +	try { +		if(LLFile::isfile(filePath)) {		 +			llstat fileStatus; +			LLFile::stat(filePath, &fileStatus); +			if(fileStatus.st_size != mDownloadData["size"].asInteger()) { +				resumeDownloading(fileStatus.st_size); +			} else if(!validateDownload()) { +				LLFile::remove(filePath); +				download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); +			} else { +				mClient.downloadComplete(mDownloadData); +			} +		} else { +			download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); +		} +	} catch(DownloadError & e) { +		mClient.downloadError(e.what()); +	} +} + + +size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) +{ +	char const * headerPtr = reinterpret_cast<const char *> (buffer); +	std::string header(headerPtr, headerPtr + size); +	size_t colonPosition = header.find(':'); +	if(colonPosition == std::string::npos) return size; // HTML response; ignore. +	 +	if(header.substr(0, colonPosition) == "Content-Length") { +		try { +			size_t firstDigitPos = header.find_first_of("0123456789", colonPosition); +			size_t lastDigitPos = header.find_last_of("0123456789"); +			std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1); +			size_t size = boost::lexical_cast<size_t>(contentLength); +			LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL; +			 +			mDownloadData["size"] = LLSD(LLSD::Integer(size)); +			llofstream odataStream(mDownloadRecordPath); +			LLSDSerialize::toPrettyXML(mDownloadData, odataStream); +		} catch (std::exception const & e) { +			LL_WARNS("UpdateDownload") << "unable to read content length ("  +				<< e.what() << ")" << LL_ENDL; +		} +	} else { +		; // No op. +	} +	 +	return size; +} + + +size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) +{ +	if(mCancelled) return 0; // Forces a write error which will halt curl thread. +	 +	mDownloadStream.write(reinterpret_cast<const char *>(buffer), size); +	return size; +} + + +void LLUpdateDownloader::Implementation::run(void) +{ +	CURLcode code = curl_easy_perform(mCurl); +	if(code == CURLE_OK) { +		LLFile::remove(mDownloadRecordPath); +		if(validateDownload()) { +			LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; +			mClient.downloadComplete(mDownloadData); +		} else { +			LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL; +			std::string filePath = mDownloadData["path"].asString(); +			if(filePath.size() != 0) LLFile::remove(filePath); +			mClient.downloadError("failed hash check"); +		} +	} else if(mCancelled && (code == CURLE_WRITE_ERROR)) { +		LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL; +		// Do not call back client. +	} else { +		LL_WARNS("UpdateDownload") << "download failed with error '" <<  +			curl_easy_strerror(code) << "'" << LL_ENDL; +		LLFile::remove(mDownloadRecordPath); +		mClient.downloadError("curl error"); +	} +} + + +void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader) +{ +	if(mCurl == 0) { +		mCurl = curl_easy_init(); +	} else { +		curl_easy_reset(mCurl); +	} +	 +	if(mCurl == 0) throw DownloadError("failed to initialize curl"); +	 +	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true)); +	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); +	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); +	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this)); +	if(processHeader) { +	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function)); +	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this)); +	} +	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true)); +	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str())); +} + + +void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) +{ +	initializeCurlGet(mDownloadData["url"].asString(), false); +	 +	// The header 'Range: bytes n-' will request the bytes remaining in the +	// source begining with byte n and ending with the last byte. +	boost::format rangeHeaderFormat("Range: bytes=%u-"); +	rangeHeaderFormat % startByte; +	curl_slist * headerList = 0; +	headerList = curl_slist_append(headerList, rangeHeaderFormat.str().c_str()); +	if(headerList == 0) throw DownloadError("cannot add Range header"); +	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, headerList)); +	curl_slist_free_all(headerList); +	 +	mDownloadStream.open(mDownloadData["path"].asString(), +						 std::ios_base::out | std::ios_base::binary | std::ios_base::app); +	start(); +} + + +void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std::string const & hash) +{ +	mDownloadData["url"] = uri.asString(); +	mDownloadData["hash"] = hash; +	LLSD path = uri.pathArray(); +	if(path.size() == 0) throw DownloadError("no file path"); +	std::string fileName = path[path.size() - 1].asString(); +	std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); +	mDownloadData["path"] = filePath; + +	LL_INFOS("UpdateDownload") << "downloading " << filePath +		<< " from " << uri.asString() << LL_ENDL; +	LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL; +		 +	llofstream dataStream(mDownloadRecordPath); +	LLSDSerialize::toPrettyXML(mDownloadData, dataStream); +	 +	mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary); +	initializeCurlGet(uri.asString(), true); +	start(); +} + + +void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code) +{ +	if(code != CURLE_OK) { +		const char * errorString = curl_easy_strerror(code); +		if(errorString != 0) { +			throw DownloadError(curl_easy_strerror(code)); +		} else { +			throw DownloadError("unknown curl error"); +		} +	} else { +		; // No op. +	} +} + + +bool LLUpdateDownloader::Implementation::validateDownload(void) +{ +	std::string filePath = mDownloadData["path"].asString(); +	llifstream fileStream(filePath); +	if(!fileStream) return false; + +	std::string hash = mDownloadData["hash"].asString(); +	if(hash.size() != 0) { +		LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL; +		char digest[33]; +		LLMD5(fileStream).hex_digest(digest); +		if(hash != digest) { +			LL_WARNS("UpdateDownload") << "download hash mismatch; expeted " << hash << +				" but download is " << digest << LL_ENDL; +		} +		return hash == digest; +	} else { +		return true; // No hash check provided. +	} +} diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h new file mode 100644 index 0000000000..491a638f9a --- /dev/null +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -0,0 +1,82 @@ +/**  + * @file llupdatedownloader.h + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_UPDATE_DOWNLOADER_H +#define LL_UPDATE_DOWNLOADER_H + + +#include <string> +#include <boost/shared_ptr.hpp> +#include "lluri.h" + + +// +// An asynchronous download service for fetching updates. +// +class LLUpdateDownloader +{ +public: +	class Client; +	class Implementation; +	 +	// Returns the path to the download marker file containing details of the +	// latest download. +	static std::string downloadMarkerPath(void); +	 +	LLUpdateDownloader(Client & client); +	 +	// Cancel any in progress download; a no op if none is in progress.  The +	// client will not receive a complete or error callback. +	void cancel(void); +	 +	// Start a new download. +	void download(LLURI const & uri, std::string const & hash); +	 +	// Returns true if a download is in progress. +	bool isDownloading(void); +	 +	// Resume a partial download. +	void resume(void); +	 +private: +	boost::shared_ptr<Implementation> mImplementation; +}; + + +// +// An interface to be implemented by clients initiating a update download. +// +class LLUpdateDownloader::Client { +public: +	 +	// The download has completed successfully. +	virtual void downloadComplete(LLSD const & data) = 0; +	 +	// The download failed. +	virtual void downloadError(std::string const & message) = 0; +}; + + +#endif diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp new file mode 100644 index 0000000000..dc48606cbc --- /dev/null +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -0,0 +1,293 @@ +/**  + * @file llupdaterservice.cpp + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llupdatedownloader.h" +#include "llevents.h" +#include "lltimer.h" +#include "llupdaterservice.h" +#include "llupdatechecker.h" + +#include "llpluginprocessparent.h" +#include <boost/scoped_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#if LL_WINDOWS +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + +boost::weak_ptr<LLUpdaterServiceImpl> gUpdater; + +class LLUpdaterServiceImpl :  +	public LLPluginProcessParentOwner, +	public LLUpdateChecker::Client, +	public LLUpdateDownloader::Client +{ +	static const std::string sListenerName; +	 +	std::string mProtocolVersion; +	std::string mUrl; +	std::string mPath; +	std::string mChannel; +	std::string mVersion; +	 +	unsigned int mCheckPeriod; +	bool mIsChecking; +	boost::scoped_ptr<LLPluginProcessParent> mPlugin; +	 +	LLUpdateChecker mUpdateChecker; +	LLUpdateDownloader mUpdateDownloader; +	LLTimer mTimer; + +	void retry(void); +	 +	LOG_CLASS(LLUpdaterServiceImpl); +	 +public: +	LLUpdaterServiceImpl(); +	virtual ~LLUpdaterServiceImpl(); + +	// LLPluginProcessParentOwner interfaces +	virtual void receivePluginMessage(const LLPluginMessage &message); +	virtual bool receivePluginMessageEarly(const LLPluginMessage &message); +	virtual void pluginLaunchFailed(); +	virtual void pluginDied(); + +	void setParams(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); + +	void startChecking(); +	void stopChecking(); +	bool isChecking(); +	 +	// LLUpdateChecker::Client: +	virtual void error(std::string const & message); +	virtual void optionalUpdate(std::string const & newVersion, +								LLURI const & uri, +								std::string const & hash); +	virtual void requiredUpdate(std::string const & newVersion, +								LLURI const & uri, +								std::string const & hash); +	virtual void upToDate(void); +	 +	// LLUpdateDownloader::Client +	void downloadComplete(LLSD const & data) { retry(); } +	void downloadError(std::string const & message) { retry(); }	 + +	bool onMainLoop(LLSD const & event);	 +}; + +const std::string LLUpdaterServiceImpl::sListenerName = "LLUpdaterServiceImpl"; + +LLUpdaterServiceImpl::LLUpdaterServiceImpl() : +	mIsChecking(false), +	mCheckPeriod(0), +	mPlugin(0), +	mUpdateChecker(*this), +	mUpdateDownloader(*this) +{ +	// Create the plugin parent, this is the owner. +	mPlugin.reset(new LLPluginProcessParent(this)); +} + +LLUpdaterServiceImpl::~LLUpdaterServiceImpl() +{ +	LL_INFOS("UpdaterService") << "shutting down updater service" << LL_ENDL; +	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); +} + +// LLPluginProcessParentOwner interfaces +void LLUpdaterServiceImpl::receivePluginMessage(const LLPluginMessage &message) +{ +} + +bool LLUpdaterServiceImpl::receivePluginMessageEarly(const LLPluginMessage &message)  +{ +	return false; +}; + +void LLUpdaterServiceImpl::pluginLaunchFailed()  +{ +}; + +void LLUpdaterServiceImpl::pluginDied()  +{ +}; + +void LLUpdaterServiceImpl::setParams(const std::string& protocol_version, +									 const std::string& url,  +									 const std::string& path, +									 const std::string& channel, +									 const std::string& version) +{ +	if(mIsChecking) +	{ +		throw LLUpdaterService::UsageError("Call LLUpdaterService::stopCheck()" +			" before setting params."); +	} +		 +	mProtocolVersion = protocol_version; +	mUrl = url; +	mPath = path; +	mChannel = channel; +	mVersion = version; +} + +void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds) +{ +	mCheckPeriod = seconds; +} + +void LLUpdaterServiceImpl::startChecking() +{ +	if(!mIsChecking) +	{ +		if(mUrl.empty() || mChannel.empty() || mVersion.empty()) +		{ +			throw LLUpdaterService::UsageError("Set params before call to " +				"LLUpdaterService::startCheck()."); +		} +		mIsChecking = true; +		 +		mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion); +	} +} + +void LLUpdaterServiceImpl::stopChecking() +{ +	if(mIsChecking) +	{ +		mIsChecking = false; +	} +} + +bool LLUpdaterServiceImpl::isChecking() +{ +	return mIsChecking; +} + +void LLUpdaterServiceImpl::error(std::string const & message) +{ +	retry(); +} + +void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, +										  LLURI const & uri, +										  std::string const & hash) +{ +	mUpdateDownloader.download(uri, hash); +} + +void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, +										  LLURI const & uri, +										  std::string const & hash) +{ +	mUpdateDownloader.download(uri, hash); +} + +void LLUpdaterServiceImpl::upToDate(void) +{ +	retry(); +} + +void LLUpdaterServiceImpl::retry(void) +{ +	LL_INFOS("UpdaterService") << "will check for update again in " <<  +	mCheckPeriod << " seconds" << LL_ENDL;  +	mTimer.start(); +	mTimer.setTimerExpirySec(mCheckPeriod); +	LLEventPumps::instance().obtain("mainloop").listen( +		sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1)); +} + +bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) +{ +	if(mTimer.hasExpired()) +	{ +		mTimer.stop(); +		LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); +		mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion); +	} else { +		// Keep on waiting... +	} +	 +	return false; +} + + +//----------------------------------------------------------------------- +// Facade interface +LLUpdaterService::LLUpdaterService() +{ +	if(gUpdater.expired()) +	{ +		mImpl =  +			boost::shared_ptr<LLUpdaterServiceImpl>(new LLUpdaterServiceImpl()); +		gUpdater = mImpl; +	} +	else +	{ +		mImpl = gUpdater.lock(); +	} +} + +LLUpdaterService::~LLUpdaterService() +{ +} + +void LLUpdaterService::setParams(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); +} + +void LLUpdaterService::setCheckPeriod(unsigned int seconds) +{ +	mImpl->setCheckPeriod(seconds); +} +	 +void LLUpdaterService::startChecking() +{ +	mImpl->startChecking(); +} + +void LLUpdaterService::stopChecking() +{ +	mImpl->stopChecking(); +} + +bool LLUpdaterService::isChecking() +{ +	return mImpl->isChecking(); +} diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h new file mode 100644 index 0000000000..04adf461b6 --- /dev/null +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -0,0 +1,61 @@ +/**  + * @file llupdaterservice.h + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_UPDATERSERVICE_H +#define LL_UPDATERSERVICE_H + +#include <boost/shared_ptr.hpp> + +class LLUpdaterServiceImpl; + +class LLUpdaterService +{ +public: +	class UsageError: public std::runtime_error +	{ +	public: +		UsageError(const std::string& msg) : std::runtime_error(msg) {} +	}; + +	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 setCheckPeriod(unsigned int seconds); +	 +	void startChecking(); +	void stopChecking(); +	bool isChecking(); + +private: +	boost::shared_ptr<LLUpdaterServiceImpl> mImpl; +}; + +#endif // LL_UPDATERSERVICE_H diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp new file mode 100644 index 0000000000..20d0f8fa09 --- /dev/null +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -0,0 +1,139 @@ +/**
 + * @file   llupdaterservice_test.cpp
 + * @brief  Tests of llupdaterservice.cpp.
 + * 
 + * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, Linden Research, Inc.
 + * 
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation;
 + * version 2.1 of the License only.
 + * 
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + * 
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 + * 
 + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 + * $/LicenseInfo$
 + */
 +
 +// Precompiled header
 +#include "linden_common.h"
 +// associated header
 +#include "../llupdaterservice.h"
 +#include "../llupdatechecker.h"
 +#include "../llupdatedownloader.h"
 +
 +#include "../../../test/lltut.h"
 +//#define DEBUG_ON
 +#include "../../../test/debug.h"
 +
 +#include "llevents.h"
 +#include "llpluginprocessparent.h"
 +
 +/*****************************************************************************
 +*   MOCK'd
 +*****************************************************************************/
 +LLPluginProcessParentOwner::~LLPluginProcessParentOwner() {}
 +LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
 +: mOwner(owner),
 +  mIncomingQueueMutex(gAPRPoolp)
 +{
 +}
 +
 +LLPluginProcessParent::~LLPluginProcessParent() {}
 +LLPluginMessagePipeOwner::LLPluginMessagePipeOwner(){}
 +LLPluginMessagePipeOwner::~LLPluginMessagePipeOwner(){}
 +void LLPluginProcessParent::receiveMessageRaw(const std::string &message) {}
 +int LLPluginMessagePipeOwner::socketError(int) { return 0; }
 +void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) {}
 +void LLPluginMessagePipeOwner::setMessagePipe(class LLPluginMessagePipe *) {}
 +LLPluginMessage::~LLPluginMessage() {}
 +LLPluginMessage::LLPluginMessage(LLPluginMessage const&) {}
 +
 +LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
 +{}
 +void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, 
 +								  std::string const & servicePath, std::string channel, std::string version)
 +{}
 +LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
 +void LLUpdateDownloader::download(LLURI const & , std::string const &){}
 +
 +/*****************************************************************************
 +*   TUT
 +*****************************************************************************/
 +namespace tut
 +{
 +    struct llupdaterservice_data
 +    {
 +		llupdaterservice_data() :
 +            pumps(LLEventPumps::instance()),
 +			test_url("dummy_url"),
 +			test_channel("dummy_channel"),
 +			test_version("dummy_version")
 +		{}
 +		LLEventPumps& pumps;
 +		std::string test_url;
 +		std::string test_channel;
 +		std::string test_version;
 +	};
 +
 +    typedef test_group<llupdaterservice_data> llupdaterservice_group;
 +    typedef llupdaterservice_group::object llupdaterservice_object;
 +    llupdaterservice_group llupdaterservicegrp("LLUpdaterService");
 +
 +    template<> template<>
 +    void llupdaterservice_object::test<1>()
 +    {
 +        DEBUG;
 +		LLUpdaterService updater;
 +		bool got_usage_error = false;
 +		try
 +		{
 +			updater.startChecking();
 +		}
 +		catch(LLUpdaterService::UsageError)
 +		{
 +			got_usage_error = true;
 +		}
 +		ensure("Caught start before params", got_usage_error);
 +	}
 +
 +    template<> template<>
 +    void llupdaterservice_object::test<2>()
 +    {
 +        DEBUG;
 +		LLUpdaterService updater;
 +		bool got_usage_error = false;
 +		try
 +		{
 +			updater.setParams("1.0",test_url, "update" ,test_channel, test_version);
 +			updater.startChecking();
 +			updater.setParams("1.0", "other_url", "update", test_channel, test_version);
 +		}
 +		catch(LLUpdaterService::UsageError)
 +		{
 +			got_usage_error = true;
 +		}
 +		ensure("Caught params while running", got_usage_error);
 +	}
 +
 +    template<> template<>
 +    void llupdaterservice_object::test<3>()
 +    {
 +        DEBUG;
 +		LLUpdaterService updater;
 +		updater.setParams("1.0", test_url, "update", test_channel, test_version);
 +		updater.startChecking();
 +		ensure(updater.isChecking());
 +		updater.stopChecking();
 +		ensure(!updater.isChecking());
 +	}
 +}
 | 
