diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 8d4969a49ea7100e8bf6e35df302d7437067cc60..d01e1869b6983dfbb1116499330bdbb783504e54 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/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 7f3d4bc4e20e833c0ed6d1bfe6c0423b1fe4a84a..8f5cb7c709c5bfd6d29d850d9dfbd653c92cf7dd 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11022,7 +11022,7 @@
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>http://secondlife.com/app/update</string>
+      <string>http://localhost/agni</string>
     </map>
     <key>UploadBakedTexOld</key>
     <map>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b122209af8e58c7b4617a1f11f08f9f77215e9a4..3a48bc25f156f3639416d75a6d0cf9a0c296d514 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -632,9 +632,6 @@ bool LLAppViewer::init()
 	if (!initConfiguration())
 		return false;
 
-	// Initialize updater service
-	initUpdater();
-
 	// write Google Breakpad minidump files to our log directory
 	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
 	logdir += gDirUtilp->getDirDelimiter();
@@ -976,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();
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 21467a2ab856146a27974ab38046146c02a657e0..8ccfdb071b663a0c5d73955c0c3dafef5f13976b 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -64,7 +64,7 @@ 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)",
-		LLVersionInfo::getChannel(),
+		LLVersionInfo::getChannel().c_str(),
 		LLVersionInfo::getMajor(),
 		LLVersionInfo::getMinor(),
 		LLVersionInfo::getPatch(),
diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt
index a8a1d685f7c8037198084e7dfcaa1d26f506582a..2e77a7140a2d39fad8fe50af7babea32a6d41c98 100644
--- a/indra/viewer_components/updater/CMakeLists.txt
+++ b/indra/viewer_components/updater/CMakeLists.txt
@@ -18,10 +18,12 @@ include_directories(
 
 set(updater_service_SOURCE_FILES
     llupdaterservice.cpp
+    llupdatechecker.cpp
     )
 
 set(updater_service_HEADER_FILES
     llupdaterservice.h
+    llupdatechecker.h
     )
 
 set_source_files_properties(${updater_service_HEADER_FILES}
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..331d0269d43fff0a8e76c7d1ca6fac0e9ca1807d
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -0,0 +1,151 @@
+/** 
+ * @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 <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::Implementation:
+	public LLHTTPClient::Responder
+{
+public:
+	
+	Implementation(Client & client);
+	~Implementation();
+	void check(std::string const & host, 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:
+	std::string buildUrl(std::string const & host, std::string channel, std::string version);
+	
+	Client & mClient;
+	LLHTTPClient mHttpClient;
+	bool mInProgress;
+	LLHTTPClient::ResponderPtr mMe;
+	std::string mVersion;
+	
+	LOG_CLASS(LLUpdateChecker::Implementation);
+};
+
+
+
+// LLUpdateChecker
+//-----------------------------------------------------------------------------
+
+
+LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
+	mImplementation(new LLUpdateChecker::Implementation(client))
+{
+	; // No op.
+}
+
+
+void LLUpdateChecker::check(std::string const & host, std::string channel, std::string version)
+{
+	mImplementation->check(host, channel, version);
+}
+
+
+
+// LLUpdateChecker::Implementation
+//-----------------------------------------------------------------------------
+
+
+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 & host, std::string channel, std::string version)
+{
+	// llassert(!mInProgress);
+		
+	mInProgress = true;
+	mVersion = version;
+	std::string checkUrl = buildUrl(host, channel, version);
+	LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
+	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["valid"].asBoolean()) {
+		LL_INFOS("UpdateCheck") << "version invalid" << llendl;
+		mClient.requiredUpdate(content["latest_version"].asString());
+	} else if(content["latest_version"].asString() != mVersion) {
+		LL_INFOS("UpdateCheck") << "newer version " << content["latest_version"].asString() << " available" << llendl;
+		mClient.optionalUpdate(content["latest_version"].asString());
+	} else {
+		LL_INFOS("UpdateCheck") << "up to date" << llendl;
+		mClient.upToDate();
+	}
+}
+
+
+void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
+{
+	mInProgress = false;
+	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
+}
+
+
+std::string LLUpdateChecker::Implementation::buildUrl(std::string const & host, std::string channel, std::string version)
+{	
+	LLSD path;
+	path.append("version");
+	path.append(channel);
+	path.append(version);
+	return LLURI::buildHTTP(host, path).asString();
+}
+
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
new file mode 100644
index 0000000000000000000000000000000000000000..b630c4d8a62e0f05cf439f55aea02af124ed6bb3
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -0,0 +1,71 @@
+/** 
+ * @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;
+	
+	LLUpdateChecker(Client & client);
+	
+	// Check status of current app on the given host for the channel and version provided.
+	void check(std::string const & hostUrl, std::string channel, std::string version);
+	
+private:
+	boost::shared_ptr<Implementation> mImplementation;
+};
+
+
+//
+// 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) = 0;
+	
+	// A newer version is available, and the current version is no longer valid. 
+	virtual void requiredUpdate(std::string const & newVersion) = 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/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 28c942b5f21fd59127d438afa21464adc8489b57..1d0ead3cd4f1bb9ad4c739a782a4769f7d4eb078 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -25,16 +25,27 @@
 
 #include "linden_common.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
+class LLUpdaterServiceImpl : 
+	public LLPluginProcessParentOwner,
+	public LLUpdateChecker::Client
 {
+	static const std::string ListenerName;
+	
 	std::string mUrl;
 	std::string mChannel;
 	std::string mVersion;
@@ -42,10 +53,17 @@ class LLUpdaterServiceImpl : public LLPluginProcessParentOwner
 	unsigned int mCheckPeriod;
 	bool mIsChecking;
 	boost::scoped_ptr<LLPluginProcessParent> mPlugin;
+	
+	LLUpdateChecker mUpdateChecker;
+	LLTimer mTimer;
 
+	void retry(void);
+	
+	LOG_CLASS(LLUpdaterServiceImpl);
+	
 public:
 	LLUpdaterServiceImpl();
-	virtual ~LLUpdaterServiceImpl() {}
+	virtual ~LLUpdaterServiceImpl();
 
 	// LLPluginProcessParentOwner interfaces
 	virtual void receivePluginMessage(const LLPluginMessage &message);
@@ -62,17 +80,34 @@ class LLUpdaterServiceImpl : public LLPluginProcessParentOwner
 	void startChecking();
 	void stopChecking();
 	bool isChecking();
+	
+	// LLUpdateChecker::Client:
+	virtual void error(std::string const & message);
+	virtual void optionalUpdate(std::string const & newVersion);
+	virtual void requiredUpdate(std::string const & newVersion);
+	virtual void upToDate(void);
+	
+	bool onMainLoop(LLSD const & event);	
 };
 
+const std::string LLUpdaterServiceImpl::ListenerName = "LLUpdaterServiceImpl";
+
 LLUpdaterServiceImpl::LLUpdaterServiceImpl() :
 	mIsChecking(false),
 	mCheckPeriod(0),
-	mPlugin(0)
+	mPlugin(0),
+	mUpdateChecker(*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(ListenerName);
+}
+
 // LLPluginProcessParentOwner interfaces
 void LLUpdaterServiceImpl::receivePluginMessage(const LLPluginMessage &message)
 {
@@ -121,6 +156,8 @@ void LLUpdaterServiceImpl::startChecking()
 				"LLUpdaterService::startCheck().");
 		}
 		mIsChecking = true;
+		
+		mUpdateChecker.check(mUrl, mChannel, mVersion);
 	}
 }
 
@@ -137,6 +174,51 @@ bool LLUpdaterServiceImpl::isChecking()
 	return mIsChecking;
 }
 
+void LLUpdaterServiceImpl::error(std::string const & message)
+{
+	retry();
+}
+
+void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion)
+{
+	retry();
+}
+
+void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion)
+{
+	retry();
+}
+
+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(
+		ListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));
+}
+
+bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
+{
+	if(mTimer.hasExpired())
+	{
+		mTimer.stop();
+		LLEventPumps::instance().obtain("mainloop").stopListening(ListenerName);
+		mUpdateChecker.check(mUrl, mChannel, mVersion);
+	} else {
+		// Keep on waiting...
+	}
+	
+	return false;
+}
+
+
 //-----------------------------------------------------------------------
 // Facade interface
 LLUpdaterService::LLUpdaterService()
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
index 6459ca49f8183b97a2b8b7b3f0dbfa6a03c58b8e..313ae8ada32e9305e3000bb1b33a5a4f114fd38a 100644
--- a/indra/viewer_components/updater/llupdaterservice.h
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -58,4 +58,4 @@ class LLUpdaterService
 	boost::shared_ptr<LLUpdaterServiceImpl> mImpl;
 };
 
-#endif LL_UPDATERSERVICE_H
+#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 73cf6ea6eb41e71a58194ac9464f03d567cbb699..d93a85cf7d294330de440734a366990e458385c7 100644
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -28,6 +28,7 @@
 #include "linden_common.h"
 // associated header
 #include "../llupdaterservice.h"
+#include "../llupdatechecker.h"
 
 #include "../../../test/lltut.h"
 //#define DEBUG_ON
@@ -54,6 +55,11 @@ 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 & host, std::string channel, std::string version){}
 
 /*****************************************************************************
 *   TUT