diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 977283247441d9376d530b7cc783843bfdab8878..1b0cf19c5a1f1ad8b95994ba7fdf92394cfd0574 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -420,6 +420,7 @@ set(viewer_SOURCE_FILES
     llpatchvertexarray.cpp
     llpathfindingcharacter.cpp
     llpathfindinglinkset.cpp
+    llpathfindingmanager.cpp
     llphysicsmotion.cpp
     llphysicsshapebuilderutil.cpp
     llplacesinventorybridge.cpp
@@ -973,6 +974,7 @@ set(viewer_HEADER_FILES
     llpatchvertexarray.h
     llpathfindingcharacter.h
     llpathfindinglinkset.h
+    llpathfindingmanager.h
     llphysicsmotion.h
     llphysicsshapebuilderutil.h
     llplacesinventorybridge.h
diff --git a/indra/newview/llfloaterpathfindingbasic.cpp b/indra/newview/llfloaterpathfindingbasic.cpp
index a1c333989efa24884256421c839ae6d897dec0ab..fc46a7525934c92858457df919457caae5840b29 100644
--- a/indra/newview/llfloaterpathfindingbasic.cpp
+++ b/indra/newview/llfloaterpathfindingbasic.cpp
@@ -25,14 +25,14 @@
 * $/LicenseInfo$
 */
 
+#include <boost/bind.hpp>
+
 #include "llviewerprecompiledheaders.h"
 #include "llfloaterpathfindingbasic.h"
-
 #include "llsd.h"
-#include "llagent.h"
 #include "lltextbase.h"
 #include "llbutton.h"
-#include "llviewerregion.h"
+#include "llpathfindingmanager.h"
 
 //---------------------------------------------------------------------------
 // LLFloaterPathfindingBasic
@@ -40,8 +40,8 @@
 
 BOOL LLFloaterPathfindingBasic::postBuild()
 {
-	mRegionNotEnabledText = findChild<LLTextBase>("disabled_warning_label");
-	llassert(mRegionNotEnabledText != NULL);
+	mStatusText = findChild<LLTextBase>("status_label");
+	llassert(mStatusText != NULL);
 
 	mUnfreezeLabel = findChild<LLTextBase>("unfreeze_label");
 	llassert(mUnfreezeLabel != NULL);
@@ -57,23 +57,32 @@ BOOL LLFloaterPathfindingBasic::postBuild()
 	llassert(mFreezeButton != NULL);
 	mFreezeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingBasic::onFreezeClicked, this));
 
-	updateOnFrozenState();
-
 	return LLFloater::postBuild();
 }
 
 void LLFloaterPathfindingBasic::onOpen(const LLSD& key)
 {
+	LLPathfindingManager *pathfindingManager = LLPathfindingManager::getInstance();
+	if (pathfindingManager->isPathfindingEnabledForCurrentRegion())
+	{
+		LLPathfindingManager::getInstance()->requestGetAgentState(boost::bind(&LLFloaterPathfindingBasic::onAgentStateCB, this, _1));
+	}
+	else
+	{
+		setAgentState(LLPathfindingManager::kAgentStateNotEnabled);
+	}
+
+	LLFloater::onOpen(key);
 }
 
 LLFloaterPathfindingBasic::LLFloaterPathfindingBasic(const LLSD& pSeed)
 	: LLFloater(pSeed),
-	mRegionNotEnabledText(NULL),
+	mStatusText(NULL),
 	mUnfreezeLabel(NULL),
 	mUnfreezeButton(NULL),
 	mFreezeLabel(NULL),
 	mFreezeButton(NULL),
-	mIsRegionFrozenXXX(true)
+	mAgentState(LLPathfindingManager::kAgentStateNotEnabled)
 {
 }
 
@@ -81,61 +90,68 @@ LLFloaterPathfindingBasic::~LLFloaterPathfindingBasic()
 {
 }
 
-std::string LLFloaterPathfindingBasic::getCapabilityURL() const
+void LLFloaterPathfindingBasic::onUnfreezeClicked()
 {
-	std::string capURL("");
+	mUnfreezeButton->setEnabled(FALSE);
+	LLPathfindingManager::getInstance()->requestSetAgentState(LLPathfindingManager::kAgentStateUnfrozen, boost::bind(&LLFloaterPathfindingBasic::onAgentStateCB, this, _1));
+}
 
-	LLViewerRegion *region = gAgent.getRegion();
-	if (region != NULL)
-	{
-		capURL = region->getCapability("RetrieveNavMeshSrc");
-	}
+void LLFloaterPathfindingBasic::onFreezeClicked()
+{
+	mUnfreezeButton->setEnabled(FALSE);
+	LLPathfindingManager::getInstance()->requestSetAgentState(LLPathfindingManager::kAgentStateFrozen, boost::bind(&LLFloaterPathfindingBasic::onAgentStateCB, this, _1));
+}
 
-	return capURL;
+void LLFloaterPathfindingBasic::onAgentStateCB(LLPathfindingManager::EAgentState pAgentState)
+{
+	setAgentState(pAgentState);
 }
 
-void LLFloaterPathfindingBasic::updateOnFrozenState()
+void LLFloaterPathfindingBasic::setAgentState(LLPathfindingManager::EAgentState pAgentState)
 {
-	std::string capURL = getCapabilityURL();
+	switch (pAgentState)
+	{
+	case LLPathfindingManager::kAgentStateNotEnabled : 
+		mStatusText->setVisible(TRUE);
+		mStatusText->setText((LLStringExplicit)getString("pathfinding_not_enabled"));
+		mAgentState = pAgentState;
+		break;
+	case LLPathfindingManager::kAgentStateError : 
+		mStatusText->setVisible(TRUE);
+		mStatusText->setText((LLStringExplicit)getString("unable_to_change_state"));
+		// Do not actually change the current state in the error case allowing user to retry previous command
+		break;
+	default :
+		mStatusText->setVisible(FALSE);
+		mAgentState = pAgentState;
+		break;
+	}
 
-	if (capURL.empty())
+	switch (mAgentState)
 	{
-		mRegionNotEnabledText->setVisible(TRUE);
+	case LLPathfindingManager::kAgentStateNotEnabled : 
 		mUnfreezeLabel->setEnabled(FALSE);
 		mUnfreezeButton->setEnabled(FALSE);
 		mFreezeLabel->setEnabled(FALSE);
 		mFreezeButton->setEnabled(FALSE);
+		break;
+	case LLPathfindingManager::kAgentStateFrozen : 
+		mUnfreezeLabel->setEnabled(TRUE);
+		mUnfreezeButton->setEnabled(TRUE);
+		mFreezeLabel->setEnabled(FALSE);
+		mFreezeButton->setEnabled(FALSE);
+		break;
+	case LLPathfindingManager::kAgentStateUnfrozen : 
+		mUnfreezeLabel->setEnabled(FALSE);
+		mUnfreezeButton->setEnabled(FALSE);
+		mFreezeLabel->setEnabled(TRUE);
+		mFreezeButton->setEnabled(TRUE);
+		break;
+	case LLPathfindingManager::kAgentStateError : 
+		llassert(0);
+		break;
+	default :
+		llassert(0);
+		break;
 	}
-	else
-	{
-		mRegionNotEnabledText->setVisible(FALSE);
-		if (mIsRegionFrozenXXX)
-		{
-			mUnfreezeLabel->setEnabled(TRUE);
-			mUnfreezeButton->setEnabled(TRUE);
-			mFreezeLabel->setEnabled(FALSE);
-			mFreezeButton->setEnabled(FALSE);
-		}
-		else
-		{
-			mUnfreezeLabel->setEnabled(FALSE);
-			mUnfreezeButton->setEnabled(FALSE);
-			mFreezeLabel->setEnabled(TRUE);
-			mFreezeButton->setEnabled(TRUE);
-		}
-	}
-}
-
-void LLFloaterPathfindingBasic::onUnfreezeClicked()
-{
-	mIsRegionFrozenXXX = false;
-	updateOnFrozenState();
-	llwarns << "functionality has not yet been implemented to set unfrozen state" << llendl;
-}
-
-void LLFloaterPathfindingBasic::onFreezeClicked()
-{
-	mIsRegionFrozenXXX = true;
-	updateOnFrozenState();
-	llwarns << "functionality has not yet been implemented to set frozen state" << llendl;
 }
diff --git a/indra/newview/llfloaterpathfindingbasic.h b/indra/newview/llfloaterpathfindingbasic.h
index cd5196433910bf2da85525a2de5f070f9e7c20a9..356a270ca0f93ffc2dde327f196866644f9ed75f 100644
--- a/indra/newview/llfloaterpathfindingbasic.h
+++ b/indra/newview/llfloaterpathfindingbasic.h
@@ -29,7 +29,7 @@
 #define LL_LLFLOATERPATHFINDINGBASIC_H
 
 #include "llfloater.h"
-#include "llhandle.h"
+#include "llpathfindingmanager.h"
 
 class LLSD;
 class LLTextBase;
@@ -55,16 +55,16 @@ class LLFloaterPathfindingBasic
 	void onUnfreezeClicked();
 	void onFreezeClicked();
 
-	std::string getCapabilityURL() const;
+	void onAgentStateCB(LLPathfindingManager::EAgentState pAgentState);
 
-	void updateOnFrozenState();
+	void setAgentState(LLPathfindingManager::EAgentState pAgentState);
 
-	LLTextBase *mRegionNotEnabledText;
-	LLTextBase *mUnfreezeLabel;
-	LLButton   *mUnfreezeButton;
-	LLTextBase *mFreezeLabel;
-	LLButton   *mFreezeButton;
-	bool       mIsRegionFrozenXXX; // XXX stinson : Feb 15, 2012 : I think this will be unneeded with the service
+	LLTextBase                        *mStatusText;
+	LLTextBase                        *mUnfreezeLabel;
+	LLButton                          *mUnfreezeButton;
+	LLTextBase                        *mFreezeLabel;
+	LLButton                          *mFreezeButton;
+	LLPathfindingManager::EAgentState mAgentState;
 };
 
 #endif // LL_LLFLOATERPATHFINDINGBASIC_H
diff --git a/indra/newview/llpathfindingcharacter.cpp b/indra/newview/llpathfindingcharacter.cpp
index 2fb48b0eea184245355bf1c18c511cd8f9da5bf2..afa07457bc92f2367b83aa5153ca9545f0d3f4d0 100644
--- a/indra/newview/llpathfindingcharacter.cpp
+++ b/indra/newview/llpathfindingcharacter.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file llpathfindinglinksets.cpp
+ * @file llpathfindingcharacter.cpp
  * @author William Todd Stinson
  * @brief Definition of a pathfinding character that contains various properties required for havok pathfinding.
  *
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e46ec0e17196b76ac81d7623d1a9f58d3bcf3370
--- /dev/null
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -0,0 +1,181 @@
+/** 
+ * @file llpathfindingmanager.cpp
+ * @author William Todd Stinson
+ * @brief A state manager for the various pathfinding states.
+ *
+ * $LicenseInfo:firstyear=2002&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 <string>
+
+#include <boost/function.hpp>
+
+#include "llviewerprecompiledheaders.h"
+#include "llpathfindingmanager.h"
+#include "llsingleton.h"
+#include "llhttpclient.h"
+#include "llagent.h"
+#include "llviewerregion.h"
+
+#define CAP_SERVICE_RETRIEVE_NAVMESH  "RetrieveNavMeshSrc"
+
+#define CAP_SERVICE_AGENT_STATE       "AgentPreferences"
+#define ALTER_PERMANENT_OBJECTS_FIELD "alter_permanent_objects"
+
+//---------------------------------------------------------------------------
+// AgentStateResponder
+//---------------------------------------------------------------------------
+
+class AgentStateResponder : public LLHTTPClient::Responder
+{
+public:
+	AgentStateResponder(LLPathfindingManager::agent_state_callback_t pAgentStateCB, const std::string &pCapabilityURL);
+	virtual ~AgentStateResponder();
+
+	virtual void result(const LLSD &pContent);
+	virtual void error(U32 pStatus, const std::string& pReason);
+
+protected:
+
+private:
+	LLPathfindingManager::agent_state_callback_t mAgentStateCB;
+	std::string                                  mCapabilityURL;
+};
+
+//---------------------------------------------------------------------------
+// LLPathfindingManager
+//---------------------------------------------------------------------------
+
+LLPathfindingManager::LLPathfindingManager()
+{
+}
+
+LLPathfindingManager::~LLPathfindingManager()
+{
+}
+
+bool LLPathfindingManager::isPathfindingEnabledForCurrentRegion() const
+{
+	std::string retrieveNavMeshURL = getRetrieveNavMeshURLForCurrentRegion();
+	return !retrieveNavMeshURL.empty();
+}
+
+void LLPathfindingManager::requestGetAgentState(agent_state_callback_t pAgentStateCB) const
+{
+	std::string agentStateURL = getAgentStateURLForCurrentRegion();
+
+	if (agentStateURL.empty())
+	{
+		pAgentStateCB(kAgentStateError);
+	}
+	else
+	{
+		LLHTTPClient::ResponderPtr responder = new AgentStateResponder(pAgentStateCB, agentStateURL);
+		LLHTTPClient::get(agentStateURL, responder);
+	}
+}
+
+void LLPathfindingManager::requestSetAgentState(EAgentState pAgentState, agent_state_callback_t pAgentStateCB) const
+{
+	std::string agentStateURL = getAgentStateURLForCurrentRegion();
+
+	if (agentStateURL.empty())
+	{
+		pAgentStateCB(kAgentStateError);
+	}
+	else
+	{
+		LLSD request;
+		request[ALTER_PERMANENT_OBJECTS_FIELD] = static_cast<LLSD::Boolean>(pAgentState == kAgentStateUnfrozen);
+
+		LLHTTPClient::ResponderPtr responder = new AgentStateResponder(pAgentStateCB, agentStateURL);
+		LLHTTPClient::post(agentStateURL, request, responder);
+	}
+}
+
+void LLPathfindingManager::handleAgentStateResult(const LLSD &pContent, agent_state_callback_t pAgentStateCB) const
+{
+	llassert(pContent.has(ALTER_PERMANENT_OBJECTS_FIELD));
+	llassert(pContent.get(ALTER_PERMANENT_OBJECTS_FIELD).isBoolean());
+	EAgentState agentState = (pContent.get(ALTER_PERMANENT_OBJECTS_FIELD).asBoolean() ? kAgentStateUnfrozen : kAgentStateFrozen);
+
+	pAgentStateCB(agentState);
+}
+
+void LLPathfindingManager::handleAgentStateError(U32 pStatus, const std::string &pReason, const std::string &pURL, agent_state_callback_t pAgentStateCB) const
+{
+	llwarns << "error with request to URL '" << pURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl;
+	pAgentStateCB(kAgentStateError);
+}
+
+std::string LLPathfindingManager::getRetrieveNavMeshURLForCurrentRegion() const
+{
+	return getCapabilityURLForCurrentRegion(CAP_SERVICE_RETRIEVE_NAVMESH);
+}
+
+std::string LLPathfindingManager::getAgentStateURLForCurrentRegion() const
+{
+	return getCapabilityURLForCurrentRegion(CAP_SERVICE_AGENT_STATE);
+}
+
+std::string LLPathfindingManager::getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const
+{
+	std::string capabilityURL("");
+
+	LLViewerRegion* region = gAgent.getRegion();
+	if (region != NULL)
+	{
+		capabilityURL = region->getCapability(pCapabilityName);
+	}
+
+	if (capabilityURL.empty())
+	{
+		llwarns << "cannot find capability '" << pCapabilityName << "' for current region '"
+			<< ((region != NULL) ? region->getName() : "<null>") << "'" << llendl;
+	}
+
+	return capabilityURL;
+}
+
+//---------------------------------------------------------------------------
+// AgentStateResponder
+//---------------------------------------------------------------------------
+
+AgentStateResponder::AgentStateResponder(LLPathfindingManager::agent_state_callback_t pAgentStateCB, const std::string &pCapabilityURL)
+	: mAgentStateCB(pAgentStateCB),
+	mCapabilityURL(pCapabilityURL)
+{
+}
+
+AgentStateResponder::~AgentStateResponder()
+{
+}
+
+void AgentStateResponder::result(const LLSD &pContent)
+{
+	LLPathfindingManager::getInstance()->handleAgentStateResult(pContent, mAgentStateCB);
+}
+
+void AgentStateResponder::error(U32 pStatus, const std::string &pReason)
+{
+	LLPathfindingManager::getInstance()->handleAgentStateError(pStatus, pReason, mCapabilityURL, mAgentStateCB);
+}
diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef50e2ad6cb8d4832ee297f57bcfaf236c3c02b9
--- /dev/null
+++ b/indra/newview/llpathfindingmanager.h
@@ -0,0 +1,71 @@
+/** 
+ * @file llpathfindingmanager.h
+ * @author William Todd Stinson
+ * @brief A state manager for the various pathfinding states.
+ *
+ * $LicenseInfo:firstyear=2002&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_LLPATHFINDINGMANAGER_H
+#define LL_LLPATHFINDINGMANAGER_H
+
+#include <string>
+
+#include <boost/function.hpp>
+
+#include "llsingleton.h"
+
+class LLFloater;
+
+class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
+{
+public:
+	typedef enum {
+		kAgentStateNotEnabled  = 0,
+		kAgentStateFrozen   = 1,
+		kAgentStateUnfrozen = 2,
+		kAgentStateError    = 3
+	} EAgentState;
+
+	typedef boost::function<void (EAgentState pAgentState)> agent_state_callback_t;
+
+	LLPathfindingManager();
+	virtual ~LLPathfindingManager();
+
+	bool isPathfindingEnabledForCurrentRegion() const;
+
+	void requestGetAgentState(agent_state_callback_t pAgentStateCB) const;
+	void requestSetAgentState(EAgentState, agent_state_callback_t pAgentStateCB) const;
+
+	void handleAgentStateResult(const LLSD &pContent, agent_state_callback_t pAgentStateCB) const;
+	void handleAgentStateError(U32 pStatus, const std::string &pReason, const std::string &pURL, agent_state_callback_t pAgentStateCB) const;
+
+protected:
+
+private:
+	std::string getRetrieveNavMeshURLForCurrentRegion() const;
+	std::string getAgentStateURLForCurrentRegion() const;
+
+	std::string getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const;
+};
+
+#endif // LL_LLPATHFINDINGMANAGER_H
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index ffad4d89bab25a9ef47f24404a496499b25b094a..1fd794fd78cef94a2b16ffc290a17ab4b64ae457 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1489,6 +1489,7 @@ void LLViewerRegion::unpackRegionHandshake()
 
 void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 {
+	capabilityNames.append("AgentPreferences");
 	capabilityNames.append("AttachmentResources");
 	capabilityNames.append("AvatarPickerSearch");
 	capabilityNames.append("CharacterProperties");
diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_basic.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_basic.xml
index 36c7f11f5dccfd0c6e661b2bc6ef78e6ebbe1f45..f53d11bb1dab6ebbed69d14ffffcff292873a0e3 100644
--- a/indra/newview/skins/default/xui/en/floater_pathfinding_basic.xml
+++ b/indra/newview/skins/default/xui/en/floater_pathfinding_basic.xml
@@ -11,6 +11,8 @@
     single_instance="true"
     title="Basic pathfinding setup"
     width="312">
+  <floater.string name="pathfinding_not_enabled">This region is not enabled for pathfinding.</floater.string>
+  <floater.string name="unable_to_change_state">Unable to change modes successfully.</floater.string>
   <text
       height="13"
       word_wrap="false"
@@ -21,10 +23,9 @@
       follows="left|top"
       layout="topleft"
       left="15"
-      name="disabled_warning_label"
+      name="status_label"
       top="8"
       width="289">
-    This region is not enabled for pathfinding.
   </text>
   <text
       height="13"