diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e77d8884669bf34e543f03bd57ccd02c6a298a08..19470102e320d177434f1b828c8591f1bfd32f1a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -82,6 +82,7 @@ include_directories(
     ${LIBS_PREBUILD_DIR}/include/hunspell
     ${OPENAL_LIB_INCLUDE_DIRS}
     ${LIBS_PREBUILT_DIR}/include/collada/1.4
+    ${CMAKE_CURRENT_SOURCE_DIR}
     )
 
 set(viewer_SOURCE_FILES
@@ -278,6 +279,7 @@ set(viewer_SOURCE_FILES
     llgroupiconctrl.cpp
     llgrouplist.cpp
     llgroupmgr.cpp
+    llhasheduniqueid.cpp
     llhints.cpp
     llhomelocationresponder.cpp
     llhudeffect.cpp
@@ -854,6 +856,7 @@ set(viewer_HEADER_FILES
     llgroupiconctrl.h
     llgrouplist.h
     llgroupmgr.h
+    llhasheduniqueid.h
     llhints.h
     llhomelocationresponder.h
     llhudeffect.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 2e91d10cd3ce05e52e05d9cf0b70e4549053eb89..5b73b075a4490105d9ba7a81afd956bfcb021b48 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -12109,6 +12109,17 @@
       <key>Value</key>
       <integer>3</integer>
     </map>
+    <key>UpdaterWillingToTest</key>
+    <map>
+      <key>Comment</key>
+      <string>Allow upgrades to release candidate viewers with new features and fixes.</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>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 468a297c2d2818275ec0053da65c78fb553170e1..ae593daf08f177150f8d23567074c238b2f78153 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2936,16 +2936,28 @@ void LLAppViewer::initUpdater()
 	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");
+	bool willing_to_test = gSavedSettings.getBOOL("UpdaterWillingToTest");
+    unsigned char unique_id[MD5HEX_STR_SIZE];
+	if ( ! llHashedUniqueID(unique_id) )
+	{
+		if ( willing_to_test )
+		{
+			LL_WARNS("UpdaterService") << "Unable to provide a unique id; overriding willing_to_test by sending testno" << LL_ENDL;
+		}
+		willing_to_test = false;
+	}
 
 	mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
-	mUpdater->initialize(protocol_version, 
-						 url, 
+	mUpdater->initialize(url, 
 						 service_path, 
 						 channel, 
-						 version);
+						 version,
+						 getOSInfo().getOSVersionString(),
+						 unique_id,
+						 willing_to_test
+						 );
  	mUpdater->setCheckPeriod(check_period);
 	mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8));
 	gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()->
diff --git a/indra/newview/llhasheduniqueid.cpp b/indra/newview/llhasheduniqueid.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5db5d22332f63421803e7fc76400ed24415d8611
--- /dev/null
+++ b/indra/newview/llhasheduniqueid.cpp
@@ -0,0 +1,54 @@
+/** 
+ * @file llhasheduniqueid.cpp
+ * @brief retrieves an obfuscated unique id for the system
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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 "llviewerprecompiledheaders.h"
+#include "llhasheduniqueid.h"
+#include "llviewernetwork.h"
+#include "lluuid.h"
+#include "llmachineid.h"
+
+bool llHashedUniqueID(unsigned char id[MD5HEX_STR_SIZE])
+{
+	bool idIsUnique = true;
+	LLMD5 hashed_unique_id;
+	unsigned char unique_id[MAC_ADDRESS_BYTES];
+	if (   LLUUID::getNodeID(unique_id)
+		|| LLMachineID::getUniqueID(unique_id, sizeof(unique_id))
+		)
+	{
+		hashed_unique_id.update(unique_id, MAC_ADDRESS_BYTES);
+		hashed_unique_id.finalize();
+		hashed_unique_id.hex_digest((char*)id);
+	}
+	else
+	{
+		idIsUnique = false;
+		memcpy(id,"00000000000000000000000000000000", MD5HEX_STR_SIZE);
+		llwarns << "Failed to get an id; cannot uniquely identify this machine." << llendl;
+	}
+	return idIsUnique;
+}
+
diff --git a/indra/newview/llhasheduniqueid.h b/indra/newview/llhasheduniqueid.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ef706c1f3044a16ebfa41c7ffd9a9c8135500c9
--- /dev/null
+++ b/indra/newview/llhasheduniqueid.h
@@ -0,0 +1,34 @@
+/** 
+ * @file llhasheduniqueid.h
+ * @brief retrieves obfuscated but unique id for the system
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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_LLHASHEDUNIQUEID_H
+#define LL_LLHASHEDUNIQUEID_H
+#include "llmd5.h"
+
+/// Get an obfuscated identifier for this system 
+bool llHashedUniqueID(unsigned char id[MD5HEX_STR_SIZE]);
+///< @returns true if the id is considered valid (if false, the id is all zeros)
+
+#endif // LL_LLHASHEDUNIQUEID_H
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 419641d23c032495d72d5927ad0ee65556cae70a..12796ca26250c16b2e071d9232a1a6e80aa521d8 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -30,7 +30,6 @@
 
 // llcommon
 #include "llevents.h"
-#include "llmd5.h"
 #include "stringize.h"
 
 // llmessage (!)
@@ -40,6 +39,7 @@
 #include "lllogin.h"
 
 // newview
+#include "llhasheduniqueid.h"
 #include "llviewernetwork.h"
 #include "llviewercontrol.h"
 #include "llversioninfo.h"
@@ -202,7 +202,7 @@ MandatoryUpdateMachine::MandatoryUpdateMachine(LLLoginInstance & loginInstance,
 
 void MandatoryUpdateMachine::start(void)
 {
-	llinfos << "starting manditory update machine" << llendl;
+	llinfos << "starting mandatory update machine" << llendl;
 	
 	if(mUpdaterService.isChecking()) {
 		switch(mUpdaterService.getState()) {
@@ -579,24 +579,17 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 	// (re)initialize the request params with creds.
 	LLSD request_params = user_credential->getLoginParams();
 
-	char hashed_unique_id_string[MD5HEX_STR_SIZE];		/* Flawfinder: ignore */
-	LLMD5 hashed_unique_id;
-	unsigned char unique_id[MAC_ADDRESS_BYTES];
-	if(LLUUID::getNodeID(unique_id) == 0) {
-		if(LLMachineID::getUniqueID(unique_id, sizeof(unique_id)) == 0) {
-			llerrs << "Failed to get an id; cannot uniquely identify this machine." << llendl;
-		}
+	unsigned char hashed_unique_id_string[MD5HEX_STR_SIZE];
+	if ( ! llHashedUniqueID(hashed_unique_id_string) )
+	{
+		llwarns << "Not providing a unique id in request params" << llendl;
 	}
-	hashed_unique_id.update(unique_id, MAC_ADDRESS_BYTES);
-	hashed_unique_id.finalize();
-	hashed_unique_id.hex_digest(hashed_unique_id_string);
-	
 	request_params["start"] = construct_start_string();
 	request_params["skipoptional"] = mSkipOptionalUpdate;
 	request_params["agree_to_tos"] = false; // Always false here. Set true in 
 	request_params["read_critical"] = false; // handleTOSResponse
 	request_params["last_exec_event"] = mLastExecEvent;
-	request_params["mac"] = hashed_unique_id_string;
+	request_params["mac"] = (char*)hashed_unique_id_string;
 	request_params["version"] = LLVersionInfo::getChannelAndVersion(); // Includes channel name
 	request_params["channel"] = LLVersionInfo::getChannel();
 	request_params["id0"] = mSerialNumber;
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 4aeea8823e688845558c83619550d0a58b5639b7..2fb6a9fd40efb0bbde91ec26c242260a90b9dcdf 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -232,6 +232,19 @@
          name="Install_manual"
          value="0" />
   </combo_box>
+  <check_box
+    top_delta="4"
+    enabled="true"
+    follows="left|top"
+    height="14"
+    initial_value="true"
+    control_name="UpdateWillingToTest"
+    label="Willing to update to release candidates"
+    left_delta="0"
+    mouse_opaque="true"
+    name="update_willing_to_test"
+    width="400"           
+    top_pad="5"/>
   <text
      type="string"
      length="1"
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index 7705b4c567d9ae1f9d81cb37c1ede30824ea67d1..a86230488b91b183489eb5f935265cced7164884 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -208,11 +208,14 @@ std::string const & LLUpdaterService::pumpName(void)
 	return wakka;
 }
 bool LLUpdaterService::updateReadyToInstall(void) { return false; }
-void LLUpdaterService::initialize(const std::string& protocol_version,
-				const std::string& url, 
-				const std::string& path,
-				const std::string& channel,
-								  const std::string& version) {}
+void LLUpdaterService::initialize(const std::string& url, 
+								  const std::string& path,
+								  const std::string& channel,
+								  const std::string& version,
+								  const std::string& platform_version,
+								  const unsigned char uniqueid[MD5HEX_STR_SIZE],
+								  const bool&         willing_to_test
+								  ) {}
 
 void LLUpdaterService::setCheckPeriod(unsigned int seconds) {}
 void LLUpdaterService::startChecking(bool install_if_ready) {}
@@ -221,6 +224,12 @@ bool LLUpdaterService::isChecking() { return false; }
 LLUpdaterService::eUpdaterState LLUpdaterService::getState() { return INITIAL; }
 std::string LLUpdaterService::updatedVersion() { return ""; }
 
+bool llHashedUniqueID(unsigned char* id) 
+{
+	memcpy( id, "66666666666666666666666666666666", MD5HEX_STR_SIZE );
+	return true;
+}
+
 //-----------------------------------------------------------------------------
 #include "llnotifications.h"
 #include "llfloaterreg.h"
diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt
index 4343f39e76f13e519c70ab9a25b6b743381dd62b..c5c78728e7ce0fefff5917e6b73d6d5ea8a10a00 100644
--- a/indra/viewer_components/updater/CMakeLists.txt
+++ b/indra/viewer_components/updater/CMakeLists.txt
@@ -19,6 +19,7 @@ include_directories(
     ${LLPLUGIN_INCLUDE_DIRS}
     ${LLVFS_INCLUDE_DIRS}
     ${CURL_INCLUDE_DIRS}
+    ${CMAKE_SOURCE_DIR}/newview
     )
 
 set(updater_service_SOURCE_FILES
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
index 5edbbf9914cbfb7ae52f17f24cade54377e8ba91..6d0758b226149c0e7823e6705aa6a527b7a7a9fe 100644
--- a/indra/viewer_components/updater/llupdatechecker.cpp
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -62,10 +62,15 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
 }
 
 
-void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, 
-							std::string const & servicePath, std::string channel, std::string version)
+void LLUpdateChecker::checkVersion(std::string const & hostUrl, 
+								   std::string const & servicePath,
+								   std::string const & channel,
+								   std::string const & version,
+								   std::string const & platform_version,
+								   unsigned char       uniqueid[MD5HEX_STR_SIZE],
+								   bool                willing_to_test)
 {
-	mImplementation->checkVersion(protocolVersion, hostUrl, servicePath, channel, version);
+	mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test);
 }
 
 
@@ -74,12 +79,14 @@ void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::str
 //-----------------------------------------------------------------------------
 
 
-const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0";
+const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0";
+const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1";
 
 
 LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
 	mClient(client),
-	mInProgress(false)
+	mInProgress(false),
+	mProtocol(sProtocolVersion)
 {
 	; // No op.
 }
@@ -91,39 +98,86 @@ LLUpdateChecker::Implementation::~Implementation()
 }
 
 
-void LLUpdateChecker::Implementation::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, 
-											std::string const & servicePath, std::string channel, std::string version)
+void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, 
+												   std::string const & servicePath,
+												   std::string const & channel,
+												   std::string const & version,
+												   std::string const & platform_version,
+												   unsigned char       uniqueid[MD5HEX_STR_SIZE],
+												   bool                willing_to_test)
 {
 	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;
+
+	mHostUrl     	 = hostUrl;
+	mServicePath 	 = servicePath;
+	mChannel     	 = channel;
+	mVersion     	 = version;
+	mPlatformVersion = platform_version;
+	memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);
+	mWillingToTest   = willing_to_test;
+	
+	mProtocol = sProtocolVersion;
+
+	std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test);
+	LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;
 	
 	mHttpClient.get(checkUrl, this);
 }
 
 void LLUpdateChecker::Implementation::completed(U32 status,
-							  const std::string & reason,
-							  const LLSD & content)
+												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;
+	if(status != 200)
+	{
+		if (status == 404)
+		{
+			if (mProtocol == sProtocolVersion)
+			{
+				mProtocol = sLegacyProtocolVersion;
+				std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest);
+
+				LL_WARNS("UpdaterService")
+					<< "update response using " << sProtocolVersion
+					<< " was 404... retry at " << retryUrl
+					<< " with legacy protocol"
+					<< LL_ENDL;
+	
+				mHttpClient.get(retryUrl, this);
+			}
+			else
+			{
+				LL_WARNS("UpdaterService")
+					<< "update response using " << sLegacyProtocolVersion
+					<< " was 404; request failed"
+					<< LL_ENDL;
+				mClient.error(reason);
+			}
+		}
+		else
+		{
+			LL_WARNS("UpdaterService") << "response error " << status << " (" << reason << ")" << LL_ENDL;
+			mClient.error(reason);
+		}
+	}
+	else if(!content.asBoolean())
+	{
+		LL_INFOS("UpdaterService") << "up to date" << LL_ENDL;
 		mClient.upToDate();
-	} else if(content["required"].asBoolean()) {
-		LL_INFOS("UpdateCheck") << "version invalid" << llendl;
+	}
+	else if(content["required"].asBoolean())
+	{
+		LL_INFOS("UpdaterService") << "version invalid" << LL_ENDL;
 		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;
+	}
+	else
+	{
+		LL_INFOS("UpdaterService") << "newer version " << content["version"].asString() << " available" << LL_ENDL;
 		LLURI uri(content["url"].asString());
 		mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString());
 	}
@@ -133,13 +187,18 @@ void LLUpdateChecker::Implementation::completed(U32 status,
 void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
 {
 	mInProgress = false;
-	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
+	LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL;
 	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)
+std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl, 
+													  std::string const & servicePath,
+													  std::string const & channel,
+													  std::string const & version,
+													  std::string const & platform_version,
+													  unsigned char       uniqueid[MD5HEX_STR_SIZE],
+													  bool                willing_to_test)
 {	
 #ifdef LL_WINDOWS
 	static const char * platform = "win";
@@ -162,9 +221,15 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protoc
 	
 	LLSD path;
 	path.append(servicePath);
-	path.append(protocolVersion);
+	path.append(mProtocol);
 	path.append(channel);
 	path.append(version);
 	path.append(platform);
+	if (mProtocol != sLegacyProtocolVersion)
+	{
+		path.append(platform_version);
+		path.append(willing_to_test ? "testok" : "testno");
+		path.append((char*)uniqueid);
+	}
 	return LLURI::buildHTTP(hostUrl, path).asString();
 }
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
index 23f62a7c5eee98b265e99935cad6edc2f8425f98..b60f21549e2b6d6e157a9dc24df5ade439ad8c9d 100644
--- a/indra/viewer_components/updater/llupdatechecker.h
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -29,6 +29,7 @@
 
 #include <boost/shared_ptr.hpp>
 
+#include "llmd5.h"
 #include "llhttpclient.h"
 
 //
@@ -37,15 +38,19 @@
 class LLUpdateChecker {
 public:
 	class Client;
-	class Implementation:
-
-	public LLHTTPClient::Responder
+	class Implementation: public LLHTTPClient::Responder
 	{
 	public:
 		Implementation(Client & client);
 		~Implementation();
-		void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, 
-				   std::string const & servicePath, std::string channel, std::string version);
+		void checkVersion(std::string const & hostUrl, 
+						  std::string const & servicePath,
+						  std::string const & channel,
+						  std::string const & version,
+						  std::string const & platform_version,
+						  unsigned char       uniqueid[MD5HEX_STR_SIZE],
+						  bool                willing_to_test
+						  );
 	
 		// Responder:
 		virtual void completed(U32 status,
@@ -54,15 +59,28 @@ class LLUpdateChecker {
 		virtual void error(U32 status, const std::string & reason);
 	
 	private:	
+		static const char * sLegacyProtocolVersion;
 		static const char * sProtocolVersion;
-	
+		const char* mProtocol;
+		
 		Client & mClient;
 		LLHTTPClient mHttpClient;
-		bool mInProgress;
-		std::string mVersion;
-	
-		std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl, 
-							 std::string const & servicePath, std::string channel, std::string version);
+		bool         mInProgress;
+		std::string   mVersion;
+		std::string   mHostUrl;
+		std::string   mServicePath;
+		std::string   mChannel;
+		std::string   mPlatformVersion;
+		unsigned char mUniqueId[MD5HEX_STR_SIZE];
+		bool          mWillingToTest;
+		
+		std::string buildUrl(std::string const & hostUrl, 
+							 std::string const & servicePath,
+							 std::string const & channel,
+							 std::string const & version,
+							 std::string const & platform_version,
+							 unsigned char       uniqueid[MD5HEX_STR_SIZE],
+							 bool                willing_to_test);
 
 		LOG_CLASS(LLUpdateChecker::Implementation);
 	};
@@ -74,8 +92,13 @@ class LLUpdateChecker {
 	LLUpdateChecker(Client & client);
 	
 	// Check status of current app on the given host for the channel and version provided.
-	void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, 
-			   std::string const & servicePath, std::string channel, std::string version);
+	void checkVersion(std::string const & hostUrl, 
+					  std::string const & servicePath,
+					  std::string const & channel,
+					  std::string const & version,
+					  std::string const & platform_version,
+					  unsigned char       uniqueid[MD5HEX_STR_SIZE],
+					  bool                willing_to_test);
 	
 private:
 	LLPointer<Implementation> mImplementation;
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index 75e455e3f6450c62070006badf357c6bb2e2ee95..001dd5ed163412d3eadeabd2428df43500261345 100644
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -301,7 +301,7 @@ void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond)
 		llassert(mCurl != 0);
 		mBandwidthLimit = bytesPerSecond;
 		CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit);
-		if(code != CURLE_OK) LL_WARNS("UpdateDownload") <<
+		if(code != CURLE_OK) LL_WARNS("UpdaterService") <<
 			"unable to change dowload bandwidth" << LL_ENDL;
 	} else {
 		mBandwidthLimit = bytesPerSecond;
@@ -322,13 +322,13 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
 			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;
+			LL_INFOS("UpdaterService") << "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 ("
+			LL_WARNS("UpdaterService") << "unable to read content length ("
 				<< e.what() << ")" << LL_ENDL;
 		}
 	} else {
@@ -368,7 +368,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b
 		event["payload"] = payload;
 		LLEventPumps::instance().obtain("mainlooprepeater").post(event);
 
-		LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL;
+		LL_INFOS("UpdaterService") << "progress event " << payload << LL_ENDL;
 	} else {
 		; // Keep events to a reasonalbe number.
 	}
@@ -384,19 +384,19 @@ void LLUpdateDownloader::Implementation::run(void)
 	if(code == CURLE_OK) {
 		LLFile::remove(mDownloadRecordPath);
 		if(validateDownload()) {
-			LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL;
+			LL_INFOS("UpdaterService") << "download successful" << LL_ENDL;
 			mClient.downloadComplete(mDownloadData);
 		} else {
-			LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL;
+			LL_INFOS("UpdaterService") << "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;
+		LL_INFOS("UpdaterService") << "download canceled by user" << LL_ENDL;
 		// Do not call back client.
 	} else {
-		LL_WARNS("UpdateDownload") << "download failed with error '" <<
+		LL_WARNS("UpdaterService") << "download failed with error '" <<
 			curl_easy_strerror(code) << "'" << LL_ENDL;
 		LLFile::remove(mDownloadRecordPath);
 		if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString());
@@ -446,7 +446,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u
 
 void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
 {
-	LL_INFOS("UpdateDownload") << "resuming download from " << mDownloadData["url"].asString()
+	LL_INFOS("UpdaterService") << "resuming download from " << mDownloadData["url"].asString()
 		<< " at byte " << startByte << LL_ENDL;
 
 	initializeCurlGet(mDownloadData["url"].asString(), false);
@@ -476,9 +476,9 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std
 	std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);
 	mDownloadData["path"] = filePath;
 
-	LL_INFOS("UpdateDownload") << "downloading " << filePath
+	LL_INFOS("UpdaterService") << "downloading " << filePath
 		<< " from " << uri.asString() << LL_ENDL;
-	LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL;
+	LL_INFOS("UpdaterService") << "hash of file is " << hash << LL_ENDL;
 
 	llofstream dataStream(mDownloadRecordPath);
 	LLSDSerialize::toPrettyXML(mDownloadData, dataStream);
@@ -512,11 +512,11 @@ bool LLUpdateDownloader::Implementation::validateDownload(void)
 
 	std::string hash = mDownloadData["hash"].asString();
 	if(hash.size() != 0) {
-		LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL;
+		LL_INFOS("UpdaterService") << "checking hash..." << LL_ENDL;
 		char digest[33];
 		LLMD5(fileStream).hex_digest(digest);
 		if(hash != digest) {
-			LL_WARNS("UpdateDownload") << "download hash mismatch; expeted " << hash <<
+			LL_WARNS("UpdaterService") << "download hash mismatch; expeted " << hash <<
 				" but download is " << digest << LL_ENDL;
 		}
 		return hash == digest;
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index 2f87d59373a6e8927951c6b0fbc213b1ed9db70b..a0e2c0b362172ff2606e09011be84a5afc41f45b 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -75,7 +75,7 @@ int ll_install_update(std::string const & script,
 			llassert(!"unpossible copy mode");
 	}
 	
-	llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
+	LL_INFOS("Updater") << "UpdateInstaller: installing " << updatePath << " using " <<
 		actualScriptPath << LL_ENDL;
 	
 	LLProcess::Params params;
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index d783360f801087fe3ed2a12d0598d4ff7c4d212c..c6c89655d31139888a13130b39fb2c34dffafdef 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -88,11 +88,14 @@ class LLUpdaterServiceImpl :
 {
 	static const std::string sListenerName;
 	
-	std::string mProtocolVersion;
-	std::string mUrl;
-	std::string mPath;
-	std::string mChannel;
-	std::string mVersion;
+	std::string   mProtocolVersion;
+	std::string   mUrl;
+	std::string   mPath;
+	std::string   mChannel;
+	std::string   mVersion;
+	std::string   mPlatformVersion;
+	unsigned char mUniqueId[MD5HEX_STR_SIZE];
+	bool          mWillingToTest;
 	
 	unsigned int mCheckPeriod;
 	bool mIsChecking;
@@ -112,11 +115,14 @@ class LLUpdaterServiceImpl :
 	LLUpdaterServiceImpl();
 	virtual ~LLUpdaterServiceImpl();
 
-	void initialize(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& 	url, 
+					const std::string& 	path,
+					const std::string& 	channel,
+					const std::string& 	version,
+					const std::string&  platform_version,
+					const unsigned char uniqueid[MD5HEX_STR_SIZE],
+					const bool&         willing_to_test					
+					);
 	
 	void setCheckPeriod(unsigned int seconds);
 	void setBandwidthLimit(U64 bytesPerSecond);
@@ -174,11 +180,13 @@ LLUpdaterServiceImpl::~LLUpdaterServiceImpl()
 	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
 }
 
-void LLUpdaterServiceImpl::initialize(const std::string& protocol_version,
-									  const std::string& url, 
-									  const std::string& path,
-									  const std::string& channel,
-									  const std::string& version)
+void LLUpdaterServiceImpl::initialize(const std::string&  url, 
+									  const std::string&  path,
+									  const std::string&  channel,
+									  const std::string&  version,
+									  const std::string & platform_version,
+									  const unsigned char uniqueid[MD5HEX_STR_SIZE],
+									  const bool&         willing_to_test)
 {
 	if(mIsChecking || mIsDownloading)
 	{
@@ -186,11 +194,21 @@ void LLUpdaterServiceImpl::initialize(const std::string& protocol_version,
 										   "while updater is running.");
 	}
 		
-	mProtocolVersion = protocol_version;
 	mUrl = url;
 	mPath = path;
 	mChannel = channel;
 	mVersion = version;
+	mPlatformVersion = platform_version;
+	memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);
+	mWillingToTest = willing_to_test;
+	LL_DEBUGS("UpdaterService")
+		<< "\n  url: " << mUrl
+		<< "\n  path: " << mPath
+		<< "\n  channel: " << mChannel
+		<< "\n  version: " << mVersion
+		<< "\n  uniqueid: " << mUniqueId
+		<< "\n  willing: " << ( mWillingToTest ? "testok" : "testno" )
+		<< LL_ENDL;
 }
 
 void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds)
@@ -289,7 +307,7 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)
 			// the update.  Do not install this update.
 			if(!path.asString().empty())
 			{
-				llinfos << "ignoring update dowloaded by different client version" << llendl;
+				LL_INFOS("UpdaterService") << "ignoring update dowloaded by different client version" << LL_ENDL;;
 				LLFile::remove(path.asString());
 				LLFile::remove(update_marker_path());
 			}
@@ -317,7 +335,7 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)
 				{
 					mAppExitCallback();
 				} else if(result != 0) {
-					llwarns << "failed to run update install script" << LL_ENDL;
+					LL_WARNS("UpdaterService") << "failed to run update install script" << LL_ENDL;
 				} else {
 					; // No op.
 				}
@@ -352,7 +370,7 @@ bool LLUpdaterServiceImpl::checkForResume()
 			else 
 			{
 				// The viewer that started this download is not the same as this viewer; ignore.
-				llinfos << "ignoring partial download from different viewer version" << llendl;
+				LL_INFOS("UpdaterService") << "ignoring partial download from different viewer version" << LL_ENDL;;
 				std::string path = download_info["path"].asString();
 				if(!path.empty()) LLFile::remove(path);
 				LLFile::remove(download_marker_path);
@@ -501,8 +519,8 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
 				if(stream.fail()) requiredValue = 0;
 			}
 			// TODO: notify the user.
-			llinfos << "found marker " << ll_install_failed_marker_path() << llendl;
-			llinfos << "last install attempt failed" << llendl;
+			LL_INFOS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;;
+			LL_INFOS("UpdaterService") << "last install attempt failed" << LL_ENDL;;
 			LLFile::remove(ll_install_failed_marker_path());
 			
 			LLSD event;
@@ -514,7 +532,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
 		}
 		else
 		{
-			mUpdateChecker.checkVersion(mProtocolVersion, mUrl, mPath, mChannel, mVersion);
+			mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest);
 			setState(LLUpdaterService::CHECKING_FOR_UPDATE);
 		}
 	} 
@@ -559,13 +577,16 @@ LLUpdaterService::~LLUpdaterService()
 {
 }
 
-void LLUpdaterService::initialize(const std::string& protocol_version,
-								 const std::string& url, 
-								 const std::string& path,
-								 const std::string& channel,
-								 const std::string& version)
+void LLUpdaterService::initialize(const std::string& url, 
+								  const std::string& path,
+								  const std::string& channel,
+								  const std::string& version,
+								  const std::string& platform_version,
+								  const unsigned char uniqueid[MD5HEX_STR_SIZE],
+								  const bool&         willing_to_test
+)
 {
-	mImpl->initialize(protocol_version, url, path, channel, version);
+	mImpl->initialize(url, path, channel, version, platform_version, uniqueid, willing_to_test);
 }
 
 void LLUpdaterService::setCheckPeriod(unsigned int seconds)
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
index 450f19c1c6d18cbffc4b4f0c95621f0a6b9717ba..48d3590f1bfe1d1e7495842aca14597090453ac6 100644
--- a/indra/viewer_components/updater/llupdaterservice.h
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -28,6 +28,7 @@
 
 #include <boost/shared_ptr.hpp>
 #include <boost/function.hpp>
+#include "llhasheduniqueid.h"
 
 class LLUpdaterServiceImpl;
 
@@ -70,11 +71,14 @@ class LLUpdaterService
 	LLUpdaterService();
 	~LLUpdaterService();
 
-	void initialize(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& 	url, 
+				    const std::string& 	path,
+				    const std::string& 	channel,
+				    const std::string& 	version,
+					const std::string&  platform_version,
+					const unsigned char uniqueid[MD5HEX_STR_SIZE],
+					const bool&         willing_to_test
+					);
 
 	void setCheckPeriod(unsigned int seconds);
 	void setBandwidthLimit(U64 bytesPerSecond);
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
index a49bc4161e2cdc4558a7d633d878d471b35ee963..ddaaccc0515592fd21ea4df26db0cc5431ccad61 100644
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -44,8 +44,13 @@
 *****************************************************************************/
 LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
 {}
-void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, 
-								  std::string const & servicePath, std::string channel, std::string version)
+void LLUpdateChecker::checkVersion(std::string const & hostUrl, 
+								   std::string const & servicePath,
+								   std::string const & channel,
+								   std::string const & version,
+								   std::string const & platform_version,
+								   unsigned char       uniqueid[MD5HEX_STR_SIZE],
+								   bool                willing_to_test)
 {}
 LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
 void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){}
@@ -171,9 +176,11 @@ namespace tut
 		bool got_usage_error = false;
 		try
 		{
-			updater.initialize("1.0",test_url, "update" ,test_channel, test_version);
+			unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111";
+			updater.initialize(test_url, "update" ,test_channel, test_version, "1.2.3", id1, true);
 			updater.startChecking();
-			updater.initialize("1.0", "other_url", "update", test_channel, test_version);
+			unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222";
+			updater.initialize("other_url", "update", test_channel, test_version, "4.5.6", id2, true);
 		}
 		catch(LLUpdaterService::UsageError)
 		{
@@ -187,7 +194,8 @@ namespace tut
     {
         DEBUG;
 		LLUpdaterService updater;
-		updater.initialize("1.0", test_url, "update", test_channel, test_version);
+		unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333";
+		updater.initialize(test_url, "update", test_channel, test_version, "7.8.9", id, true);
 		updater.startChecking();
 		ensure(updater.isChecking());
 		updater.stopChecking();