diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 239d974bc3391c569ac3d8c85fd19f61cadee034..73c00c1d82c50544622a2c8d63ce5a9057cde5cf 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -45,6 +45,7 @@
 #include "llagent.h"
 #include "llbutton.h"
 #include "llcombobox.h"
+#include "llcommandhandler.h"	// secondlife:///app/chat/ support
 #include "llviewercontrol.h"
 #include "llfloaterchat.h"
 #include "llgesturemgr.h"
@@ -76,6 +77,7 @@ LLChatBar *gChatBar = NULL;
 
 // legacy calllback glue
 void toggleChatHistory(void* user_data);
+void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
 
 
 class LLChatBarGestureObserver : public LLGestureManagerObserver
@@ -570,8 +572,6 @@ void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type,
 
 void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)
 {
-	LLMessageSystem* msg = gMessageSystem;
-
 	// Look for "/20 foo" channel chats.
 	S32 channel = 0;
 	LLWString out_text = stripChannelNumber(wtext, &channel);
@@ -616,6 +616,12 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
 		}
 	}
 
+	send_chat_from_viewer(utf8_out_text, type, channel);
+}
+
+void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
+{
+	LLMessageSystem* msg = gMessageSystem;
 	msg->newMessageFast(_PREHASH_ChatFromViewer);
 	msg->nextBlockFast(_PREHASH_AgentData);
 	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -670,3 +676,24 @@ void toggleChatHistory(void* user_data)
 {
 	LLFloaterChat::toggleInstance(LLSD());
 }
+
+
+class LLChatHandler : public LLCommandHandler
+{
+public:
+	// not allowed from outside the app
+	LLChatHandler() : LLCommandHandler("chat", false) { }
+
+    // Your code here
+	bool handle(const LLSD& tokens, const LLSD& queryMap)
+	{
+		if (tokens.size() < 2) return false;
+		S32 channel = tokens[0].asInteger();
+		std::string mesg = tokens[1].asString();
+		send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel);
+		return true;
+	}
+};
+
+// Creating the object registers with the dispatcher.
+LLChatHandler gChatHandler;
diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..72110e4fffe0657710a88dcb3b3f2042c3ad72b0
--- /dev/null
+++ b/indra/newview/llfloaterhud.cpp
@@ -0,0 +1,118 @@
+/** 
+ * @file llfloaterhud.cpp
+ * @brief Implementation of HUD floater
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterhud.h"
+#include "llviewercontrol.h"
+#include "llvieweruictrlfactory.h"
+#include "llwebbrowserctrl.h"
+#include "llalertdialog.h"
+
+// statics 
+LLFloaterHUD* LLFloaterHUD::sInstance = 0; 
+std::string LLFloaterHUD::sTutorialUrl = "";
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterHUD
+///----------------------------------------------------------------------------
+#define super LLFloater	/* superclass */
+
+// Default constructor
+LLFloaterHUD::LLFloaterHUD()
+:	LLFloater("floater_hud"),
+	mWebBrowser(0)
+{
+	// Don't grab the focus as it will impede performing in-world actions
+	// while using the HUD
+	setAutoFocus(FALSE);
+	
+	// Opaque background since we never get the focus
+	setBackgroundOpaque(TRUE);
+
+	// Create floater from its XML definition
+	gUICtrlFactory->buildFloater(this, "floater_hud.xml");
+	
+	// Position floater based on saved location
+	LLRect saved_position_rect = gSavedSettings.getRect("FloaterHUDRect");
+	reshape(saved_position_rect.getWidth(), saved_position_rect.getHeight(), FALSE);
+	setRect(saved_position_rect);
+	
+	mWebBrowser = LLViewerUICtrlFactory::getWebBrowserByName(this,  "floater_hud_browser" );
+	if (mWebBrowser)
+	{
+		// Always refresh the browser
+		mWebBrowser->setAlwaysRefresh(true);
+
+		// Open links in internal browser
+		mWebBrowser->setOpenInExternalBrowser(false);
+
+		LLString language(gSavedSettings.getString("Language"));
+		if(language == "default")
+		{
+			language = gSavedSettings.getString("SystemLanguage");
+		}
+	
+		std::string url = sTutorialUrl + language + "/";
+		mWebBrowser->navigateTo(url);
+	}
+
+	// Remember the one instance
+	sInstance = this;
+}
+
+// Get the instance
+LLFloaterHUD* LLFloaterHUD::getInstance()
+{
+	if (!sInstance)
+	{
+		new LLFloaterHUD();
+	}
+	return sInstance;
+}
+
+// Destructor
+LLFloaterHUD::~LLFloaterHUD()
+{
+	// Save floater position
+	gSavedSettings.setRect("FloaterHUDRect", getRect() );
+
+	// Clear out the one instance if it's ours
+	if (sInstance == this)
+	{
+		sInstance = NULL;
+	}
+}
+
+// Show the HUD
+void LLFloaterHUD::show()
+{
+	// do not build the floater if there the url is empty
+	if (sTutorialUrl == "")
+	{
+		LLAlertDialog::showXml("TutorialNotFound");
+		return;
+	}
+
+	// Create the instance if necessary
+	LLFloaterHUD* hud = getInstance();
+	hud->open();
+	hud->setFrontmost(FALSE);
+}
+
+void LLFloaterHUD::close()
+{
+	if (sInstance) sInstance->close();
+}
+
+void LLFloaterHUD::onFocusReceived()
+{
+	// Never get the focus
+	setFocus(FALSE);
+}
diff --git a/indra/newview/llfloaterhud.h b/indra/newview/llfloaterhud.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c1140986e68458a01d690b3eea1e0ca781b1443
--- /dev/null
+++ b/indra/newview/llfloaterhud.h
@@ -0,0 +1,44 @@
+/** 
+ * @file llfloaterhud.h
+ * @brief The HUD floater
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERHUD_H
+#define LL_LLFLOATERHUD_H
+
+#include "llfloater.h"
+
+class LLWebBrowserCtrl;
+
+//=============================================================================
+//
+//	CLASS		LLFloaterHUD
+
+class LLFloaterHUD : public LLFloater
+
+/*!	@brief		A floater showing the HUD tutorial
+*/
+{
+public:
+	static LLFloaterHUD* getInstance(); ///< get instance creating if necessary
+	virtual ~LLFloaterHUD(); ///< virtual destructor
+
+	static std::string sTutorialUrl;
+
+	static void show(); ///< show the HUD
+	static void close(); ///< close the HUD (destroys floater)
+
+protected:
+	LLWebBrowserCtrl* mWebBrowser; ///< the actual web browser control
+
+	LLFloaterHUD(); ///< default constructor
+	virtual void onFocusReceived(); ///< called when we get the focus
+private:
+	static LLFloaterHUD* sInstance;
+};
+
+#endif // LL_LLFLOATERHUD_H
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index c5bb21dad2fa39d15f384f944a625d48a88c8563..e189e28c7ddd11cf5d07d3fc85fd1054007bb16d 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -94,6 +94,7 @@
 #include "llfloateractivespeakers.h"
 #include "llfloaterchat.h"
 #include "llfloatergesture.h"
+#include "llfloaterhud.h"
 #include "llfloaterland.h"
 #include "llfloatertopobjects.h"
 #include "llfloatertos.h"
@@ -948,6 +949,7 @@ BOOL idle_startup()
 		requested_options.push_back("buddy-list");
 		requested_options.push_back("ui-config");
 #endif
+		requested_options.push_back("tutorial_setting");
 		requested_options.push_back("login-flags");
 		requested_options.push_back("global-textures");
 		if(gGodConnect)
@@ -1971,6 +1973,29 @@ BOOL idle_startup()
 				}
 			}
  		}
+		options.clear();
+		if(gUserAuthp->getOptions("tutorial_setting", options))
+		{
+			LLUserAuth::options_t::iterator it = options.begin();
+			LLUserAuth::options_t::iterator end = options.end();
+			for (; it != end; ++it)
+			{
+				LLUserAuth::response_t::const_iterator option_it;
+				option_it = (*it).find("tutorial_url");
+				if(option_it != (*it).end())
+				{
+					LLFloaterHUD::sTutorialUrl = option_it->second;
+				}
+				option_it = (*it).find("use_tutorial");
+				if(option_it != (*it).end())
+				{
+					if (option_it->second == "true")
+					{
+						LLFloaterHUD::show();
+					}
+				}
+			}
+		}
 
 		options.clear();
 		if(gUserAuthp->getOptions("event_categories", options))
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 1a4ee66cda3bf6c8c6f4abfa4cac21404c26ea58..8ef9d9c913aec5d3af83541b11db1e9f6b82643f 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -106,6 +106,7 @@
 #include "llfloatergroups.h"
 #include "llfloaterhtml.h"
 #include "llfloaterhtmlhelp.h"
+#include "llfloaterhud.h"
 #include "llfloaterinspect.h"
 #include "llfloaterlagmeter.h"
 #include "llfloaterland.h"
@@ -5372,6 +5373,10 @@ class LLShowFloater : public view_listener_t
 		{
 			gViewerHtmlHelp.show();
 		}
+		else if (floater_name == "help tutorial")
+		{
+			LLFloaterHUD::show();
+		}
 		else if (floater_name == "complaint reporter")
 		{
 			// Prevent menu from appearing in screen shot.
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 9460111869951b72a3d844c55516e7c76f8bc91f..d1e67bfbbdb476005b1940d273d144eabacc956f 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1842,6 +1842,8 @@ void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window)
 
 	adjust_rect_top_left("FloaterLandRect5", window);
 
+	adjust_rect_top_left("FloaterHUDRect", window);
+
 	adjust_rect_top_left("FloaterFindRect2", window);
 
 	adjust_rect_top_left("FloaterGestureRect2", window);