diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 9119408fd1bef303132816785a75a2ea515330eb..d3d888cc5d0c85c175a98b48d37a7b9894fa4b2f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -127,6 +127,7 @@ set(viewer_SOURCE_FILES
     alcontrolcache.cpp
     alfloaterao.cpp
     alfloaterexploresounds.cpp
+    alfloatergenerictext.cpp
     alfloaterparticleeditor.cpp
     alfloaterregiontracker.cpp
     alpanelaomini.cpp
@@ -800,6 +801,7 @@ set(viewer_HEADER_FILES
     alcontrolcache.h
     alfloaterao.h
     alfloaterexploresounds.h
+    alfloatergenerictext.h
     alfloaterparticleeditor.h
     alfloaterregiontracker.h
     alpanelaomini.h
diff --git a/indra/newview/alfloatergenerictext.cpp b/indra/newview/alfloatergenerictext.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cde167dbba1aaf6cdffca1b6c6833d61d4982b0a
--- /dev/null
+++ b/indra/newview/alfloatergenerictext.cpp
@@ -0,0 +1,61 @@
+/**
+ * @file llfloatergenerictext.cpp
+ * @brief A generic text floater for dumping info (usually debug info)
+ *
+ * Copyright (c) 2015, Cinder Roxley <cinder@sdf.org>
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "alfloatergenerictext.h"
+#include "llclipboard.h"
+#include "lltexteditor.h"
+
+LLFloaterGenericText::LLFloaterGenericText(const LLSD& key)
+:	LLFloater(key)
+{
+	mTitle = key["title"].asString();
+	mContents = key["data"].asString();
+	
+	mCommitCallbackRegistrar.add("GenericText.Close", boost::bind(&LLFloaterGenericText::onClickClose, this));
+	mCommitCallbackRegistrar.add("GenericText.Copy", boost::bind(&LLFloaterGenericText::onClickCopy, this));
+}
+
+BOOL LLFloaterGenericText::postBuild()
+{
+	setTitle(mTitle);
+	getChild<LLTextEditor>("payload")->setText(mContents);
+	return TRUE;
+}
+
+void LLFloaterGenericText::onClickClose()
+{
+	closeFloater();
+}
+
+void LLFloaterGenericText::onClickCopy()
+{
+	LLClipboard::instance().copyToClipboard(utf8str_to_wstring(mContents, mContents.length()), 0, mContents.length());
+}
diff --git a/indra/newview/alfloatergenerictext.h b/indra/newview/alfloatergenerictext.h
new file mode 100644
index 0000000000000000000000000000000000000000..43f35802e96355dd4acfd9d47417d4597dc84945
--- /dev/null
+++ b/indra/newview/alfloatergenerictext.h
@@ -0,0 +1,51 @@
+/**
+ * @file llfloatergenerictext.h
+ * @brief A generic text floater for dumping info (usually debug info)
+ *
+ * Copyright (c) 2015, Cinder Roxley <cinder@sdf.org>
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef LL_FLOATERGENERICTEXT_H
+#define LL_FLOATERGENERICTEXT_H
+
+#include "llfloater.h"
+
+class LLFloaterGenericText final : public LLFloater
+{
+public:
+	LLFloaterGenericText(const LLSD& key);
+	BOOL postBuild() override;
+private:
+	~LLFloaterGenericText() = default;
+	void onClickClose();
+	void onClickCopy();
+	
+	std::string mTitle;
+	std::string mContents;
+	
+};
+
+#endif // LL_FLOATERGENERICTEXT_H
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 36388ec24622bda8dc8e51ff0a5b0d9e744fcef5..2a55134f6169eed062ed2f66fd6ab61fd229465a 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -101,6 +101,7 @@
 #include "lltextbox.h"
 #include "llui.h"
 #include "llversioninfo.h"
+#include "llviewernetwork.h"
 #include "llviewerobjectlist.h"
 #include "llvoavatar.h"
 #include "llvovolume.h"
@@ -353,6 +354,12 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.DeleteTranscripts",      boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
 	mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false));
 
+	mCommitCallbackRegistrar.add("Pref.AddGrid", boost::bind(&LLFloaterPreference::onClickAddGrid, this));
+    mCommitCallbackRegistrar.add("Pref.ActivateGrid", boost::bind(&LLFloaterPreference::onClickActivateGrid, this));
+	mCommitCallbackRegistrar.add("Pref.RemoveGrid", boost::bind(&LLFloaterPreference::onClickRemoveGrid, this));
+	mCommitCallbackRegistrar.add("Pref.RefreshGrid", boost::bind(&LLFloaterPreference::onClickRefreshGrid, this));
+	mCommitCallbackRegistrar.add("Pref.DebugGrid", boost::bind(&LLFloaterPreference::onClickDebugGrid, this));
+	mCommitCallbackRegistrar.add("Pref.SelectGrid", boost::bind(&LLFloaterPreference::onSelectGrid, this, _2));
 	mCommitCallbackRegistrar.add("Pref.AddSkin", boost::bind(&LLFloaterPreference::onAddSkin, this));
 	mCommitCallbackRegistrar.add("Pref.RemoveSkin", boost::bind(&LLFloaterPreference::onRemoveSkin, this));
 	mCommitCallbackRegistrar.add("Pref.ApplySkin", boost::bind(&LLFloaterPreference::onApplySkin, this));
@@ -463,6 +470,9 @@ BOOL LLFloaterPreference::postBuild()
 
 	LLLogChat::getInstance()->setSaveHistorySignal(boost::bind(&LLFloaterPreference::onLogChatHistorySaved, this));
 	
+	refreshGridList();
+	mGridListChangedConnection = LLGridManager::getInstance()->addGridListChangedCallback(boost::bind(&LLFloaterPreference::refreshGridList, this));
+	
 	loadUserSkins();
 	
 
@@ -517,6 +527,109 @@ void LLFloaterPreference::onDoNotDisturbResponseChanged()
 	gSavedPerAccountSettings.setBOOL("DoNotDisturbResponseChanged", response_changed_flag );
 }
 
+////////////////////////////////////////////////////
+// Grid panel
+
+void LLFloaterPreference::refreshGridList()
+{
+	LLScrollListCtrl* grid_list = getChild<LLScrollListCtrl>("grid_list");
+	grid_list->clearRows();
+	std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
+	for (auto& known_grid : known_grids)
+    {
+		if (!known_grid.first.empty() && !known_grid.second.empty())
+		{
+			bool connected_grid = LLGridManager::getInstance()->getGrid() == known_grid.first;
+			std::vector<std::string> uris;
+			LLGridManager::getInstance()->getLoginURIs(known_grid.first, uris);
+			LLURI login_uri = LLURI(uris.at(0));
+			
+			LLSD row;
+			row["id"] = known_grid.first;
+			row["columns"][0]["column"] = "grid_label";
+			row["columns"][0]["value"] = known_grid.second;
+			row["columns"][0]["font"]["style"] = connected_grid ? "BOLD" : "NORMAL";
+			row["columns"][1]["column"] = "login_uri";
+			row["columns"][1]["value"] = login_uri.authority();
+			row["columns"][1]["font"]["style"] = connected_grid ? "BOLD" : "NORMAL";
+			
+			grid_list->addElement(row);
+		}
+	}
+}
+
+void LLFloaterPreference::onClickAddGrid()
+{
+	std::string login_uri = getChild<LLLineEditor>("add_grid")->getValue().asString();
+	LLGridManager::getInstance()->addRemoteGrid(login_uri, LLGridManager::ADD_MANUAL);
+}
+
+void LLFloaterPreference::onClickActivateGrid()
+{
+    std::string grid = getChild<LLScrollListCtrl>("grid_list")->getSelectedValue().asString();
+    LLGridManager::getInstance()->setGridChoice(grid);
+}
+
+void LLFloaterPreference::onClickRemoveGrid()
+{
+	std::string grid = getChild<LLScrollListCtrl>("grid_list")->getSelectedValue().asString();
+	if (LLGridManager::getInstance()->getGrid() == grid)
+	{
+		LLNotificationsUtil::add("CannotRemoveConnectedGrid",
+								 LLSD().with("GRID", LLGridManager::getInstance()->getGridLabel()));
+	}
+	else
+	{
+		LLNotificationsUtil::add("ConfirmRemoveGrid",
+								 LLSD().with("GRID", LLGridManager::getInstance()->getGridLabel(grid)),
+								 LLSD(grid), boost::bind(&LLFloaterPreference::handleRemoveGridCB, this, _1, _2));
+	}
+}
+
+void LLFloaterPreference::onClickRefreshGrid()
+{
+	std::string grid = getChild<LLScrollListCtrl>("grid_list")->getSelectedValue().asString();
+	// So I'm a little paranoid, no big deal...
+	if (!LLGridManager::getInstance()->isSystemGrid(grid))
+	{
+		LLGridManager::getInstance()->addRemoteGrid(grid, LLGridManager::ADD_MANUAL);
+	}
+}
+
+void LLFloaterPreference::onClickDebugGrid()
+{
+	LLSD args;
+	std::stringstream data_str;
+	const std::string& grid = getChild<LLScrollListCtrl>("grid_list")->getSelectedValue().asString().c_str();
+	LLSD gridInfo = LLGridManager::getInstance()->getGridInfo(grid);
+	LLSDSerialize::toPrettyXML(gridInfo, data_str);
+	args["title"] = llformat("%s - %s", LLTrans::getString("GridInfoTitle").c_str(), grid.c_str());
+	args["data"] = data_str.str();
+	LLFloaterReg::showInstance("generic_text", args);
+}
+
+void LLFloaterPreference::onSelectGrid(const LLSD& data)
+{
+    getChild<LLUICtrl>("activate_grid")->setEnabled(LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP
+                                                    && LLGridManager::getInstance()->getGrid() != data.asString());
+	getChild<LLUICtrl>("remove_grid")->setEnabled(LLGridManager::getInstance()->getGrid() != data.asString()
+												  && !LLGridManager::getInstance()->isSystemGrid(data.asString()));
+	getChild<LLUICtrl>("refresh_grid")->setEnabled(!LLGridManager::getInstance()->isSystemGrid(data.asString()));
+	getChild<LLUICtrl>("debug_grid")->setEnabled(!data.asString().empty());
+}
+
+bool LLFloaterPreference::handleRemoveGridCB(const LLSD& notification, const LLSD& response)
+{
+	const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (0 == option)
+	{
+		const std::string& grid = notification["payload"].asString();
+		if (!LLGridManager::getInstance()->removeGrid(grid))
+			LLNotificationsUtil::add("RemoveGridFailure",
+									 LLSD().with("GRID", notification["substitutions"]["GRID"].asString()));
+	}
+	return false;
+}
 
 ////////////////////////////////////////////////////
 // Skins panel
@@ -777,6 +890,9 @@ void LLFloaterPreference::refreshSkinInfo(const skin_t& skin)
 
 LLFloaterPreference::~LLFloaterPreference()
 {
+	
+	if (mGridListChangedConnection.connected())
+		mGridListChangedConnection.disconnect();
 	LLConversationLog::instance().removeObserver(this);
 }
 
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 5641d5db56f242dfa37d544d3992bfecd6049949..a9b95acf2cd7d91a992d21e604fa4c434f831d62 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -202,6 +202,14 @@ class LLFloaterPreference final : public LLFloater, public LLAvatarPropertiesObs
 	void updateMaxComplexity();
 	static bool loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map);
 
+	void refreshGridList();
+	void onClickAddGrid();
+    void onClickActivateGrid();
+	void onClickRemoveGrid();
+	void onClickRefreshGrid();
+	void onClickDebugGrid();
+	void onSelectGrid(const LLSD& data);
+	bool handleRemoveGridCB(const LLSD& notification, const LLSD& response);
 	
 	void loadUserSkins();
 	void reloadSkinList();
@@ -230,6 +238,8 @@ class LLFloaterPreference final : public LLFloater, public LLAvatarPropertiesObs
 	typedef std::map<std::string, skin_t> skinmap_t;
 	skinmap_t mUserSkins;
 	
+	boost::signals2::connection mGridListChangedConnection;
+
 	LOG_CLASS(LLFloaterPreference);
 
 	LLSearchEditor *mFilterEdit;
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index e4078ac81663dd3d7b21cdfa53f9ff3ebe1bcf94..04f78d0b4ab03c3bb96a34f985aa54cb55eb1824 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -33,6 +33,7 @@
 
 #include "alfloaterao.h"
 #include "alfloaterexploresounds.h"
+#include "alfloatergenerictext.h"
 #include "alfloaterparticleeditor.h"
 #include "alfloaterregiontracker.h"
 #include "llcommandhandler.h"
@@ -417,6 +418,7 @@ void LLViewerFloaterReg::registerFloaters()
 
 	LLFloaterReg::add("ao", "floater_ao.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterAO>);
 	LLFloaterReg::add("delete_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeleteQueue>);
+	LLFloaterReg::add("generic_text", "floater_generic_text.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGenericText>);
 	LLFloaterReg::add("music_ticker", "floater_music_ticker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
 	LLFloaterReg::add("particle_editor", "floater_particle_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterParticleEditor>);
 	LLFloaterReg::add("quick_settings", "floater_quick_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
diff --git a/indra/newview/skins/default/xui/en/floater_generic_text.xml b/indra/newview/skins/default/xui/en/floater_generic_text.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c0f6ed0b045ae3a2d6f87884d29b90ef0dbfff0a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_generic_text.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater can_close="true"
+ single_instance="false"
+ can_drag_on_left="false"
+ can_minimize="true"
+ can_resize="true"
+ height="258"
+ width="258"
+ min_width="214"
+ min_height="100"
+ name="floater_generic_text"
+ title="INFO">
+  <text_editor
+   type="string"
+   length="1"
+   enabled="false"
+   follows="left|top|right|bottom"
+   font="SansSerif"
+   height="200"
+   layout="topleft"
+   top="4"
+   bottom="-32"
+   left="4"
+   right="-4"
+   max_length="65536"
+   name="payload"
+   word_wrap="true">
+It doesn't matter what comes, fresh goes better in life, with Mentos fresh and full of Life! Nothing gets to you, stayin' fresh, stayin' cool, with Mentos fresh and full of life! Fresh goes better! Mentos freshness! Fresh goes better with Mentos, fresh and full of life! Mentos! The Freshmaker!
+  </text_editor>
+  <button
+   follows="right|bottom"
+   label="Copy"
+   name="copy_btn"
+   left="49"
+   top_pad="2"
+   height="26"
+   width="100">
+    <button.commit_callback
+     function="GenericText.Copy" />
+  </button>
+  <button
+   follows="right|bottom"
+   label="Close"
+   name="close_btn"
+   left_pad="4"
+   top_delta="0"
+   height="26"
+   width="100">
+    <button.commit_callback
+     function="GenericText.Close" />
+  </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 7200fe09c779ca9a75c76056d89a1d9352155cde..dd64f60a53e1666c89066366ff785e8c2e57859d 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -180,6 +180,11 @@
          label="Interface"
          layout="topleft"
          name="interface" />
+        <panel
+         filename="panel_preferences_grids.xml"
+         label="Grids"
+         layout="topleft"
+         name="grids" />
     </tab_container>
 
 </floater>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 5d891ea24c3f6f9b665613d86870a9190b4b0697..3659e16c0dea8def0e8a5ee497045f6e18a46796 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -11994,6 +11994,82 @@ Unable to load the track from [TRACK1] into [TRACK2].
     Dice Roll: [RESULT]
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="InvalidGrid"
+   type="alertmodal">
+    <tag>fail</tag>
+    <tag>opensim</tag>
+    '[GRID]' is not a valid grid identifier.
+  </notification>
+  <notification
+   icon="alertmodal.tga"
+   name="MalformedGridInfo"
+   type="alertmodal">
+    <tag>fail</tag>
+    <tag>opensim</tag>
+    [GRID] provided malformed grid info.
+
+    Please contact them for support.
+  </notification>
+  <notification
+   icon="alertmodal.tga"
+   name="CannotRemoveConnectedGrid"
+   type="alertmodal">
+    <tag>fail</tag>
+    <tag>opensim</tag>
+    [GRID] cannot be removed while you are connected to it.
+  </notification>
+  <notification
+   icon="alertmodal.tga"
+   name="ConfirmRemoveGrid"
+   type="alertmodal">
+    <tag>opensim</tag>
+    <tag>confirm</tag>
+    Are you sure you want to remove [GRID] from the grid list?
+    <usetemplate
+     ignoretext="Confirm removing grids"
+     name="okcancelignore"
+     notext="Cancel"
+     yestext="OK"/>
+  </notification>
+  <notification
+   icon="alertmodal.tga"
+   name="RemoveGridFailure"
+   type="alertmodal">
+    <tag>fail</tag>
+    <tag>opensim</tag>
+    Failed to remove [GRID] from the list.
+  </notification>
+  <notification
+   icon="alertmodal.tga"
+   name="CantAddGrid"
+   type="alertmodal">
+    <tag>fail</tag>
+    <tag>opensim</tag>
+Could not get grid info for [GRID].
+Error: [STATUS] [REASON]
+  </notification>
+  <notification
+   icon="alertmodal.tga"
+   name="AddGridSuccess"
+   type="alertmodal">
+    <form name="form">
+      <ignore name="ignore"
+       text="A grid was added to the grid list"/>
+    </form>
+    <tag>fail</tag>
+    <tag>opensim</tag>
+[GRID] has been added to your grid list.
+  </notification>
+
+  <notification
+   icon="notify.tga"
+   name="SecondLifePasswordTooLong"
+   type="notify">
+    Due to a bug in the Second Life signup process, your password is longer than 16 characters and had been truncated to allow logging in.
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="ConfirmRemoveSkin"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_grids.xml b/indra/newview/skins/default/xui/en/panel_preferences_grids.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6c35c446ace5394148071373aca0e2bf4dae5399
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_grids.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="Grids"
+ layout="topleft"
+ left="102"
+ name="grids"
+ top="1"
+ width="517">
+  <text
+   type="string"
+   length="1"
+   follows="left|top"
+   height="12"
+   layout="topleft"
+   left="30"
+   name="add_grid_text"
+   top="12"
+   width="400">
+   Add new grid:
+  </text>
+  <line_editor
+   border_style="line"
+   border_thickness="1"
+   follows="left|top"
+   font="SansSerif"
+   height="19"
+   layout="topleft"
+   left="50"
+   max_length_chars="4096"
+   name="add_grid"
+   top_pad="8"
+   label="Enter a LoginURI"
+   width="320" />
+  <button
+   layout="topleft"
+   follows="left|top"
+   height="19"
+   label="Add"
+   left_pad="2"
+   name="add_grid_commit"
+   top_delta="0"
+   width="50">
+    <button.commit_callback
+     function="Pref.AddGrid" />
+  </button>
+  <text
+   type="string"
+   length="1"
+   layout="topleft"
+   follows="left|top"
+   height="12"
+   left="30"
+   name="manage_grid_text"
+   top_pad="4"
+   width="400">
+   Manage grids:
+  </text>
+  <scroll_list
+   layout="topleft"
+   follows="left|top"
+   height="225"
+   left="50"
+   name="grid_list"
+   draw_heading="true"
+   top_pad="8"
+   width="370">
+    <scroll_list.columns
+     label="Grid name"
+     name="grid_label"
+     width="150" />
+    <scroll_list.columns
+     dynamic_width="true"
+     label="Login URI"
+     name="login_uri" />
+    <scroll_list.commit_callback
+     function="Pref.SelectGrid" />
+  </scroll_list>
+  <button
+   enabled="false"
+   layout="topleft"
+   follows="left|top"
+   height="19"
+   label="Activate"
+   left_pad="5"
+   name="activate_grid"
+   top_delta="5"
+   width="75">
+    <button.commit_callback
+     function="Pref.ActivateGrid" />
+  </button>
+  <button
+    enabled="false"
+    layout="topleft"
+    follows="left|top"
+    height="19"
+    label="Refresh"
+    left_delta="0"
+    name="refresh_grid"
+    top_pad="5"
+    width="75">
+     <button.commit_callback
+      function="Pref.RefreshGrid" />
+  </button>
+  <button
+   enabled="false"
+   layout="topleft"
+   follows="left|top"
+   height="19"
+   label="Remove"
+   left_delta="0"
+   name="remove_grid"
+   top_pad="5"
+   width="75">
+    <button.commit_callback
+     function="Pref.RemoveGrid" />
+  </button>
+  <button
+   enabled="false"
+   layout="topleft"
+   follows="left|top"
+   height="19"
+   label="Debug"
+   left_delta="0"
+   name="debug_grid"
+   top_pad="5"
+   width="75">
+    <button.commit_callback
+     function="Pref.DebugGrid" />
+  </button>
+  <check_box
+   control_name="ForceShowGrid"
+   height="20"
+   layout="topleft"
+   follows="left|top"
+   label="Show Grid Selection at Login"
+   left="30"
+   name="show_grid_selection_check"
+   tool_tip="Show grid selection on login screen to login to other worlds"
+   width="280"
+   top="310" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index db96d5bf3a1eb549fc39a459ccf585e79bf96a8c..a2ed595b26b1e5f0edf31d51ec519e935b00614c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -4370,5 +4370,6 @@ and report the problem.
   <string name="AvatarTyping">Typing</string>
   <string name="UnknownAvatar">Unknown Avatar</string>
   <string name="NotAvailableOnPlatform">Not availalbe on this platform</string>
+  <string name="GridInfoTitle">GRID INFO</string>
   
 </strings>