diff --git a/doc/contributions.txt b/doc/contributions.txt
index 780fa0e3c88b46235ef3ae5ec7bcc2be266f4f17..740c2f470c6a39ee4e3ce4377a2738246d4d87fd 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -373,6 +373,8 @@ Khyota Wulluf
 Kitty Barnett
 	VWR-19699
 	STORM-288
+	STORM-799
+	STORM-800
 Kunnis Basiat
 	VWR-82
 	VWR-102
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e51f28e2e9b19ee8d973b06090c4058ea79f6ccc..4f7b4be52609206899dee5e9934bdf6c9aa49d62 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -805,6 +805,69 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const
 	return ::getStringAfterToken(url, "://");
 }
 
+//
+// LLUrlEntryRegion Describes secondlife:///app/region/REGION_NAME/X/Y/Z URLs, e.g.
+// secondlife:///app/region/Ahern/128/128/0
+//
+LLUrlEntryRegion::LLUrlEntryRegion()
+{
+	mPattern = boost::regex("secondlife:///app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
+							boost::regex::perl|boost::regex::icase);
+	mMenuName = "menu_url_slurl.xml";
+	mTooltip = LLTrans::getString("TooltipSLURL");
+}
+
+std::string LLUrlEntryRegion::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+	//
+	// we handle SLURLs in the following formats:
+	//   - secondlife:///app/region/Place/X/Y/Z
+	//   - secondlife:///app/region/Place/X/Y
+	//   - secondlife:///app/region/Place/X
+	//   - secondlife:///app/region/Place
+	//
+
+	LLSD path_array = LLURI(url).pathArray();
+	S32 path_parts = path_array.size();
+
+	if (path_parts < 3) // no region name
+	{
+		llwarns << "Failed to parse url [" << url << "]" << llendl;
+		return url;
+	}
+
+	std::string label = unescapeUrl(path_array[2]); // region name
+
+	if (path_parts > 3) // secondlife:///app/region/Place/X
+	{
+		std::string x = path_array[3];
+		label += " (" + x;
+
+		if (path_parts > 4) // secondlife:///app/region/Place/X/Y
+		{
+			std::string y = path_array[4];
+			label += "," + y;
+
+			if (path_parts > 5) // secondlife:///app/region/Place/X/Y/Z
+			{
+				std::string z = path_array[5];
+				label = label + "," + z;
+			}
+		}
+
+		label += ")";
+	}
+
+	return label;
+}
+
+std::string LLUrlEntryRegion::getLocation(const std::string &url) const
+{
+	LLSD path_array = LLURI(url).pathArray();
+	std::string region_name = unescapeUrl(path_array[2]);
+	return region_name;
+}
+
 //
 // LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
 // secondlife:///app/teleport/Ahern/50/50/50/
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 43a667c3909599c3a950bd4d3b72d8eea0f59bb8..1791739061cdae4c3cf3db6891984ef99d2eeb08 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -301,6 +301,18 @@ class LLUrlEntryPlace : public LLUrlEntryBase
 	/*virtual*/ std::string getLocation(const std::string &url) const;
 };
 
+///
+/// LLUrlEntryRegion Describes a Second Life location Url, e.g.,
+/// secondlife:///app/region/Ahern/128/128/0
+///
+class LLUrlEntryRegion : public LLUrlEntryBase
+{
+public:
+	LLUrlEntryRegion();
+	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+	/*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
 ///
 /// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
 /// secondlife:///app/teleport/Ahern/50/50/50/
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 478b412d5ea541a2bbd908d9b4f3055bede59882..523ee5d78c6534c1682d4aee4f166b52c92b4bab 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -54,6 +54,7 @@ LLUrlRegistry::LLUrlRegistry()
 	registerUrl(new LLUrlEntryGroup());
 	registerUrl(new LLUrlEntryParcel());
 	registerUrl(new LLUrlEntryTeleport());
+	registerUrl(new LLUrlEntryRegion());
 	registerUrl(new LLUrlEntryWorldMap());
 	registerUrl(new LLUrlEntryObjectIM());
 	registerUrl(new LLUrlEntryPlace());
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 59c0826ad79de90257270e520cfeebbedabd3883..8f0a48018fb26132f0ca1b5257a1110850dce4d3 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -103,6 +103,45 @@ namespace tut
 		ensure_equals(testname, url, expected);
 	}
 
+	void dummyCallback(const std::string &url, const std::string &label, const std::string& icon)
+	{
+	}
+
+	void testLabel(const std::string &testname, LLUrlEntryBase &entry,
+				   const char *text, const std::string &expected)
+	{
+		boost::regex regex = entry.getPattern();
+		std::string label = "";
+		boost::cmatch result;
+		bool found = boost::regex_search(text, result, regex);
+		if (found)
+		{
+			S32 start = static_cast<U32>(result[0].first - text);
+			S32 end = static_cast<U32>(result[0].second - text);
+			std::string url = std::string(text+start, end-start);
+			label = entry.getLabel(url, boost::bind(dummyCallback, _1, _2, _3));
+		}
+		ensure_equals(testname, label, expected);
+	}
+
+	void testLocation(const std::string &testname, LLUrlEntryBase &entry,
+					  const char *text, const std::string &expected)
+	{
+		boost::regex regex = entry.getPattern();
+		std::string location = "";
+		boost::cmatch result;
+		bool found = boost::regex_search(text, result, regex);
+		if (found)
+		{
+			S32 start = static_cast<U32>(result[0].first - text);
+			S32 end = static_cast<U32>(result[0].second - text);
+			std::string url = std::string(text+start, end-start);
+			location = entry.getLocation(url);
+		}
+		ensure_equals(testname, location, expected);
+	}
+
+
 	template<> template<>
 	void object::test<1>()
 	{
@@ -697,4 +736,114 @@ namespace tut
 				  "<nolink>My Object</nolink>",
 				  "My Object");
 	}
+
+	template<> template<>
+	void object::test<13>()
+	{
+		//
+		// test LLUrlEntryRegion - secondlife:///app/region/<location> URLs
+		//
+		LLUrlEntryRegion url;
+
+		// Regex tests.
+		testRegex("no valid region", url,
+				  "secondlife:///app/region/",
+				  "");
+
+		testRegex("invalid coords", url,
+				  "secondlife:///app/region/Korea2/a/b/c",
+				  "secondlife:///app/region/Korea2/"); // don't count invalid coords
+
+		testRegex("Ahern (50,50,50) [1]", url,
+				  "secondlife:///app/region/Ahern/50/50/50/",
+				  "secondlife:///app/region/Ahern/50/50/50/");
+
+		testRegex("Ahern (50,50,50) [2]", url,
+				  "XXX secondlife:///app/region/Ahern/50/50/50/ XXX",
+				  "secondlife:///app/region/Ahern/50/50/50/");
+
+		testRegex("Ahern (50,50,50) [3]", url,
+				  "XXX secondlife:///app/region/Ahern/50/50/50 XXX",
+				  "secondlife:///app/region/Ahern/50/50/50");
+
+		testRegex("Ahern (50,50,50) multicase", url,
+				  "XXX secondlife:///app/region/Ahern/50/50/50/ XXX",
+				  "secondlife:///app/region/Ahern/50/50/50/");
+
+		testRegex("Ahern (50,50) [1]", url,
+				  "XXX secondlife:///app/region/Ahern/50/50/ XXX",
+				  "secondlife:///app/region/Ahern/50/50/");
+
+		testRegex("Ahern (50,50) [2]", url,
+				  "XXX secondlife:///app/region/Ahern/50/50 XXX",
+				  "secondlife:///app/region/Ahern/50/50");
+
+		// DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
+		testRegex("Region with brackets", url,
+				  "XXX secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30 XXX",
+				  "secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30");
+
+		// DEV-35459: SLURLs and teleport Links not parsed properly
+		testRegex("Region with quote", url,
+				  "XXX secondlife:///app/region/A'ksha%20Oasis/41/166/701 XXX",
+			          "secondlife:///app/region/A%27ksha%20Oasis/41/166/701");
+
+		// Rendering tests.
+		testLabel("Render /app/region/Ahern/50/50/50/", url,
+			"secondlife:///app/region/Ahern/50/50/50/",
+			"Ahern (50,50,50)");
+
+		testLabel("Render /app/region/Ahern/50/50/50", url,
+			"secondlife:///app/region/Ahern/50/50/50",
+			"Ahern (50,50,50)");
+
+		testLabel("Render /app/region/Ahern/50/50/", url,
+			"secondlife:///app/region/Ahern/50/50/",
+			"Ahern (50,50)");
+
+		testLabel("Render /app/region/Ahern/50/50", url,
+			"secondlife:///app/region/Ahern/50/50",
+			"Ahern (50,50)");
+
+		testLabel("Render /app/region/Ahern/50/", url,
+			"secondlife:///app/region/Ahern/50/",
+			"Ahern (50)");
+
+		testLabel("Render /app/region/Ahern/50", url,
+			"secondlife:///app/region/Ahern/50",
+			"Ahern (50)");
+
+		testLabel("Render /app/region/Ahern/", url,
+			"secondlife:///app/region/Ahern/",
+			"Ahern");
+
+		testLabel("Render /app/region/Ahern/ within context", url,
+			"XXX secondlife:///app/region/Ahern/ XXX",
+			"Ahern");
+
+		testLabel("Render /app/region/Ahern", url,
+			"secondlife:///app/region/Ahern",
+			"Ahern");
+
+		testLabel("Render /app/region/Ahern within context", url,
+			"XXX secondlife:///app/region/Ahern XXX",
+			"Ahern");
+
+		testLabel("Render /app/region/Product%20Engine/", url,
+			"secondlife:///app/region/Product%20Engine/",
+			"Product Engine");
+
+		testLabel("Render /app/region/Product%20Engine", url,
+			"secondlife:///app/region/Product%20Engine",
+			"Product Engine");
+
+		// Location parsing texts.
+		testLocation("Location /app/region/Ahern/50/50/50/", url,
+			"secondlife:///app/region/Ahern/50/50/50/",
+			"Ahern");
+
+		testLocation("Location /app/region/Product%20Engine", url,
+			"secondlife:///app/region/Product%20Engine",
+			"Product Engine");
+	}
 }
diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp
index 58b3f0309fd795d10718af884d17214822b98903..d7b82667d17732dacbfa5a7e6521c011f4f8af3f 100644
--- a/indra/newview/llinspecttoast.cpp
+++ b/indra/newview/llinspecttoast.cpp
@@ -46,6 +46,7 @@ class LLInspectToast: public LLInspect
 	virtual ~LLInspectToast();
 
 	/*virtual*/ void onOpen(const LLSD& notification_id);
+	/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
 private:
 	void onToastDestroy(LLToast * toast);
 
@@ -73,6 +74,7 @@ LLInspectToast::~LLInspectToast()
 	LLTransientFloaterMgr::getInstance()->removeControlView(this);
 }
 
+// virtual
 void LLInspectToast::onOpen(const LLSD& notification_id)
 {
 	LLInspect::onOpen(notification_id);
@@ -103,6 +105,15 @@ void LLInspectToast::onOpen(const LLSD& notification_id)
 	LLUI::positionViewNearMouse(this);
 }
 
+// virtual
+BOOL LLInspectToast::handleToolTip(S32 x, S32 y, MASK mask)
+{
+	// We don't like the way LLInspect handles tooltips
+	// (black tooltips look weird),
+	// so force using the default implementation (STORM-511).
+	return LLFloater::handleToolTip(x, y, mask);
+}
+
 void LLInspectToast::onToastDestroy(LLToast * toast)
 {
 	closeFloater(false);
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 1249d5d85600563ff67cf4c2954d5cfb39225fef..a9bcdef47cf93b70f13021e19742c43b26216e7e 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -341,10 +341,11 @@ LLPanelAvatarNotes::~LLPanelAvatarNotes()
 	if(getAvatarId().notNull())
 	{
 		LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
-		if(LLVoiceClient::instanceExists())
-		{
-			LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
-		}
+	}
+
+	if(LLVoiceClient::instanceExists())
+	{
+		LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
 	}
 }
 
@@ -758,10 +759,11 @@ LLPanelAvatarProfile::~LLPanelAvatarProfile()
 	if(getAvatarId().notNull())
 	{
 		LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
-		if(LLVoiceClient::instanceExists())
-		{
-			LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
-		}
+	}
+
+	if(LLVoiceClient::instanceExists())
+	{
+		LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
 	}
 }
 
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index 0dff0875533743b50fba8d48709bf4621be93362..e5ef51bdd18c6b54c1ac0e801fa3567f6f15ec87 100644
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -140,22 +140,25 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v
 	typedef std::vector<observer_multimap_t::iterator> deadlist_t;
 	deadlist_t dead_iters;
 
-	observer_multimap_t::iterator oi;
-	observer_multimap_t::iterator start = observers.lower_bound(parcel_data.parcel_id);
+	observer_multimap_t::iterator oi = observers.lower_bound(parcel_data.parcel_id);
 	observer_multimap_t::iterator end = observers.upper_bound(parcel_data.parcel_id);
 
-	for (oi = start; oi != end; ++oi)
+	while (oi != end)
 	{
-		LLRemoteParcelInfoObserver * observer = oi->second.get();
+		// increment the loop iterator now since it may become invalid below
+		observer_multimap_t::iterator cur_oi = oi++;
+
+		LLRemoteParcelInfoObserver * observer = cur_oi->second.get();
 		if(observer)
 		{
+			// may invalidate cur_oi if the observer removes itself 
 			observer->processParcelInfo(parcel_data);
 		}
 		else
 		{
 			// the handle points to an expired observer, so don't keep it
 			// around anymore
-			dead_iters.push_back(oi);
+			dead_iters.push_back(cur_oi);
 		}
 	}
 
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index 563c27c4d739ddbf535a2f01bc2ced256e778a01..75178a6ef8a6fcaa8a560d795d90742be6084636 100644
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -77,6 +77,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
 	from << from_name << "/" << groupData.mName;
 	LLTextBox* pTitleText = getChild<LLTextBox>("title");
 	pTitleText->setValue(from.str());
+	pTitleText->setToolTip(from.str());
 
 	//message subject
 	const std::string& subject = payload["subject"].asString();
diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml
index 1b41f602cd59e3a2bee32dd4742308efab218c1b..5b8abaca6f1b7467f72603bf44805969da26f482 100644
--- a/indra/newview/skins/default/xui/en/panel_my_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml
@@ -185,7 +185,7 @@
               </expandable_text>
             </panel>
             <text
-             follows="left|top"
+             follows="left|top|right"
              height="15"
        font.style="BOLD"
        font="SansSerifMedium"
@@ -200,7 +200,7 @@
              use_ellipses="true"
          />
             <text
-             follows="left|top"
+             follows="left|top|right"
            font.style="BOLD"
              height="10"
              layout="topleft"
@@ -213,7 +213,7 @@
             <text_editor
              allow_scroll="false"
              bg_visible="false"
-             follows="left|top"
+             follows="left|top|right"
              h_pad="0"
              height="15"
              layout="topleft"
@@ -226,7 +226,7 @@
              width="300"
              word_wrap="true" />
             <text
-             follows="left|top"
+             follows="left|top|right"
        font.style="BOLD"
              height="15"
              layout="topleft"
@@ -250,7 +250,7 @@
             <text_editor
             allow_scroll="false"
             bg_visible="false"
-            follows="left|top"
+            follows="left|top|right"
             h_pad="0"
             height="28"
             layout="topleft"
@@ -266,7 +266,7 @@
               Linden.
             </text_editor>
             <text
-             follows="left|top"
+             follows="left|top|right"
        font.style="BOLD"
              height="15"
              layout="topleft"
@@ -277,7 +277,7 @@
              value="Partner:"
              width="300" />
             <panel
-             follows="left|top"
+             follows="left|top|right"
              height="15"
              layout="topleft"
              left="10"
@@ -285,7 +285,7 @@
              top_pad="0"
              width="300">
               <text
-               follows="left|top"
+               follows="left|top|right"
                height="10"
                initial_value="(retrieving)"
                layout="topleft"
@@ -297,7 +297,7 @@
            width="300" />
             </panel>
             <text
-             follows="left|top"
+             follows="left|top|right"
        font.style="BOLD"
              height="13"
              layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index d6e4c5611363e08b7b435a383db2a0737b1c93e7..37aab059a93b2cb85a603c40189b39384be8740a 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -82,7 +82,7 @@
      control_name="AllowMultipleViewers"
      follows="top|left"
      height="15"
-     label="Allow Multiple Viewer"
+     label="Allow Multiple Viewers"
      layout="topleft"
      left="30"
      name="allow_multiple_viewer_check"