diff --git a/autobuild.xml b/autobuild.xml
index d1a7107319fe0586ee9695c0cce873961ede57f3..d38103524856d1196cf519c3b660ba423f7d9d29 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1206,9 +1206,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>82798d0da3ac3d97c91517a575d9ea1c</string>
+              <string>a7c80fd8516df3b879b669b2b220067f</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/231093/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20110526.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/232420/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20110608.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -1230,9 +1230,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>f0708d18943a05013493f69ab7dc6429</string>
+              <string>b9cc0333cc274c9cc40256ab7146b4fc</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/231093/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20110526.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/232420/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20110608.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1570,9 +1570,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>e19576af3c0affc71293d8f0bcce2606</string>
+              <string>24e735ae005f3ce7a21a09cc02cece17</string>
               <key>url</key>
-              <string> http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-darwin-20110120.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/Darwin/installer/slvoice-3.2.0002.10426-darwin-20110601.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -1582,9 +1582,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>53fefed8120d7c6a0eb6778edae6fa32</string>
+              <string>8a0bc982367d6fdc20a28b391cd40566</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-linux-20110120.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/Linux/installer/slvoice-3.2.0002.10426-linux-20110601.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -1594,9 +1594,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>44f84b3b45f7067a104a7c34d50d62f0</string>
+              <string>1e821cc7d25eabad013b7f3db260dd6b</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-windows-20110120.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/CYGWIN/installer/slvoice-3.2.0002.10426-windows-20110601.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 7a3d2a24854af4e5bb37fc436dc3e9d9ff7c8bab..bad78dcd5f2eeeb8be05d5550c45391b7daa874e 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -103,8 +103,6 @@ Ales Beaumont
 Alexandrea Fride
     STORM-255
 	STORM-960
-	STORM-1327
-	STORM-1406
 Alissa Sabre
 	VWR-81
 	VWR-83
@@ -161,6 +159,7 @@ Ann Congrejo
 Ansariel Hiller
 	STORM-1101
 	VWR-25480
+	VWR-26150
 Ardy Lay
 	STORM-859
 	VWR-19499
@@ -446,20 +445,9 @@ Jonathan Yap
 	STORM-1236
 	STORM-1259
 	STORM-787
-	VWR-25480
-	STORM-1334
 	STORM-1313
 	STORM-899
 	STORM-1273
-	STORM-457
-	STORM-1452
-	STORM-1406
-	STORM-1327
-	STORM-1396
-	STORM-1292
-	STORM-1392
-	STORM-1302
-	STORM-1326
 	STORM-1462
 Kage Pixel
 	VWR-11
@@ -793,7 +781,6 @@ Strife Onizuka
 	SNOW-691
 TankMaster Finesmith
 	STORM-1100
-	STORM-1452
 Tayra Dagostino
 	SNOW-517
 	SNOW-543
@@ -926,7 +913,6 @@ WolfPup Lowenhar
 	STORM-825
 	STORM-859
 	STORM-1098
-	STORM-1393
 	VWR-20741
 	VWR-20933
 Zai Lynch
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp
index c2cfb7286e242478506c338335e19caa0cb495bb..f6d0f5bce89f596685e13c78ba52386ad158f8c4 100644
--- a/indra/llcommon/llfoldertype.cpp
+++ b/indra/llcommon/llfoldertype.cpp
@@ -93,6 +93,8 @@ LLFolderDictionary::LLFolderDictionary()
 	addEntry(LLFolderType::FT_MESH, 				new FolderEntry("mesh",	TRUE));
 
 	addEntry(LLFolderType::FT_INBOX, 				new FolderEntry("inbox",	TRUE));
+	addEntry(LLFolderType::FT_OUTBOX, 				new FolderEntry("outbox",	TRUE));
+	addEntry(LLFolderType::FT_BASIC_ROOT,			new FolderEntry("basic_rt", TRUE));
 		 
 	addEntry(LLFolderType::FT_NONE, 				new FolderEntry("-1",		FALSE));
 };
diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h
index cb32cb075b533957d6d3e7e785fa2a5946f1d3af..a0c847914f048c717ba90f05399f5f6ea308a06d 100644
--- a/indra/llcommon/llfoldertype.h
+++ b/indra/llcommon/llfoldertype.h
@@ -83,8 +83,11 @@ public:
 		FT_MESH = 49,
 
 		FT_INBOX = 50,
+		FT_OUTBOX = 51,
 
-		FT_COUNT = 51,
+		FT_BASIC_ROOT = 52,
+
+		FT_COUNT,
 
 		FT_NONE = -1
 	};
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 9f666369d41712f410dfc665538246dbc0fe3885..d3d0403bbbe6347f8ed93ccc85822d583a3a7664 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -1,1436 +1,1424 @@
-/** 
- * @file llpluginclassmedia.cpp
- * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&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$
- * @endcond
- */
-
-#include "linden_common.h"
-#include "indra_constants.h"
-
-#include "llpluginclassmedia.h"
-#include "llpluginmessageclasses.h"
-
-#include "llqtwebkit.h"
-
-static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
-
-static int nextPowerOf2( int value )
-{
-	int next_power_of_2 = 1;
-	while ( next_power_of_2 < value )
-	{
-		next_power_of_2 <<= 1;
-	}
-	
-	return next_power_of_2;
-}
-
-LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
-{
-	mOwner = owner;
-	mPlugin = NULL;
-	reset();
-
-	//debug use
-	mDeleteOK = true ;
-}
-
-
-LLPluginClassMedia::~LLPluginClassMedia()
-{
-	llassert_always(mDeleteOK) ;
-	reset();
-}
-
-bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
-{	
-	LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
-	LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
-	LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
-	
-	mPlugin = new LLPluginProcessParent(this);
-	mPlugin->setSleepTime(mSleepTime);
-	
-	// Queue up the media init message -- it will be sent after all the currently queued messages.
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
-	message.setValue("target", mTarget);
-	sendMessage(message);
-	
-	mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
-
-	return true;
-}
-
-
-void LLPluginClassMedia::reset()
-{
-	if(mPlugin != NULL)
-	{
-		delete mPlugin;
-		mPlugin = NULL;
-	}
-
-	mTextureParamsReceived = false;
-	mRequestedTextureDepth = 0;
-	mRequestedTextureInternalFormat = 0;
-	mRequestedTextureFormat = 0;
-	mRequestedTextureType = 0;
-	mRequestedTextureSwapBytes = false;
-	mRequestedTextureCoordsOpenGL = false;
-	mTextureSharedMemorySize = 0;
-	mTextureSharedMemoryName.clear();
-	mDefaultMediaWidth = 0;
-	mDefaultMediaHeight = 0;
-	mNaturalMediaWidth = 0;
-	mNaturalMediaHeight = 0;
-	mSetMediaWidth = -1;
-	mSetMediaHeight = -1;
-	mRequestedMediaWidth = 0;
-	mRequestedMediaHeight = 0;
-	mRequestedTextureWidth = 0;
-	mRequestedTextureHeight = 0;
-	mFullMediaWidth = 0;
-	mFullMediaHeight = 0;
-	mTextureWidth = 0;
-	mTextureHeight = 0;
-	mMediaWidth = 0;
-	mMediaHeight = 0;
-	mDirtyRect = LLRect::null;	
-	mAutoScaleMedia = false;
-	mRequestedVolume = 1.0f;
-	mPriority = PRIORITY_NORMAL;
-	mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
-	mAllowDownsample = false;
-	mPadding = 0;
-	mLastMouseX = 0;
-	mLastMouseY = 0;
-	mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
-	mSleepTime = 1.0f / 100.0f;
-	mCanCut = false;
-	mCanCopy = false;
-	mCanPaste = false;
-	mMediaName.clear();
-	mMediaDescription.clear();
-	mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
-	
-	// media_browser class
-	mNavigateURI.clear();
-	mNavigateResultCode = -1;
-	mNavigateResultString.clear();
-	mHistoryBackAvailable = false;
-	mHistoryForwardAvailable = false;
-	mStatusText.clear();
-	mProgressPercent = 0;	
-	mClickURL.clear();
-	mClickNavType.clear();
-	mClickTarget.clear();
-	mClickUUID.clear();
-	mStatusCode = 0;
-	
-	// media_time class
-	mCurrentTime = 0.0f;
-	mDuration = 0.0f;
-	mCurrentRate = 0.0f;
-	mLoadedDuration = 0.0f;
-}
-
-void LLPluginClassMedia::idle(void)
-{
-	if(mPlugin)
-	{
-		mPlugin->idle();
-	}
-	
-	if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
-	{
-		// Can't process a size change at this time
-	}
-	else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
-	{
-		// Calculate the correct size for the media texture
-		mRequestedTextureHeight = mRequestedMediaHeight;
-		if(mPadding < 0)
-		{
-			// negative values indicate the plugin wants a power of 2
-			mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
-		}
-		else
-		{
-			mRequestedTextureWidth = mRequestedMediaWidth;
-			
-			if(mPadding > 1)
-			{
-				// Pad up to a multiple of the specified number of bytes per row
-				int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
-				int pad = rowbytes % mPadding;
-				if(pad != 0)
-				{
-					rowbytes += mPadding - pad;
-				}
-				
-				if(rowbytes % mRequestedTextureDepth == 0)
-				{
-					mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
-				}
-				else
-				{
-					LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
-				}
-			}
-		}
-
-		
-		// Size change has been requested but not initiated yet.
-		size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
-
-		// Add an extra line for padding, just in case.
-		newsize += mRequestedTextureWidth * mRequestedTextureDepth;
-
-		if(newsize != mTextureSharedMemorySize)
-		{
-			if(!mTextureSharedMemoryName.empty())
-			{
-				// Tell the plugin to remove the old memory segment
-				mPlugin->removeSharedMemory(mTextureSharedMemoryName);
-				mTextureSharedMemoryName.clear();
-			}
-			
-			mTextureSharedMemorySize = newsize;
-			mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
-			if(!mTextureSharedMemoryName.empty())
-			{
-				void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-				
-				// clear texture memory to avoid random screen visual fuzz from uninitialized texture data
-				memset( addr, 0x00, newsize );
-				
-				// We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
-				// so it may not be worthwhile.
-				// mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
-			}
-		}
-		
-		// This is our local indicator that a change is in progress.
-		mTextureWidth = -1;
-		mTextureHeight = -1;
-		mMediaWidth = -1;
-		mMediaHeight = -1;
-
-		// This invalidates any existing dirty rect.
-		resetDirty();
-		
-		// Send a size change message to the plugin
-		{
-			LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
-			message.setValue("name", mTextureSharedMemoryName);
-			message.setValueS32("width", mRequestedMediaWidth);
-			message.setValueS32("height", mRequestedMediaHeight);
-			message.setValueS32("texture_width", mRequestedTextureWidth);
-			message.setValueS32("texture_height", mRequestedTextureHeight);
-			message.setValueReal("background_r", mBackgroundColor.mV[VX]);
-			message.setValueReal("background_g", mBackgroundColor.mV[VY]);
-			message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
-			message.setValueReal("background_a", mBackgroundColor.mV[VW]);
-			mPlugin->sendMessage(message);	// DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
-			
-			LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
-		}
-	}
-	
-	if(mPlugin && mPlugin->isRunning())
-	{
-		// Send queued messages
-		while(!mSendQueue.empty())
-		{
-			LLPluginMessage message = mSendQueue.front();
-			mSendQueue.pop();
-			mPlugin->sendMessage(message);
-		}
-	}
-}
-
-int LLPluginClassMedia::getTextureWidth() const
-{
-	return nextPowerOf2(mTextureWidth);
-}
-
-int LLPluginClassMedia::getTextureHeight() const
-{
-	return nextPowerOf2(mTextureHeight);
-}
-
-unsigned char* LLPluginClassMedia::getBitsData()
-{
-	unsigned char *result = NULL;
-	if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
-	{
-		result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-	}
-	return result;
-}
-
-void LLPluginClassMedia::setSize(int width, int height)
-{
-	if((width > 0) && (height > 0))
-	{
-		mSetMediaWidth = width;
-		mSetMediaHeight = height;
-	}
-	else
-	{
-		mSetMediaWidth = -1;
-		mSetMediaHeight = -1;
-	}
-
-	setSizeInternal();
-}
-
-void LLPluginClassMedia::setSizeInternal(void)
-{
-	if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
-	{
-		mRequestedMediaWidth = mSetMediaWidth;
-		mRequestedMediaHeight = mSetMediaHeight;
-	}
-	else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
-	{
-		mRequestedMediaWidth = mNaturalMediaWidth;
-		mRequestedMediaHeight = mNaturalMediaHeight;
-	}
-	else
-	{
-		mRequestedMediaWidth = mDefaultMediaWidth;
-		mRequestedMediaHeight = mDefaultMediaHeight;
-	}
-	
-	// Save these for size/interest calculations
-	mFullMediaWidth = mRequestedMediaWidth;
-	mFullMediaHeight = mRequestedMediaHeight;
-	
-	if(mAllowDownsample)
-	{
-		switch(mPriority)
-		{
-			case PRIORITY_SLIDESHOW:
-			case PRIORITY_LOW:
-				// Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
-				while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
-				{
-					mRequestedMediaWidth /= 2;
-					mRequestedMediaHeight /= 2;
-				}
-			break;
-			
-			default:
-				// Don't adjust texture size
-			break;
-		}
-	}
-	
-	if(mAutoScaleMedia)
-	{
-		mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
-		mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
-	}
-	
-	if(mRequestedMediaWidth > 2048)
-		mRequestedMediaWidth = 2048;
-
-	if(mRequestedMediaHeight > 2048)
-		mRequestedMediaHeight = 2048;
-}
-
-void LLPluginClassMedia::setAutoScale(bool auto_scale)
-{
-	if(auto_scale != mAutoScaleMedia)
-	{
-		mAutoScaleMedia = auto_scale;
-		setSizeInternal();
-	}
-}
-
-bool LLPluginClassMedia::textureValid(void)
-{
-	if(
-		!mTextureParamsReceived ||
-		mTextureWidth <= 0 ||
-		mTextureHeight <= 0 ||
-		mMediaWidth <= 0 ||
-		mMediaHeight <= 0 ||
-		mRequestedMediaWidth != mMediaWidth ||
-		mRequestedMediaHeight != mMediaHeight ||
-		getBitsData() == NULL
-	)	
-		return false;
-	
-	return true;
-}
-
-bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
-{
-	bool result = !mDirtyRect.isEmpty();
-
-	if(dirty_rect != NULL)
-	{
-		*dirty_rect = mDirtyRect;
-	}
-
-	return result;
-}
-
-void LLPluginClassMedia::resetDirty(void)
-{
-	mDirtyRect = LLRect::null;
-}
-
-std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
-{
-	std::string result;
-	
-	
-	if(modifiers & MASK_CONTROL)
-	{
-		result += "control|";
-	}
-
-	if(modifiers & MASK_ALT)
-	{
-		result += "alt|";
-	}
-
-	if(modifiers & MASK_SHIFT)
-	{
-		result += "shift|";
-	}
-
-	// TODO: should I deal with platform differences here or in callers?
-	// TODO: how do we deal with the Mac "command" key?
-/*
-	if(modifiers & MASK_SOMETHING)
-	{
-		result += "meta|";
-	}
-*/	
-	return result;
-}
-
-void LLPluginClassMedia::jsExposeObjectEvent( bool expose )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_expose_object");
-	message.setValueBoolean( "expose", expose );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsValuesValidEvent( bool valid )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_values_valid");
-	message.setValueBoolean( "valid", valid );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
-	message.setValueReal( "x", x );
-	message.setValueReal( "y", y );
-	message.setValueReal( "z", z );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
-	message.setValueReal( "x", x );
-	message.setValueReal( "y", y );
-	message.setValueReal( "z", z );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
-	message.setValueReal( "angle", angle );
-
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
-	message.setValue( "language", language );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
-	message.setValue( "region", region );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
-	message.setValue( "maturity", maturity );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
-{
-	if(type == MOUSE_EVENT_MOVE)
-	{
-		if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
-		{
-			// Don't queue up mouse move events that can't be delivered.
-			return;
-		}
-
-		if((x == mLastMouseX) && (y == mLastMouseY))
-		{
-			// Don't spam unnecessary mouse move events.
-			return;
-		}
-		
-		mLastMouseX = x;
-		mLastMouseY = y;
-	}
-	
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
-	std::string temp;
-	switch(type)
-	{
-		case MOUSE_EVENT_DOWN:			temp = "down";			break;
-		case MOUSE_EVENT_UP:			temp = "up";			break;
-		case MOUSE_EVENT_MOVE:			temp = "move";			break;
-		case MOUSE_EVENT_DOUBLE_CLICK:	temp = "double_click";	break;
-	}
-	message.setValue("event", temp);
-
-	message.setValueS32("button", button);
-
-	message.setValueS32("x", x);
-	
-	// Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
-	if(!mRequestedTextureCoordsOpenGL)
-	{
-		// TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
-		y = mMediaHeight - y;
-	}
-	message.setValueS32("y", y);
-
-	message.setValue("modifiers", translateModifiers(modifiers));
-	
-	sendMessage(message);
-}
-
-bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
-{
-	bool result = true;
-	
-	// FIXME:
-	// HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
-	// For now, return false for the ones the webkit plugin won't handle properly.
-	
-	switch(key_code)
-	{
-		case KEY_BACKSPACE:		
-		case KEY_TAB:			
-		case KEY_RETURN:		
-		case KEY_PAD_RETURN:	
-		case KEY_SHIFT:			
-		case KEY_CONTROL:		
-		case KEY_ALT:			
-		case KEY_CAPSLOCK:		
-		case KEY_ESCAPE:		
-		case KEY_PAGE_UP:		
-		case KEY_PAGE_DOWN:		
-		case KEY_END:			
-		case KEY_HOME:			
-		case KEY_LEFT:			
-		case KEY_UP:			
-		case KEY_RIGHT:			
-		case KEY_DOWN:			
-		case KEY_INSERT:		
-		case KEY_DELETE:
-			// These will be handled		
-		break;
-		
-		default:
-			// regular ASCII characters will also be handled
-			if(key_code >= KEY_SPECIAL)
-			{
-				// Other "special" codes will not work properly.
-				result = false;
-			}
-		break;
-	}
-
-#if LL_DARWIN	
-	if(modifiers & MASK_ALT)
-	{
-		// Option-key modified characters should be handled by the unicode input path instead of this one.
-		result = false;
-	}
-#endif
-
-	if(result)
-	{
-		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
-		std::string temp;
-		switch(type)
-		{
-			case KEY_EVENT_DOWN:			temp = "down";			break;
-			case KEY_EVENT_UP:				temp = "up";			break;
-			case KEY_EVENT_REPEAT:			temp = "repeat";		break;
-		}
-		message.setValue("event", temp);
-		
-		message.setValueS32("key", key_code);
-
-		message.setValue("modifiers", translateModifiers(modifiers));
-		message.setValueLLSD("native_key_data", native_key_data);
-		
-		sendMessage(message);
-	}
-		
-	return result;
-}
-
-void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
-
-	message.setValueS32("x", x);
-	message.setValueS32("y", y);
-	message.setValue("modifiers", translateModifiers(modifiers));
-	
-	sendMessage(message);
-}
-	
-bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
-
-	message.setValue("text", text);
-	message.setValue("modifiers", translateModifiers(modifiers));
-	message.setValueLLSD("native_key_data", native_key_data);
-	
-	sendMessage(message);
-	
-	return true;
-}
-
-void LLPluginClassMedia::loadURI(const std::string &uri)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
-
-	message.setValue("uri", uri);
-	
-	sendMessage(message);
-}
-
-const char* LLPluginClassMedia::priorityToString(EPriority priority)
-{
-	const char* result = "UNKNOWN";
-	switch(priority)
-	{
-		case PRIORITY_UNLOADED:		result = "unloaded";	break;
-		case PRIORITY_STOPPED:		result = "stopped";		break;
-		case PRIORITY_HIDDEN:		result = "hidden";		break;
-		case PRIORITY_SLIDESHOW:	result = "slideshow";	break;
-		case PRIORITY_LOW:			result = "low";			break;
-		case PRIORITY_NORMAL:		result = "normal";		break;
-		case PRIORITY_HIGH:			result = "high";		break;
-	}
-	
-	return result;
-}
-
-void LLPluginClassMedia::setPriority(EPriority priority)
-{
-	if(mPriority != priority)
-	{
-		mPriority = priority;
-
-		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
-		
-		std::string priority_string = priorityToString(priority);
-		switch(priority)
-		{
-			case PRIORITY_UNLOADED:	
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_STOPPED:	
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_HIDDEN:	
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_SLIDESHOW:
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_LOW:		
-				mSleepTime = 1.0f / 25.0f;
-			break;
-			case PRIORITY_NORMAL:	
-				mSleepTime = 1.0f / 50.0f;
-			break;
-			case PRIORITY_HIGH:		
-				mSleepTime = 1.0f / 100.0f;
-			break;
-		}
-		
-		message.setValue("priority", priority_string);
-
-		sendMessage(message);
-		
-		if(mPlugin)
-		{
-			mPlugin->setSleepTime(mSleepTime);
-		}
-		
-		LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
-		
-		// This may affect the calculated size, so recalculate it here.
-		setSizeInternal();
-	}
-}
-
-void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
-{
-	int power = nextPowerOf2(size);
-	if(mLowPrioritySizeLimit != power)
-	{
-		mLowPrioritySizeLimit = power;
-
-		// This may affect the calculated size, so recalculate it here.
-		setSizeInternal();
-	}
-}
-
-F64 LLPluginClassMedia::getCPUUsage()
-{
-	F64 result = 0.0f;
-	
-	if(mPlugin)
-	{
-		result = mPlugin->getCPUUsage();
-	}
-	
-	return result;
-}
-
-void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
-	message.setValue("file", file);
-	if(mPlugin && mPlugin->isBlocked())
-	{
-		// If the plugin sent a blocking pick-file request, the response should unblock it.
-		message.setValueBoolean("blocking_response", true);
-	}
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
-	message.setValueBoolean("ok", ok);
-	message.setValue("username", username);
-	message.setValue("password", password);
-	if(mPlugin && mPlugin->isBlocked())
-	{
-		// If the plugin sent a blocking pick-file request, the response should unblock it.
-		message.setValueBoolean("blocking_response", true);
-	}
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::cut()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::copy()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::paste()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
-	message.setValue("path", user_data_path);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
-	message.setValue("language", language_code);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
-	message.setValueBoolean("enable", enabled);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
-	message.setValueBoolean("enable", enabled);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setTarget(const std::string &target)
-{
-	mTarget = target;
-}
-
-/* virtual */ 
-void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
-{
-	std::string message_class = message.getClass();
-	
-	if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
-	{
-		std::string message_name = message.getName();
-		if(message_name == "texture_params")
-		{
-			mRequestedTextureDepth = message.getValueS32("depth");
-			mRequestedTextureInternalFormat = message.getValueU32("internalformat");
-			mRequestedTextureFormat = message.getValueU32("format");
-			mRequestedTextureType = message.getValueU32("type");
-			mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
-			mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");			
-			
-			// These two are optional, and will default to 0 if they're not specified.
-			mDefaultMediaWidth = message.getValueS32("default_width");
-			mDefaultMediaHeight = message.getValueS32("default_height");
-			
-			mAllowDownsample = message.getValueBoolean("allow_downsample");
-			mPadding = message.getValueS32("padding");
-
-			setSizeInternal();
-			
-			mTextureParamsReceived = true;
-		}
-		else if(message_name == "updated")
-		{			
-			if(message.hasValue("left"))
-			{
-				LLRect newDirtyRect;
-				newDirtyRect.mLeft = message.getValueS32("left");
-				newDirtyRect.mTop = message.getValueS32("top");
-				newDirtyRect.mRight = message.getValueS32("right");
-				newDirtyRect.mBottom = message.getValueS32("bottom");
-							
-				// The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
-				// If they're backwards, swap them.
-				if(newDirtyRect.mTop < newDirtyRect.mBottom)
-				{
-					S32 temp = newDirtyRect.mTop;
-					newDirtyRect.mTop = newDirtyRect.mBottom;
-					newDirtyRect.mBottom = temp;
-				}
-				
-				if(mDirtyRect.isEmpty())
-				{
-					mDirtyRect = newDirtyRect;
-				}
-				else
-				{
-					mDirtyRect.unionWith(newDirtyRect);
-				}
-
-				LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" 
-					<< newDirtyRect.mLeft << ", "
-					<< newDirtyRect.mTop << ", "
-					<< newDirtyRect.mRight << ", "
-					<< newDirtyRect.mBottom << "), new dirty rect is: ("
-					<< mDirtyRect.mLeft << ", "
-					<< mDirtyRect.mTop << ", "
-					<< mDirtyRect.mRight << ", "
-					<< mDirtyRect.mBottom << ")"
-					<< LL_ENDL;
-				
-				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
-			}			
-			
-
-			bool time_duration_updated = false;
-			int previous_percent = mProgressPercent;
-
-			if(message.hasValue("current_time"))
-			{
-				mCurrentTime = message.getValueReal("current_time");
-				time_duration_updated = true;
-			}
-			if(message.hasValue("duration"))
-			{
-				mDuration = message.getValueReal("duration");
-				time_duration_updated = true;
-			}
-
-			if(message.hasValue("current_rate"))
-			{
-				mCurrentRate = message.getValueReal("current_rate");
-			}
-			
-			if(message.hasValue("loaded_duration"))
-			{
-				mLoadedDuration = message.getValueReal("loaded_duration");
-				time_duration_updated = true;
-			}
-			else
-			{
-				// If the message doesn't contain a loaded_duration param, assume it's equal to duration
-				mLoadedDuration = mDuration;
-			}
-			
-			// Calculate a percentage based on the loaded duration and total duration.
-			if(mDuration != 0.0f)	// Don't divide by zero.
-			{
-				mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
-			}
-
-			if(time_duration_updated)
-			{
-				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
-			}
-			
-			if(previous_percent != mProgressPercent)
-			{
-				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
-			}
-		}
-		else if(message_name == "media_status")
-		{
-			std::string status = message.getValue("status");
-			
-			LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
-			
-			if(status == "loading")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
-			}
-			else if(status == "loaded")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
-			}
-			else if(status == "error")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
-			}
-			else if(status == "playing")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
-			}
-			else if(status == "paused")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
-			}
-			else if(status == "done")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
-			}
-			else
-			{
-				// empty string or any unknown string
-				mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
-			}
-		}
-		else if(message_name == "size_change_request")
-		{
-			S32 width = message.getValueS32("width");
-			S32 height = message.getValueS32("height");
-			std::string name = message.getValue("name");
-
-			// TODO: check that name matches?
-			mNaturalMediaWidth = width;
-			mNaturalMediaHeight = height;
-			
-			setSizeInternal();
-		}
-		else if(message_name == "size_change_response")
-		{
-			std::string name = message.getValue("name");
-			
-			// TODO: check that name matches?
-			
-			mTextureWidth = message.getValueS32("texture_width");
-			mTextureHeight = message.getValueS32("texture_height");
-			mMediaWidth = message.getValueS32("width");
-			mMediaHeight = message.getValueS32("height");
-			
-			// This invalidates any existing dirty rect.
-			resetDirty();
-			
-			// TODO: should we verify that the plugin sent back the right values?  
-			// Two size changes in a row may cause them to not match, due to queueing, etc.
-
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
-		}
-		else if(message_name == "cursor_changed")
-		{
-			mCursorName = message.getValue("name");
-
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
-		}
-		else if(message_name == "edit_state")
-		{
-			if(message.hasValue("cut"))
-			{
-				mCanCut = message.getValueBoolean("cut");
-			}
-			if(message.hasValue("copy"))
-			{
-				mCanCopy = message.getValueBoolean("copy");
-			}
-			if(message.hasValue("paste"))
-			{
-				mCanPaste = message.getValueBoolean("paste");
-			}
-		}
-		else if(message_name == "name_text")
-		{
-			mMediaName = message.getValue("name");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
-		}
-		else if(message_name == "pick_file")
-		{
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
-		}
-		else if(message_name == "auth_request")
-		{
-			mAuthURL = message.getValue("url");
-			mAuthRealm = message.getValue("realm");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
-		}
-		else
-		{
-			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
-		}
-	}
-	else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
-	{
-		std::string message_name = message.getName();
-		if(message_name == "navigate_begin")
-		{
-			mNavigateURI = message.getValue("uri");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
-		}
-		else if(message_name == "navigate_complete")
-		{
-			mNavigateURI = message.getValue("uri");
-			mNavigateResultCode = message.getValueS32("result_code");
-			mNavigateResultString = message.getValue("result_string");
-			mHistoryBackAvailable = message.getValueBoolean("history_back_available");
-			mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
-			
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
-		}
-		else if(message_name == "progress")
-		{
-			mProgressPercent = message.getValueS32("percent");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
-		}
-		else if(message_name == "status_text")
-		{
-			mStatusText = message.getValue("status");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
-		}
-		else if(message_name == "location_changed")
-		{
-			mLocation = message.getValue("uri");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
-		}
-		else if(message_name == "click_href")
-		{
-			mClickURL = message.getValue("uri");
-			mClickTarget = message.getValue("target");
-			mClickUUID = message.getValue("uuid");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
-		}
-		else if(message_name == "click_nofollow")
-		{
-			mClickURL = message.getValue("uri");
-			mClickNavType = message.getValue("nav_type");
-			mClickTarget.clear();
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
-		}
-		else if(message_name == "navigate_error_page")
-		{
-			mStatusCode = message.getValueS32("status_code");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
-		}
-		else if(message_name == "cookie_set")
-		{
-			if(mOwner)
-			{
-				mOwner->handleCookieSet(this, message.getValue("cookie"));
-			}
-		}
-		else if(message_name == "close_request")
-		{
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
-		}
-		else if(message_name == "geometry_change")
-		{
-			mClickUUID = message.getValue("uuid");
-			mGeometryX = message.getValueS32("x");
-			mGeometryY = message.getValueS32("y");
-			mGeometryWidth = message.getValueS32("width");
-			mGeometryHeight = message.getValueS32("height");
-				
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
-		}
-		else if(message_name == "link_hovered")
-		{
-			// text is not currently used -- the tooltip hover text is taken from the "title".
-			mHoverLink = message.getValue("link");
-			mHoverText = message.getValue("title");
-			// message.getValue("text");
-				
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
-		}
-		else
-		{
-			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
-		}
-	}
-	else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
-	{
-		std::string message_name = message.getName();
-
-		// This class hasn't defined any incoming messages yet.
-//		if(message_name == "message_name")
-//		{
-//		}
-//		else 
-		{
-			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
-		}
-	}
-
-}
-
-/* virtual */ 
-void LLPluginClassMedia::pluginLaunchFailed()
-{
-	mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
-}
-
-/* virtual */ 
-void LLPluginClassMedia::pluginDied()
-{
-	mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
-}
-
-void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
-{
-	if(mOwner)
-	{
-		mOwner->handleMediaEvent(this, event);
-	}
-}
-
-void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
-{
-	if(mPlugin && mPlugin->isRunning())
-	{
-		mPlugin->sendMessage(message);
-	}
-	else
-	{
-		// The plugin isn't set up yet -- queue this message to be sent after initialization.
-		mSendQueue.push(message);
-	}
-}
-
-////////////////////////////////////////////////////////////
-// MARK: media_browser class functions
-bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
-{
-	std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
-	return !version.empty();
-}
-
-void LLPluginClassMedia::focus(bool focused)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
-
-	message.setValueBoolean("focused", focused);
-	
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cache()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cookies()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::set_cookies(const std::string &cookies)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
-	message.setValue("cookies", cookies);	
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::enable_cookies(bool enable)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
-	message.setValueBoolean("enable", enable);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
-
-	message.setValueBoolean("enable", enable);
-	message.setValue("host", host);
-	message.setValueS32("port", port);
-
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_stop()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_reload(bool ignore_cache)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
-
-	message.setValueBoolean("ignore_cache", ignore_cache);
-	
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_forward()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_back()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
-
-	message.setValue("user_agent", user_agent);
-
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
-
-	message.setValue("target", target);
-	message.setValue("uuid", uuid);
-
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
-
-	message.setValue("uuid", uuid);
-
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
-	message.setValueBoolean("ignore", ignore);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
-	message.setValue("path", path);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::crashPlugin()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
-
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::hangPlugin()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
-
-	sendMessage(message);
-}
-
-
-////////////////////////////////////////////////////////////
-// MARK: media_time class functions
-bool LLPluginClassMedia::pluginSupportsMediaTime(void)
-{
-	std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
-	return !version.empty();
-}
-
-void LLPluginClassMedia::stop()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::start(float rate)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
-
-	message.setValueReal("rate", rate);
-
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::pause()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::seek(float time)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
-
-	message.setValueReal("time", time);
-	
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setLoop(bool loop)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
-
-	message.setValueBoolean("loop", loop);
-
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setVolume(float volume)
-{
-	if(volume != mRequestedVolume)
-	{
-		mRequestedVolume = volume;
-		
-		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
-
-		message.setValueReal("volume", volume);
-		
-		sendMessage(message);
-	}
-}
-
-float LLPluginClassMedia::getVolume()
-{
-	return mRequestedVolume;
-}
-
-void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
-{
-	// Send URL history to plugin
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
-	message.setValueLLSD("history", url_history);
-	sendMessage(message);
-
-	LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
-}
-
+/** 
+ * @file llpluginclassmedia.cpp
+ * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&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$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include "indra_constants.h"
+
+#include "llpluginclassmedia.h"
+#include "llpluginmessageclasses.h"
+
+#include "llqtwebkit.h"
+
+static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
+
+static int nextPowerOf2( int value )
+{
+	int next_power_of_2 = 1;
+	while ( next_power_of_2 < value )
+	{
+		next_power_of_2 <<= 1;
+	}
+	
+	return next_power_of_2;
+}
+
+LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
+{
+	mOwner = owner;
+	mPlugin = NULL;
+	reset();
+
+	//debug use
+	mDeleteOK = true ;
+}
+
+
+LLPluginClassMedia::~LLPluginClassMedia()
+{
+	llassert_always(mDeleteOK) ;
+	reset();
+}
+
+bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
+{	
+	LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+	LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
+	LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
+	
+	mPlugin = new LLPluginProcessParent(this);
+	mPlugin->setSleepTime(mSleepTime);
+	
+	// Queue up the media init message -- it will be sent after all the currently queued messages.
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
+	message.setValue("target", mTarget);
+	sendMessage(message);
+	
+	mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
+
+	return true;
+}
+
+
+void LLPluginClassMedia::reset()
+{
+	if(mPlugin != NULL)
+	{
+		delete mPlugin;
+		mPlugin = NULL;
+	}
+
+	mTextureParamsReceived = false;
+	mRequestedTextureDepth = 0;
+	mRequestedTextureInternalFormat = 0;
+	mRequestedTextureFormat = 0;
+	mRequestedTextureType = 0;
+	mRequestedTextureSwapBytes = false;
+	mRequestedTextureCoordsOpenGL = false;
+	mTextureSharedMemorySize = 0;
+	mTextureSharedMemoryName.clear();
+	mDefaultMediaWidth = 0;
+	mDefaultMediaHeight = 0;
+	mNaturalMediaWidth = 0;
+	mNaturalMediaHeight = 0;
+	mSetMediaWidth = -1;
+	mSetMediaHeight = -1;
+	mRequestedMediaWidth = 0;
+	mRequestedMediaHeight = 0;
+	mRequestedTextureWidth = 0;
+	mRequestedTextureHeight = 0;
+	mFullMediaWidth = 0;
+	mFullMediaHeight = 0;
+	mTextureWidth = 0;
+	mTextureHeight = 0;
+	mMediaWidth = 0;
+	mMediaHeight = 0;
+	mDirtyRect = LLRect::null;	
+	mAutoScaleMedia = false;
+	mRequestedVolume = 1.0f;
+	mPriority = PRIORITY_NORMAL;
+	mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
+	mAllowDownsample = false;
+	mPadding = 0;
+	mLastMouseX = 0;
+	mLastMouseY = 0;
+	mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+	mSleepTime = 1.0f / 100.0f;
+	mCanCut = false;
+	mCanCopy = false;
+	mCanPaste = false;
+	mMediaName.clear();
+	mMediaDescription.clear();
+	mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
+	
+	// media_browser class
+	mNavigateURI.clear();
+	mNavigateResultCode = -1;
+	mNavigateResultString.clear();
+	mHistoryBackAvailable = false;
+	mHistoryForwardAvailable = false;
+	mStatusText.clear();
+	mProgressPercent = 0;	
+	mClickURL.clear();
+	mClickNavType.clear();
+	mClickTarget.clear();
+	mClickUUID.clear();
+	mStatusCode = 0;
+	
+	// media_time class
+	mCurrentTime = 0.0f;
+	mDuration = 0.0f;
+	mCurrentRate = 0.0f;
+	mLoadedDuration = 0.0f;
+}
+
+void LLPluginClassMedia::idle(void)
+{
+	if(mPlugin)
+	{
+		mPlugin->idle();
+	}
+	
+	if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
+	{
+		// Can't process a size change at this time
+	}
+	else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
+	{
+		// Calculate the correct size for the media texture
+		mRequestedTextureHeight = mRequestedMediaHeight;
+		if(mPadding < 0)
+		{
+			// negative values indicate the plugin wants a power of 2
+			mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
+		}
+		else
+		{
+			mRequestedTextureWidth = mRequestedMediaWidth;
+			
+			if(mPadding > 1)
+			{
+				// Pad up to a multiple of the specified number of bytes per row
+				int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
+				int pad = rowbytes % mPadding;
+				if(pad != 0)
+				{
+					rowbytes += mPadding - pad;
+				}
+				
+				if(rowbytes % mRequestedTextureDepth == 0)
+				{
+					mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
+				}
+				else
+				{
+					LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
+				}
+			}
+		}
+
+		
+		// Size change has been requested but not initiated yet.
+		size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
+
+		// Add an extra line for padding, just in case.
+		newsize += mRequestedTextureWidth * mRequestedTextureDepth;
+
+		if(newsize != mTextureSharedMemorySize)
+		{
+			if(!mTextureSharedMemoryName.empty())
+			{
+				// Tell the plugin to remove the old memory segment
+				mPlugin->removeSharedMemory(mTextureSharedMemoryName);
+				mTextureSharedMemoryName.clear();
+			}
+			
+			mTextureSharedMemorySize = newsize;
+			mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
+			if(!mTextureSharedMemoryName.empty())
+			{
+				void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+				
+				// clear texture memory to avoid random screen visual fuzz from uninitialized texture data
+				memset( addr, 0x00, newsize );
+				
+				// We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
+				// so it may not be worthwhile.
+				// mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
+			}
+		}
+		
+		// This is our local indicator that a change is in progress.
+		mTextureWidth = -1;
+		mTextureHeight = -1;
+		mMediaWidth = -1;
+		mMediaHeight = -1;
+
+		// This invalidates any existing dirty rect.
+		resetDirty();
+		
+		// Send a size change message to the plugin
+		{
+			LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
+			message.setValue("name", mTextureSharedMemoryName);
+			message.setValueS32("width", mRequestedMediaWidth);
+			message.setValueS32("height", mRequestedMediaHeight);
+			message.setValueS32("texture_width", mRequestedTextureWidth);
+			message.setValueS32("texture_height", mRequestedTextureHeight);
+			message.setValueReal("background_r", mBackgroundColor.mV[VX]);
+			message.setValueReal("background_g", mBackgroundColor.mV[VY]);
+			message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
+			message.setValueReal("background_a", mBackgroundColor.mV[VW]);
+			mPlugin->sendMessage(message);	// DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
+			
+			LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
+		}
+	}
+	
+	if(mPlugin && mPlugin->isRunning())
+	{
+		// Send queued messages
+		while(!mSendQueue.empty())
+		{
+			LLPluginMessage message = mSendQueue.front();
+			mSendQueue.pop();
+			mPlugin->sendMessage(message);
+		}
+	}
+}
+
+int LLPluginClassMedia::getTextureWidth() const
+{
+	return nextPowerOf2(mTextureWidth);
+}
+
+int LLPluginClassMedia::getTextureHeight() const
+{
+	return nextPowerOf2(mTextureHeight);
+}
+
+unsigned char* LLPluginClassMedia::getBitsData()
+{
+	unsigned char *result = NULL;
+	if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
+	{
+		result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+	}
+	return result;
+}
+
+void LLPluginClassMedia::setSize(int width, int height)
+{
+	if((width > 0) && (height > 0))
+	{
+		mSetMediaWidth = width;
+		mSetMediaHeight = height;
+	}
+	else
+	{
+		mSetMediaWidth = -1;
+		mSetMediaHeight = -1;
+	}
+
+	setSizeInternal();
+}
+
+void LLPluginClassMedia::setSizeInternal(void)
+{
+	if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
+	{
+		mRequestedMediaWidth = mSetMediaWidth;
+		mRequestedMediaHeight = mSetMediaHeight;
+	}
+	else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
+	{
+		mRequestedMediaWidth = mNaturalMediaWidth;
+		mRequestedMediaHeight = mNaturalMediaHeight;
+	}
+	else
+	{
+		mRequestedMediaWidth = mDefaultMediaWidth;
+		mRequestedMediaHeight = mDefaultMediaHeight;
+	}
+	
+	// Save these for size/interest calculations
+	mFullMediaWidth = mRequestedMediaWidth;
+	mFullMediaHeight = mRequestedMediaHeight;
+	
+	if(mAllowDownsample)
+	{
+		switch(mPriority)
+		{
+			case PRIORITY_SLIDESHOW:
+			case PRIORITY_LOW:
+				// Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
+				while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
+				{
+					mRequestedMediaWidth /= 2;
+					mRequestedMediaHeight /= 2;
+				}
+			break;
+			
+			default:
+				// Don't adjust texture size
+			break;
+		}
+	}
+	
+	if(mAutoScaleMedia)
+	{
+		mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
+		mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
+	}
+	
+	if(mRequestedMediaWidth > 2048)
+		mRequestedMediaWidth = 2048;
+
+	if(mRequestedMediaHeight > 2048)
+		mRequestedMediaHeight = 2048;
+}
+
+void LLPluginClassMedia::setAutoScale(bool auto_scale)
+{
+	if(auto_scale != mAutoScaleMedia)
+	{
+		mAutoScaleMedia = auto_scale;
+		setSizeInternal();
+	}
+}
+
+bool LLPluginClassMedia::textureValid(void)
+{
+	if(
+		!mTextureParamsReceived ||
+		mTextureWidth <= 0 ||
+		mTextureHeight <= 0 ||
+		mMediaWidth <= 0 ||
+		mMediaHeight <= 0 ||
+		mRequestedMediaWidth != mMediaWidth ||
+		mRequestedMediaHeight != mMediaHeight ||
+		getBitsData() == NULL
+	)	
+		return false;
+	
+	return true;
+}
+
+bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
+{
+	bool result = !mDirtyRect.isEmpty();
+
+	if(dirty_rect != NULL)
+	{
+		*dirty_rect = mDirtyRect;
+	}
+
+	return result;
+}
+
+void LLPluginClassMedia::resetDirty(void)
+{
+	mDirtyRect = LLRect::null;
+}
+
+std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
+{
+	std::string result;
+	
+	
+	if(modifiers & MASK_CONTROL)
+	{
+		result += "control|";
+	}
+
+	if(modifiers & MASK_ALT)
+	{
+		result += "alt|";
+	}
+
+	if(modifiers & MASK_SHIFT)
+	{
+		result += "shift|";
+	}
+
+	// TODO: should I deal with platform differences here or in callers?
+	// TODO: how do we deal with the Mac "command" key?
+/*
+	if(modifiers & MASK_SOMETHING)
+	{
+		result += "meta|";
+	}
+*/	
+	return result;
+}
+
+void LLPluginClassMedia::jsEnableObject( bool enable )
+{
+	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+	{
+		return;
+	}
+
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
+	message.setValueBoolean( "enable", enable );
+	sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
+{
+	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+	{
+		return;
+	}
+
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
+	message.setValueReal( "x", x );
+	message.setValueReal( "y", y );
+	message.setValueReal( "z", z );
+	sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
+{
+	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+	{
+		return;
+	}
+
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
+	message.setValueReal( "x", x );
+	message.setValueReal( "y", y );
+	message.setValueReal( "z", z );
+	sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
+{
+	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+	{
+		return;
+	}
+
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
+	message.setValueReal( "angle", angle );
+
+	sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
+{
+	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+	{
+		return;
+	}
+
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
+	message.setValue( "language", language );
+	sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
+{
+	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+	{
+		return;
+	}
+
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
+	message.setValue( "region", region );
+	sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
+{
+	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+	{
+		return;
+	}
+
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
+	message.setValue( "maturity", maturity );
+	sendMessage( message );
+}
+
+void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
+{
+	if(type == MOUSE_EVENT_MOVE)
+	{
+		if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
+		{
+			// Don't queue up mouse move events that can't be delivered.
+			return;
+		}
+
+		if((x == mLastMouseX) && (y == mLastMouseY))
+		{
+			// Don't spam unnecessary mouse move events.
+			return;
+		}
+		
+		mLastMouseX = x;
+		mLastMouseY = y;
+	}
+	
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
+	std::string temp;
+	switch(type)
+	{
+		case MOUSE_EVENT_DOWN:			temp = "down";			break;
+		case MOUSE_EVENT_UP:			temp = "up";			break;
+		case MOUSE_EVENT_MOVE:			temp = "move";			break;
+		case MOUSE_EVENT_DOUBLE_CLICK:	temp = "double_click";	break;
+	}
+	message.setValue("event", temp);
+
+	message.setValueS32("button", button);
+
+	message.setValueS32("x", x);
+	
+	// Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
+	if(!mRequestedTextureCoordsOpenGL)
+	{
+		// TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
+		y = mMediaHeight - y;
+	}
+	message.setValueS32("y", y);
+
+	message.setValue("modifiers", translateModifiers(modifiers));
+	
+	sendMessage(message);
+}
+
+bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
+{
+	bool result = true;
+	
+	// FIXME:
+	// HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
+	// For now, return false for the ones the webkit plugin won't handle properly.
+	
+	switch(key_code)
+	{
+		case KEY_BACKSPACE:		
+		case KEY_TAB:			
+		case KEY_RETURN:		
+		case KEY_PAD_RETURN:	
+		case KEY_SHIFT:			
+		case KEY_CONTROL:		
+		case KEY_ALT:			
+		case KEY_CAPSLOCK:		
+		case KEY_ESCAPE:		
+		case KEY_PAGE_UP:		
+		case KEY_PAGE_DOWN:		
+		case KEY_END:			
+		case KEY_HOME:			
+		case KEY_LEFT:			
+		case KEY_UP:			
+		case KEY_RIGHT:			
+		case KEY_DOWN:			
+		case KEY_INSERT:		
+		case KEY_DELETE:
+			// These will be handled		
+		break;
+		
+		default:
+			// regular ASCII characters will also be handled
+			if(key_code >= KEY_SPECIAL)
+			{
+				// Other "special" codes will not work properly.
+				result = false;
+			}
+		break;
+	}
+
+#if LL_DARWIN	
+	if(modifiers & MASK_ALT)
+	{
+		// Option-key modified characters should be handled by the unicode input path instead of this one.
+		result = false;
+	}
+#endif
+
+	if(result)
+	{
+		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
+		std::string temp;
+		switch(type)
+		{
+			case KEY_EVENT_DOWN:			temp = "down";			break;
+			case KEY_EVENT_UP:				temp = "up";			break;
+			case KEY_EVENT_REPEAT:			temp = "repeat";		break;
+		}
+		message.setValue("event", temp);
+		
+		message.setValueS32("key", key_code);
+
+		message.setValue("modifiers", translateModifiers(modifiers));
+		message.setValueLLSD("native_key_data", native_key_data);
+		
+		sendMessage(message);
+	}
+		
+	return result;
+}
+
+void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
+
+	message.setValueS32("x", x);
+	message.setValueS32("y", y);
+	message.setValue("modifiers", translateModifiers(modifiers));
+	
+	sendMessage(message);
+}
+	
+bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
+
+	message.setValue("text", text);
+	message.setValue("modifiers", translateModifiers(modifiers));
+	message.setValueLLSD("native_key_data", native_key_data);
+	
+	sendMessage(message);
+	
+	return true;
+}
+
+void LLPluginClassMedia::loadURI(const std::string &uri)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
+
+	message.setValue("uri", uri);
+	
+	sendMessage(message);
+}
+
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+	const char* result = "UNKNOWN";
+	switch(priority)
+	{
+		case PRIORITY_UNLOADED:		result = "unloaded";	break;
+		case PRIORITY_STOPPED:		result = "stopped";		break;
+		case PRIORITY_HIDDEN:		result = "hidden";		break;
+		case PRIORITY_SLIDESHOW:	result = "slideshow";	break;
+		case PRIORITY_LOW:			result = "low";			break;
+		case PRIORITY_NORMAL:		result = "normal";		break;
+		case PRIORITY_HIGH:			result = "high";		break;
+	}
+	
+	return result;
+}
+
+void LLPluginClassMedia::setPriority(EPriority priority)
+{
+	if(mPriority != priority)
+	{
+		mPriority = priority;
+
+		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
+		
+		std::string priority_string = priorityToString(priority);
+		switch(priority)
+		{
+			case PRIORITY_UNLOADED:	
+				mSleepTime = 1.0f;
+			break;
+			case PRIORITY_STOPPED:	
+				mSleepTime = 1.0f;
+			break;
+			case PRIORITY_HIDDEN:	
+				mSleepTime = 1.0f;
+			break;
+			case PRIORITY_SLIDESHOW:
+				mSleepTime = 1.0f;
+			break;
+			case PRIORITY_LOW:		
+				mSleepTime = 1.0f / 25.0f;
+			break;
+			case PRIORITY_NORMAL:	
+				mSleepTime = 1.0f / 50.0f;
+			break;
+			case PRIORITY_HIGH:		
+				mSleepTime = 1.0f / 100.0f;
+			break;
+		}
+		
+		message.setValue("priority", priority_string);
+
+		sendMessage(message);
+		
+		if(mPlugin)
+		{
+			mPlugin->setSleepTime(mSleepTime);
+		}
+		
+		LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
+		
+		// This may affect the calculated size, so recalculate it here.
+		setSizeInternal();
+	}
+}
+
+void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
+{
+	int power = nextPowerOf2(size);
+	if(mLowPrioritySizeLimit != power)
+	{
+		mLowPrioritySizeLimit = power;
+
+		// This may affect the calculated size, so recalculate it here.
+		setSizeInternal();
+	}
+}
+
+F64 LLPluginClassMedia::getCPUUsage()
+{
+	F64 result = 0.0f;
+	
+	if(mPlugin)
+	{
+		result = mPlugin->getCPUUsage();
+	}
+	
+	return result;
+}
+
+void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
+	message.setValue("file", file);
+	if(mPlugin && mPlugin->isBlocked())
+	{
+		// If the plugin sent a blocking pick-file request, the response should unblock it.
+		message.setValueBoolean("blocking_response", true);
+	}
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
+	message.setValueBoolean("ok", ok);
+	message.setValue("username", username);
+	message.setValue("password", password);
+	if(mPlugin && mPlugin->isBlocked())
+	{
+		// If the plugin sent a blocking pick-file request, the response should unblock it.
+		message.setValueBoolean("blocking_response", true);
+	}
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::cut()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::copy()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::paste()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
+	message.setValue("path", user_data_path);
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
+	message.setValue("language", language_code);
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
+	message.setValueBoolean("enable", enabled);
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
+	message.setValueBoolean("enable", enabled);
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setTarget(const std::string &target)
+{
+	mTarget = target;
+}
+
+/* virtual */ 
+void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
+{
+	std::string message_class = message.getClass();
+	
+	if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+	{
+		std::string message_name = message.getName();
+		if(message_name == "texture_params")
+		{
+			mRequestedTextureDepth = message.getValueS32("depth");
+			mRequestedTextureInternalFormat = message.getValueU32("internalformat");
+			mRequestedTextureFormat = message.getValueU32("format");
+			mRequestedTextureType = message.getValueU32("type");
+			mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
+			mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");			
+			
+			// These two are optional, and will default to 0 if they're not specified.
+			mDefaultMediaWidth = message.getValueS32("default_width");
+			mDefaultMediaHeight = message.getValueS32("default_height");
+			
+			mAllowDownsample = message.getValueBoolean("allow_downsample");
+			mPadding = message.getValueS32("padding");
+
+			setSizeInternal();
+			
+			mTextureParamsReceived = true;
+		}
+		else if(message_name == "updated")
+		{			
+			if(message.hasValue("left"))
+			{
+				LLRect newDirtyRect;
+				newDirtyRect.mLeft = message.getValueS32("left");
+				newDirtyRect.mTop = message.getValueS32("top");
+				newDirtyRect.mRight = message.getValueS32("right");
+				newDirtyRect.mBottom = message.getValueS32("bottom");
+							
+				// The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
+				// If they're backwards, swap them.
+				if(newDirtyRect.mTop < newDirtyRect.mBottom)
+				{
+					S32 temp = newDirtyRect.mTop;
+					newDirtyRect.mTop = newDirtyRect.mBottom;
+					newDirtyRect.mBottom = temp;
+				}
+				
+				if(mDirtyRect.isEmpty())
+				{
+					mDirtyRect = newDirtyRect;
+				}
+				else
+				{
+					mDirtyRect.unionWith(newDirtyRect);
+				}
+
+				LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" 
+					<< newDirtyRect.mLeft << ", "
+					<< newDirtyRect.mTop << ", "
+					<< newDirtyRect.mRight << ", "
+					<< newDirtyRect.mBottom << "), new dirty rect is: ("
+					<< mDirtyRect.mLeft << ", "
+					<< mDirtyRect.mTop << ", "
+					<< mDirtyRect.mRight << ", "
+					<< mDirtyRect.mBottom << ")"
+					<< LL_ENDL;
+				
+				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
+			}			
+			
+
+			bool time_duration_updated = false;
+			int previous_percent = mProgressPercent;
+
+			if(message.hasValue("current_time"))
+			{
+				mCurrentTime = message.getValueReal("current_time");
+				time_duration_updated = true;
+			}
+			if(message.hasValue("duration"))
+			{
+				mDuration = message.getValueReal("duration");
+				time_duration_updated = true;
+			}
+
+			if(message.hasValue("current_rate"))
+			{
+				mCurrentRate = message.getValueReal("current_rate");
+			}
+			
+			if(message.hasValue("loaded_duration"))
+			{
+				mLoadedDuration = message.getValueReal("loaded_duration");
+				time_duration_updated = true;
+			}
+			else
+			{
+				// If the message doesn't contain a loaded_duration param, assume it's equal to duration
+				mLoadedDuration = mDuration;
+			}
+			
+			// Calculate a percentage based on the loaded duration and total duration.
+			if(mDuration != 0.0f)	// Don't divide by zero.
+			{
+				mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+			}
+
+			if(time_duration_updated)
+			{
+				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
+			}
+			
+			if(previous_percent != mProgressPercent)
+			{
+				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+			}
+		}
+		else if(message_name == "media_status")
+		{
+			std::string status = message.getValue("status");
+			
+			LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
+			
+			if(status == "loading")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
+			}
+			else if(status == "loaded")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
+			}
+			else if(status == "error")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
+			}
+			else if(status == "playing")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
+			}
+			else if(status == "paused")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
+			}
+			else if(status == "done")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+			}
+			else
+			{
+				// empty string or any unknown string
+				mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+			}
+		}
+		else if(message_name == "size_change_request")
+		{
+			S32 width = message.getValueS32("width");
+			S32 height = message.getValueS32("height");
+			std::string name = message.getValue("name");
+
+			// TODO: check that name matches?
+			mNaturalMediaWidth = width;
+			mNaturalMediaHeight = height;
+			
+			setSizeInternal();
+		}
+		else if(message_name == "size_change_response")
+		{
+			std::string name = message.getValue("name");
+			
+			// TODO: check that name matches?
+			
+			mTextureWidth = message.getValueS32("texture_width");
+			mTextureHeight = message.getValueS32("texture_height");
+			mMediaWidth = message.getValueS32("width");
+			mMediaHeight = message.getValueS32("height");
+			
+			// This invalidates any existing dirty rect.
+			resetDirty();
+			
+			// TODO: should we verify that the plugin sent back the right values?  
+			// Two size changes in a row may cause them to not match, due to queueing, etc.
+
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
+		}
+		else if(message_name == "cursor_changed")
+		{
+			mCursorName = message.getValue("name");
+
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
+		}
+		else if(message_name == "edit_state")
+		{
+			if(message.hasValue("cut"))
+			{
+				mCanCut = message.getValueBoolean("cut");
+			}
+			if(message.hasValue("copy"))
+			{
+				mCanCopy = message.getValueBoolean("copy");
+			}
+			if(message.hasValue("paste"))
+			{
+				mCanPaste = message.getValueBoolean("paste");
+			}
+		}
+		else if(message_name == "name_text")
+		{
+			mMediaName = message.getValue("name");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+		}
+		else if(message_name == "pick_file")
+		{
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
+		}
+		else if(message_name == "auth_request")
+		{
+			mAuthURL = message.getValue("url");
+			mAuthRealm = message.getValue("realm");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
+		}
+		else
+		{
+			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+		}
+	}
+	else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+	{
+		std::string message_name = message.getName();
+		if(message_name == "navigate_begin")
+		{
+			mNavigateURI = message.getValue("uri");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
+		}
+		else if(message_name == "navigate_complete")
+		{
+			mNavigateURI = message.getValue("uri");
+			mNavigateResultCode = message.getValueS32("result_code");
+			mNavigateResultString = message.getValue("result_string");
+			mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+			mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+			
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
+		}
+		else if(message_name == "progress")
+		{
+			mProgressPercent = message.getValueS32("percent");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+		}
+		else if(message_name == "status_text")
+		{
+			mStatusText = message.getValue("status");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
+		}
+		else if(message_name == "location_changed")
+		{
+			mLocation = message.getValue("uri");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
+		}
+		else if(message_name == "click_href")
+		{
+			mClickURL = message.getValue("uri");
+			mClickTarget = message.getValue("target");
+			mClickUUID = message.getValue("uuid");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
+		}
+		else if(message_name == "click_nofollow")
+		{
+			mClickURL = message.getValue("uri");
+			mClickNavType = message.getValue("nav_type");
+			mClickTarget.clear();
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
+		}
+		else if(message_name == "navigate_error_page")
+		{
+			mStatusCode = message.getValueS32("status_code");
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
+		}
+		else if(message_name == "cookie_set")
+		{
+			if(mOwner)
+			{
+				mOwner->handleCookieSet(this, message.getValue("cookie"));
+			}
+		}
+		else if(message_name == "close_request")
+		{
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
+		}
+		else if(message_name == "geometry_change")
+		{
+			mClickUUID = message.getValue("uuid");
+			mGeometryX = message.getValueS32("x");
+			mGeometryY = message.getValueS32("y");
+			mGeometryWidth = message.getValueS32("width");
+			mGeometryHeight = message.getValueS32("height");
+				
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
+		}
+		else if(message_name == "link_hovered")
+		{
+			// text is not currently used -- the tooltip hover text is taken from the "title".
+			mHoverLink = message.getValue("link");
+			mHoverText = message.getValue("title");
+			// message.getValue("text");
+				
+			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
+		}
+		else
+		{
+			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+		}
+	}
+	else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+	{
+		std::string message_name = message.getName();
+
+		// This class hasn't defined any incoming messages yet.
+//		if(message_name == "message_name")
+//		{
+//		}
+//		else 
+		{
+			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+		}
+	}
+
+}
+
+/* virtual */ 
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+	mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */ 
+void LLPluginClassMedia::pluginDied()
+{
+	mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
+}
+
+void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
+{
+	if(mOwner)
+	{
+		mOwner->handleMediaEvent(this, event);
+	}
+}
+
+void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
+{
+	if(mPlugin && mPlugin->isRunning())
+	{
+		mPlugin->sendMessage(message);
+	}
+	else
+	{
+		// The plugin isn't set up yet -- queue this message to be sent after initialization.
+		mSendQueue.push(message);
+	}
+}
+
+////////////////////////////////////////////////////////////
+// MARK: media_browser class functions
+bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
+{
+	std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
+	return !version.empty();
+}
+
+void LLPluginClassMedia::focus(bool focused)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
+
+	message.setValueBoolean("focused", focused);
+	
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cache()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cookies()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::set_cookies(const std::string &cookies)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
+	message.setValue("cookies", cookies);	
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::enable_cookies(bool enable)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
+	message.setValueBoolean("enable", enable);
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
+
+	message.setValueBoolean("enable", enable);
+	message.setValue("host", host);
+	message.setValueS32("port", port);
+
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_stop()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_reload(bool ignore_cache)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
+
+	message.setValueBoolean("ignore_cache", ignore_cache);
+	
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_forward()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_back()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
+
+	message.setValue("user_agent", user_agent);
+
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
+
+	message.setValue("target", target);
+	message.setValue("uuid", uuid);
+
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
+
+	message.setValue("uuid", uuid);
+
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
+	message.setValueBoolean("ignore", ignore);
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
+	message.setValue("path", path);
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::crashPlugin()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
+
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::hangPlugin()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
+
+	sendMessage(message);
+}
+
+
+////////////////////////////////////////////////////////////
+// MARK: media_time class functions
+bool LLPluginClassMedia::pluginSupportsMediaTime(void)
+{
+	std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
+	return !version.empty();
+}
+
+void LLPluginClassMedia::stop()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::start(float rate)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
+
+	message.setValueReal("rate", rate);
+
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::pause()
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::seek(float time)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
+
+	message.setValueReal("time", time);
+	
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setLoop(bool loop)
+{
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
+
+	message.setValueBoolean("loop", loop);
+
+	sendMessage(message);
+}
+
+void LLPluginClassMedia::setVolume(float volume)
+{
+	if(volume != mRequestedVolume)
+	{
+		mRequestedVolume = volume;
+		
+		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
+
+		message.setValueReal("volume", volume);
+		
+		sendMessage(message);
+	}
+}
+
+float LLPluginClassMedia::getVolume()
+{
+	return mRequestedVolume;
+}
+
+void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
+{
+	// Send URL history to plugin
+	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
+	message.setValueLLSD("history", url_history);
+	sendMessage(message);
+
+	LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index fea836aa68a8daab5d47360a4009f2d60f6b6708..f8ed89f644a098297ff7a23f3d3a60e6ee5654f1 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -1,426 +1,425 @@
-/** 
- * @file llpluginclassmedia.h
- * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&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$
- * @endcond
- */
-
-#ifndef LL_LLPLUGINCLASSMEDIA_H
-#define LL_LLPLUGINCLASSMEDIA_H
-
-#include "llgltypes.h"
-#include "llpluginprocessparent.h"
-#include "llrect.h"
-#include "llpluginclassmediaowner.h"
-#include <queue>
-#include "v4color.h"
-
-class LLPluginClassMedia : public LLPluginProcessParentOwner
-{
-	LOG_CLASS(LLPluginClassMedia);
-public:
-	LLPluginClassMedia(LLPluginClassMediaOwner *owner);
-	virtual ~LLPluginClassMedia();
-
-	// local initialization, called by the media manager when creating a source
-	virtual bool init(const std::string &launcher_filename, 
-					  const std::string &plugin_dir, 
-					  const std::string &plugin_filename, 
-					  bool debug);
-
-	// undoes everything init() didm called by the media manager when destroying a source
-	virtual void reset();
-	
-	void idle(void);
-	
-	// All of these may return 0 or an actual valid value.
-	// Callers need to check the return for 0, and not use the values in that case.
-	int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
-	int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
-	int getNaturalWidth() const { return mNaturalMediaWidth; };
-	int getNaturalHeight() const { return mNaturalMediaHeight; };
-	int getSetWidth() const { return mSetMediaWidth; };
-	int getSetHeight() const { return mSetMediaHeight; };
-	int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
-	int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
-	int getTextureWidth() const;
-	int getTextureHeight() const;
-	int getFullWidth() const { return mFullMediaWidth; };
-	int getFullHeight() const { return mFullMediaHeight; };
-	
-	// This may return NULL.  Callers need to check for and handle this case.
-	unsigned char* getBitsData();
-
-	// gets the format details of the texture data
-	// These may return 0 if they haven't been set up yet.  The caller needs to detect this case.
-	int getTextureDepth() const { return mRequestedTextureDepth; };
-	int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
-	int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
-	int getTextureFormatType() const { return mRequestedTextureType; };
-	bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
-	bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
-
-	void setSize(int width, int height);
-	void setAutoScale(bool auto_scale);
-	
-	void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
-	
-	void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
-	
-	// Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
-	// This will initially be false, and will also be false for some time after setSize while the resize is processed.
-	// Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
-	// until you call idle() again.
-	bool textureValid(void);
-	
-	bool getDirty(LLRect *dirty_rect = NULL);
-	void resetDirty(void);
-	
-	typedef enum 
-	{
-		MOUSE_EVENT_DOWN,
-		MOUSE_EVENT_UP,
-		MOUSE_EVENT_MOVE,
-		MOUSE_EVENT_DOUBLE_CLICK
-	}EMouseEventType;
-	
-	void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
-
-	typedef enum 
-	{
-		KEY_EVENT_DOWN,
-		KEY_EVENT_UP,
-		KEY_EVENT_REPEAT
-	}EKeyEventType;
-	
-	bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
-
-	void scrollEvent(int x, int y, MASK modifiers);
-
-	// Javascript <-> viewer events
-	void jsExposeObjectEvent( bool expose );
-	void jsValuesValidEvent( bool valid );
-	void jsAgentLocationEvent( double x, double y, double z );
-	void jsAgentGlobalLocationEvent( double x, double y, double z );
-	void jsAgentOrientationEvent( double angle );
-	void jsAgentLanguageEvent( const std::string& language );
-	void jsAgentRegionEvent( const std::string& region_name );
-	void jsAgentMaturityEvent( const std::string& maturity );
-		
-	// Text may be unicode (utf8 encoded)
-	bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
-	
-	void loadURI(const std::string &uri);
-	
-	// "Loading" means uninitialized or any state prior to fully running (processing commands)
-	bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
-
-	// "Running" means the steady state -- i.e. processing messages
-	bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
-	
-	// "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
-	bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
-
-	std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
-
-	bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
-	void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
-	
-	// Inherited from LLPluginProcessParentOwner
-	/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
-	/* virtual */ void pluginLaunchFailed();
-	/* virtual */ void pluginDied();
-	
-	
-	typedef enum 
-	{
-		PRIORITY_UNLOADED,	// media plugin isn't even loaded.
-		PRIORITY_STOPPED,	// media is not playing, shouldn't need to update at all.
-		PRIORITY_HIDDEN,	// media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
-		PRIORITY_SLIDESHOW,	// media is in the far distance, updates very infrequently
-		PRIORITY_LOW,		// media is in the distance, may be rendered at reduced size
-		PRIORITY_NORMAL,	// normal (default) priority
-		PRIORITY_HIGH		// media has user focus and/or is taking up most of the screen
-	}EPriority;
-
-	static const char* priorityToString(EPriority priority);
-	void setPriority(EPriority priority);
-	void setLowPrioritySizeLimit(int size);
-	
-	F64 getCPUUsage();
-	
-	void sendPickFileResponse(const std::string &file);
-
-	void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
-
-	// Valid after a MEDIA_EVENT_CURSOR_CHANGED event
-	std::string getCursorName() const { return mCursorName; };
-
-	LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
-
-	void	cut();
-	bool	canCut() const { return mCanCut; };
-
-	void	copy();
-	bool	canCopy() const { return mCanCopy; };
-
-	void	paste();
-	bool	canPaste() const { return mCanPaste; };
-	
-	// These can be called before init(), and they will be queued and sent before the media init message.
-	void	setUserDataPath(const std::string &user_data_path);
-	void	setLanguageCode(const std::string &language_code);
-	void	setPluginsEnabled(const bool enabled);
-	void	setJavascriptEnabled(const bool enabled);
-	void	setTarget(const std::string &target);
-	
-	///////////////////////////////////
-	// media browser class functions
-	bool pluginSupportsMediaBrowser(void);
-	
-	void focus(bool focused);
-	void clear_cache();
-	void clear_cookies();
-	void set_cookies(const std::string &cookies);
-	void enable_cookies(bool enable);
-	void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
-	void browse_stop();
-	void browse_reload(bool ignore_cache = false);
-	void browse_forward();
-	void browse_back();
-	void setBrowserUserAgent(const std::string& user_agent);
-	void proxyWindowOpened(const std::string &target, const std::string &uuid);
-	void proxyWindowClosed(const std::string &uuid);
-	void ignore_ssl_cert_errors(bool ignore);
-	void addCertificateFilePath(const std::string& path);
-	
-	// This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
-	std::string	getNavigateURI() const { return mNavigateURI; };
-
-	// These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
-	S32			getNavigateResultCode() const { return mNavigateResultCode; };
-	std::string getNavigateResultString() const { return mNavigateResultString; };
-	bool		getHistoryBackAvailable() const { return mHistoryBackAvailable; };
-	bool		getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
-
-	// This is valid after MEDIA_EVENT_PROGRESS_UPDATED
-	int			getProgressPercent() const { return mProgressPercent; };
-	
-	// This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
-	std::string getStatusText() const { return mStatusText; };
-	
-	// This is valid after MEDIA_EVENT_LOCATION_CHANGED
-	std::string getLocation() const { return mLocation; };
-	
-	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
-	std::string getClickURL() const { return mClickURL; };
-
-	// This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
-	std::string getClickNavType() const { return mClickNavType; };
-
-	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
-	std::string getClickTarget() const { return mClickTarget; };
-
-	// This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
-	std::string getClickUUID() const { return mClickUUID; };
-
-	// This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
-	S32 getStatusCode() const { return mStatusCode; };
-	
-	// These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
-	S32 getGeometryX() const { return mGeometryX; };
-	S32 getGeometryY() const { return mGeometryY; };
-	S32 getGeometryWidth() const { return mGeometryWidth; };
-	S32 getGeometryHeight() const { return mGeometryHeight; };
-	
-	// These are valid during MEDIA_EVENT_AUTH_REQUEST
-	std::string	getAuthURL() const { return mAuthURL; };
-	std::string	getAuthRealm() const { return mAuthRealm; };
-
-	// These are valid during MEDIA_EVENT_LINK_HOVERED
-	std::string	getHoverText() const { return mHoverText; };
-	std::string	getHoverLink() const { return mHoverLink; };
-	
-	std::string getMediaName() const { return mMediaName; };
-	std::string getMediaDescription() const { return mMediaDescription; };
-
-	// Crash the plugin.  If you use this outside of a testbed, you will be punished.
-	void		crashPlugin();
-	
-	// Hang the plugin.  If you use this outside of a testbed, you will be punished.
-	void		hangPlugin();
-
-	///////////////////////////////////
-	// media time class functions
-	bool pluginSupportsMediaTime(void);
-	void stop();
-	void start(float rate = 0.0f);
-	void pause();
-	void seek(float time);
-	void setLoop(bool loop);
-	void setVolume(float volume);
-	float getVolume();
-	
-	F64 getCurrentTime(void) const { return mCurrentTime; };
-	F64 getDuration(void) const { return mDuration; };
-	F64 getCurrentPlayRate(void) { return mCurrentRate; };
-	F64 getLoadedDuration(void) const { return mLoadedDuration; };
-	
-	// Initialize the URL history of the plugin by sending
-	// "init_history" message 
-	void initializeUrlHistory(const LLSD& url_history);
-
-protected:
-
-	LLPluginClassMediaOwner *mOwner;
-
-	// Notify this object's owner that an event has occurred.
-	void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
-		
-	void sendMessage(const LLPluginMessage &message);  // Send message internally, either queueing or sending directly.
-	std::queue<LLPluginMessage> mSendQueue;		// Used to queue messages while the plugin initializes.
-	
-	void setSizeInternal(void);
-
-	bool		mTextureParamsReceived;		// the mRequestedTexture* fields are only valid when this is true
-	S32 		mRequestedTextureDepth;
-	LLGLenum	mRequestedTextureInternalFormat;
-	LLGLenum	mRequestedTextureFormat;
-	LLGLenum	mRequestedTextureType;
-	bool		mRequestedTextureSwapBytes;
-	bool		mRequestedTextureCoordsOpenGL;
-	
-	std::string mTextureSharedMemoryName;
-	size_t		mTextureSharedMemorySize;
-	
-	// True to scale requested media up to the full size of the texture (i.e. next power of two)
-	bool		mAutoScaleMedia;
-
-	// default media size for the plugin, from the texture_params message.
-	int			mDefaultMediaWidth;
-	int			mDefaultMediaHeight;
-
-	// Size that has been requested by the plugin itself
-	int			mNaturalMediaWidth;
-	int			mNaturalMediaHeight;
-
-	// Size that has been requested with setSize()
-	int			mSetMediaWidth;
-	int			mSetMediaHeight;
-	
-	// Full calculated media size (before auto-scale and downsample calculations)
-	int			mFullMediaWidth;
-	int			mFullMediaHeight;
-
-	// Actual media size being set (after auto-scale)
-	int			mRequestedMediaWidth;
-	int			mRequestedMediaHeight;
-	
-	// Texture size calculated from actual media size
-	int			mRequestedTextureWidth;
-	int			mRequestedTextureHeight;
-	
-	// Size that the plugin has acknowledged
-	int			mTextureWidth;
-	int			mTextureHeight;
-	int			mMediaWidth;
-	int			mMediaHeight;
-	
-	float		mRequestedVolume;
-	
-	// Priority of this media stream
-	EPriority	mPriority;
-	int			mLowPrioritySizeLimit;
-	
-	bool		mAllowDownsample;
-	int			mPadding;
-	
-	
-	LLPluginProcessParent *mPlugin;
-	
-	LLRect mDirtyRect;
-	
-	std::string translateModifiers(MASK modifiers);
-	
-	std::string mCursorName;
-	int			mLastMouseX;
-	int			mLastMouseY;
-
-	LLPluginClassMediaOwner::EMediaStatus mStatus;
-	
-	F64				mSleepTime;
-
-	bool			mCanCut;
-	bool			mCanCopy;
-	bool			mCanPaste;
-	
-	std::string		mMediaName;
-	std::string		mMediaDescription;
-	
-	LLColor4		mBackgroundColor;
-	
-	std::string		mTarget;
-	
-	/////////////////////////////////////////
-	// media_browser class
-	std::string		mNavigateURI;
-	S32				mNavigateResultCode;
-	std::string		mNavigateResultString;
-	bool			mHistoryBackAvailable;
-	bool			mHistoryForwardAvailable;
-	std::string		mStatusText;
-	int				mProgressPercent;
-	std::string		mLocation;
-	std::string		mClickURL;
-	std::string		mClickNavType;
-	std::string		mClickTarget;
-	std::string		mClickUUID;
-	S32				mGeometryX;
-	S32				mGeometryY;
-	S32				mGeometryWidth;
-	S32				mGeometryHeight;
-	S32				mStatusCode;
-	std::string		mAuthURL;
-	std::string		mAuthRealm;
-	std::string		mHoverText;
-	std::string		mHoverLink;
-	
-	/////////////////////////////////////////
-	// media_time class
-	F64				mCurrentTime;
-	F64				mDuration;
-	F64				mCurrentRate;
-	F64				mLoadedDuration;
-	
-//--------------------------------------
-	//debug use only
-	//
-private:
-	bool  mDeleteOK ;
-public:
-	void setDeleteOK(bool flag) { mDeleteOK = flag ;}
-//--------------------------------------
-};
-
-#endif // LL_LLPLUGINCLASSMEDIA_H
+/** 
+ * @file llpluginclassmedia.h
+ * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&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$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINCLASSMEDIA_H
+#define LL_LLPLUGINCLASSMEDIA_H
+
+#include "llgltypes.h"
+#include "llpluginprocessparent.h"
+#include "llrect.h"
+#include "llpluginclassmediaowner.h"
+#include <queue>
+#include "v4color.h"
+
+class LLPluginClassMedia : public LLPluginProcessParentOwner
+{
+	LOG_CLASS(LLPluginClassMedia);
+public:
+	LLPluginClassMedia(LLPluginClassMediaOwner *owner);
+	virtual ~LLPluginClassMedia();
+
+	// local initialization, called by the media manager when creating a source
+	virtual bool init(const std::string &launcher_filename, 
+					  const std::string &plugin_dir, 
+					  const std::string &plugin_filename, 
+					  bool debug);
+
+	// undoes everything init() didm called by the media manager when destroying a source
+	virtual void reset();
+	
+	void idle(void);
+	
+	// All of these may return 0 or an actual valid value.
+	// Callers need to check the return for 0, and not use the values in that case.
+	int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
+	int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
+	int getNaturalWidth() const { return mNaturalMediaWidth; };
+	int getNaturalHeight() const { return mNaturalMediaHeight; };
+	int getSetWidth() const { return mSetMediaWidth; };
+	int getSetHeight() const { return mSetMediaHeight; };
+	int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
+	int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
+	int getTextureWidth() const;
+	int getTextureHeight() const;
+	int getFullWidth() const { return mFullMediaWidth; };
+	int getFullHeight() const { return mFullMediaHeight; };
+	
+	// This may return NULL.  Callers need to check for and handle this case.
+	unsigned char* getBitsData();
+
+	// gets the format details of the texture data
+	// These may return 0 if they haven't been set up yet.  The caller needs to detect this case.
+	int getTextureDepth() const { return mRequestedTextureDepth; };
+	int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
+	int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
+	int getTextureFormatType() const { return mRequestedTextureType; };
+	bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
+	bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
+
+	void setSize(int width, int height);
+	void setAutoScale(bool auto_scale);
+	
+	void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
+	
+	void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
+	
+	// Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
+	// This will initially be false, and will also be false for some time after setSize while the resize is processed.
+	// Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
+	// until you call idle() again.
+	bool textureValid(void);
+	
+	bool getDirty(LLRect *dirty_rect = NULL);
+	void resetDirty(void);
+	
+	typedef enum 
+	{
+		MOUSE_EVENT_DOWN,
+		MOUSE_EVENT_UP,
+		MOUSE_EVENT_MOVE,
+		MOUSE_EVENT_DOUBLE_CLICK
+	}EMouseEventType;
+	
+	void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
+
+	typedef enum 
+	{
+		KEY_EVENT_DOWN,
+		KEY_EVENT_UP,
+		KEY_EVENT_REPEAT
+	}EKeyEventType;
+	
+	bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
+
+	void scrollEvent(int x, int y, MASK modifiers);
+
+	// Javascript <-> viewer events
+	void jsEnableObject( bool enable );
+	void jsAgentLocationEvent( double x, double y, double z );
+	void jsAgentGlobalLocationEvent( double x, double y, double z );
+	void jsAgentOrientationEvent( double angle );
+	void jsAgentLanguageEvent( const std::string& language );
+	void jsAgentRegionEvent( const std::string& region_name );
+	void jsAgentMaturityEvent( const std::string& maturity );
+		
+	// Text may be unicode (utf8 encoded)
+	bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
+	
+	void loadURI(const std::string &uri);
+	
+	// "Loading" means uninitialized or any state prior to fully running (processing commands)
+	bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
+
+	// "Running" means the steady state -- i.e. processing messages
+	bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
+	
+	// "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
+	bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
+
+	std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
+
+	bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
+	void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
+	
+	// Inherited from LLPluginProcessParentOwner
+	/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+	/* virtual */ void pluginLaunchFailed();
+	/* virtual */ void pluginDied();
+	
+	
+	typedef enum 
+	{
+		PRIORITY_UNLOADED,	// media plugin isn't even loaded.
+		PRIORITY_STOPPED,	// media is not playing, shouldn't need to update at all.
+		PRIORITY_HIDDEN,	// media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
+		PRIORITY_SLIDESHOW,	// media is in the far distance, updates very infrequently
+		PRIORITY_LOW,		// media is in the distance, may be rendered at reduced size
+		PRIORITY_NORMAL,	// normal (default) priority
+		PRIORITY_HIGH		// media has user focus and/or is taking up most of the screen
+	}EPriority;
+
+	static const char* priorityToString(EPriority priority);
+	void setPriority(EPriority priority);
+	void setLowPrioritySizeLimit(int size);
+	
+	F64 getCPUUsage();
+	
+	void sendPickFileResponse(const std::string &file);
+
+	void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
+
+	// Valid after a MEDIA_EVENT_CURSOR_CHANGED event
+	std::string getCursorName() const { return mCursorName; };
+
+	LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
+
+	void	cut();
+	bool	canCut() const { return mCanCut; };
+
+	void	copy();
+	bool	canCopy() const { return mCanCopy; };
+
+	void	paste();
+	bool	canPaste() const { return mCanPaste; };
+	
+	// These can be called before init(), and they will be queued and sent before the media init message.
+	void	setUserDataPath(const std::string &user_data_path);
+	void	setLanguageCode(const std::string &language_code);
+	void	setPluginsEnabled(const bool enabled);
+	void	setJavascriptEnabled(const bool enabled);
+	void	setTarget(const std::string &target);
+	
+	///////////////////////////////////
+	// media browser class functions
+	bool pluginSupportsMediaBrowser(void);
+	
+	void focus(bool focused);
+	void clear_cache();
+	void clear_cookies();
+	void set_cookies(const std::string &cookies);
+	void enable_cookies(bool enable);
+	void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
+	void browse_stop();
+	void browse_reload(bool ignore_cache = false);
+	void browse_forward();
+	void browse_back();
+	void setBrowserUserAgent(const std::string& user_agent);
+	void proxyWindowOpened(const std::string &target, const std::string &uuid);
+	void proxyWindowClosed(const std::string &uuid);
+	void ignore_ssl_cert_errors(bool ignore);
+	void addCertificateFilePath(const std::string& path);
+	
+	// This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
+	std::string	getNavigateURI() const { return mNavigateURI; };
+
+	// These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
+	S32			getNavigateResultCode() const { return mNavigateResultCode; };
+	std::string getNavigateResultString() const { return mNavigateResultString; };
+	bool		getHistoryBackAvailable() const { return mHistoryBackAvailable; };
+	bool		getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
+
+	// This is valid after MEDIA_EVENT_PROGRESS_UPDATED
+	int			getProgressPercent() const { return mProgressPercent; };
+	
+	// This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
+	std::string getStatusText() const { return mStatusText; };
+	
+	// This is valid after MEDIA_EVENT_LOCATION_CHANGED
+	std::string getLocation() const { return mLocation; };
+	
+	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+	std::string getClickURL() const { return mClickURL; };
+
+	// This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+	std::string getClickNavType() const { return mClickNavType; };
+
+	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+	std::string getClickTarget() const { return mClickTarget; };
+
+	// This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
+	std::string getClickUUID() const { return mClickUUID; };
+
+	// This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
+	S32 getStatusCode() const { return mStatusCode; };
+	
+	// These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
+	S32 getGeometryX() const { return mGeometryX; };
+	S32 getGeometryY() const { return mGeometryY; };
+	S32 getGeometryWidth() const { return mGeometryWidth; };
+	S32 getGeometryHeight() const { return mGeometryHeight; };
+	
+	// These are valid during MEDIA_EVENT_AUTH_REQUEST
+	std::string	getAuthURL() const { return mAuthURL; };
+	std::string	getAuthRealm() const { return mAuthRealm; };
+
+	// These are valid during MEDIA_EVENT_LINK_HOVERED
+	std::string	getHoverText() const { return mHoverText; };
+	std::string	getHoverLink() const { return mHoverLink; };
+	
+	std::string getMediaName() const { return mMediaName; };
+	std::string getMediaDescription() const { return mMediaDescription; };
+
+	// Crash the plugin.  If you use this outside of a testbed, you will be punished.
+	void		crashPlugin();
+	
+	// Hang the plugin.  If you use this outside of a testbed, you will be punished.
+	void		hangPlugin();
+
+	///////////////////////////////////
+	// media time class functions
+	bool pluginSupportsMediaTime(void);
+	void stop();
+	void start(float rate = 0.0f);
+	void pause();
+	void seek(float time);
+	void setLoop(bool loop);
+	void setVolume(float volume);
+	float getVolume();
+	
+	F64 getCurrentTime(void) const { return mCurrentTime; };
+	F64 getDuration(void) const { return mDuration; };
+	F64 getCurrentPlayRate(void) { return mCurrentRate; };
+	F64 getLoadedDuration(void) const { return mLoadedDuration; };
+	
+	// Initialize the URL history of the plugin by sending
+	// "init_history" message 
+	void initializeUrlHistory(const LLSD& url_history);
+
+protected:
+
+	LLPluginClassMediaOwner *mOwner;
+
+	// Notify this object's owner that an event has occurred.
+	void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
+		
+	void sendMessage(const LLPluginMessage &message);  // Send message internally, either queueing or sending directly.
+	std::queue<LLPluginMessage> mSendQueue;		// Used to queue messages while the plugin initializes.
+	
+	void setSizeInternal(void);
+
+	bool		mTextureParamsReceived;		// the mRequestedTexture* fields are only valid when this is true
+	S32 		mRequestedTextureDepth;
+	LLGLenum	mRequestedTextureInternalFormat;
+	LLGLenum	mRequestedTextureFormat;
+	LLGLenum	mRequestedTextureType;
+	bool		mRequestedTextureSwapBytes;
+	bool		mRequestedTextureCoordsOpenGL;
+	
+	std::string mTextureSharedMemoryName;
+	size_t		mTextureSharedMemorySize;
+	
+	// True to scale requested media up to the full size of the texture (i.e. next power of two)
+	bool		mAutoScaleMedia;
+
+	// default media size for the plugin, from the texture_params message.
+	int			mDefaultMediaWidth;
+	int			mDefaultMediaHeight;
+
+	// Size that has been requested by the plugin itself
+	int			mNaturalMediaWidth;
+	int			mNaturalMediaHeight;
+
+	// Size that has been requested with setSize()
+	int			mSetMediaWidth;
+	int			mSetMediaHeight;
+	
+	// Full calculated media size (before auto-scale and downsample calculations)
+	int			mFullMediaWidth;
+	int			mFullMediaHeight;
+
+	// Actual media size being set (after auto-scale)
+	int			mRequestedMediaWidth;
+	int			mRequestedMediaHeight;
+	
+	// Texture size calculated from actual media size
+	int			mRequestedTextureWidth;
+	int			mRequestedTextureHeight;
+	
+	// Size that the plugin has acknowledged
+	int			mTextureWidth;
+	int			mTextureHeight;
+	int			mMediaWidth;
+	int			mMediaHeight;
+	
+	float		mRequestedVolume;
+	
+	// Priority of this media stream
+	EPriority	mPriority;
+	int			mLowPrioritySizeLimit;
+	
+	bool		mAllowDownsample;
+	int			mPadding;
+	
+	
+	LLPluginProcessParent *mPlugin;
+	
+	LLRect mDirtyRect;
+	
+	std::string translateModifiers(MASK modifiers);
+	
+	std::string mCursorName;
+	int			mLastMouseX;
+	int			mLastMouseY;
+
+	LLPluginClassMediaOwner::EMediaStatus mStatus;
+	
+	F64				mSleepTime;
+
+	bool			mCanCut;
+	bool			mCanCopy;
+	bool			mCanPaste;
+	
+	std::string		mMediaName;
+	std::string		mMediaDescription;
+	
+	LLColor4		mBackgroundColor;
+	
+	std::string		mTarget;
+	
+	/////////////////////////////////////////
+	// media_browser class
+	std::string		mNavigateURI;
+	S32				mNavigateResultCode;
+	std::string		mNavigateResultString;
+	bool			mHistoryBackAvailable;
+	bool			mHistoryForwardAvailable;
+	std::string		mStatusText;
+	int				mProgressPercent;
+	std::string		mLocation;
+	std::string		mClickURL;
+	std::string		mClickNavType;
+	std::string		mClickTarget;
+	std::string		mClickUUID;
+	S32				mGeometryX;
+	S32				mGeometryY;
+	S32				mGeometryWidth;
+	S32				mGeometryHeight;
+	S32				mStatusCode;
+	std::string		mAuthURL;
+	std::string		mAuthRealm;
+	std::string		mHoverText;
+	std::string		mHoverLink;
+	
+	/////////////////////////////////////////
+	// media_time class
+	F64				mCurrentTime;
+	F64				mDuration;
+	F64				mCurrentRate;
+	F64				mLoadedDuration;
+	
+//--------------------------------------
+	//debug use only
+	//
+private:
+	bool  mDeleteOK ;
+public:
+	void setDeleteOK(bool flag) { mDeleteOK = flag ;}
+//--------------------------------------
+};
+
+#endif // LL_LLPLUGINCLASSMEDIA_H
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 5914c3551a9712bb3451e78f3b2473c7748422d9..0bbdcfd6ffe8048afc77a55c2b6ad2d0442b442c 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -28,6 +28,8 @@ include_directories(
 set(llui_SOURCE_FILES
     llaccordionctrl.cpp
     llaccordionctrltab.cpp
+    llbadge.cpp
+    llbadgeowner.cpp
     llbutton.cpp
     llcheckboxctrl.cpp
     llclipboard.cpp
@@ -120,6 +122,8 @@ set(llui_HEADER_FILES
 
     llaccordionctrl.h
     llaccordionctrltab.h
+    llbadge.h
+    llbadgeowner.h
     llbutton.h
     llcallbackmap.h
     llcheckboxctrl.h
@@ -247,11 +251,11 @@ target_link_libraries(llui
     )
 
 # Add tests
-if (LL_TESTS)
-	include(LLAddBuildTest)
-	SET(llui_TEST_SOURCE_FILES
-		llurlmatch.cpp
-		llurlentry.cpp
-		)
-	LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
-endif (LL_TESTS)
\ No newline at end of file
+if(LL_TESTS)
+  include(LLAddBuildTest)
+  SET(llui_TEST_SOURCE_FILES
+      llurlmatch.cpp
+      llurlentry.cpp
+      )
+  LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
+endif(LL_TESTS)
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 9e4849c58b781a6d2b161f28c80aaec61df03171..6afe27637902ce458662ddf71c0551fbc960b9f9 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -1022,7 +1022,7 @@ void	LLAccordionCtrlTab::updateLayout	( const LLRect& child_rect )
 	S32 panel_width = child_rect.getWidth();
 
 	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
-	if(mScrollbar->getVisible() != false)
+	if(mScrollbar && mScrollbar->getVisible() != false)
 	{
 		panel_top+=mScrollbar->getDocPos();
 		panel_width-=scrollbar_size;
diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c28a947a7fa1eb2e8fb2486d19b314a26739dd5d
--- /dev/null
+++ b/indra/llui/llbadge.cpp
@@ -0,0 +1,274 @@
+/** 
+ * @file llbadge.cpp
+ * @brief Implementation for badges
+ *
+ * $LicenseInfo:firstyear=2001&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$
+ */
+
+#define LLBADGE_CPP
+#include "llbadge.h"
+
+#include "lluictrlfactory.h"
+
+
+static LLDefaultChildRegistry::Register<LLBadge> r("badge");
+
+// Compiler optimization, generate extern template
+template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+
+
+LLBadge::Params::Params()
+	: image("image")
+	, border_image("border_image")
+	, border_color("border_color")
+	, image_color("image_color")
+	, label("label")
+	, label_color("label_color")
+	, location("location", LLRelPos::TOP_LEFT)
+	, location_percent_hcenter("location_percent_hcenter")
+	, location_percent_vcenter("location_percent_vcenter")
+	, padding_horiz("padding_horiz")
+	, padding_vert("padding_vert")
+{
+	// We set a name here so the name isn't necessary in any xml files that use badges
+	name = "badge";
+}
+
+bool LLBadge::Params::equals(const Params& a) const
+{
+	bool comp = true;
+	
+	// skip owner in comparison on purpose
+	
+	comp &= (border_image() == a.border_image());
+	comp &= (border_color() == a.border_color());
+	comp &= (image() == a.image());
+	comp &= (image_color() == a.image_color());
+	comp &= (label() == a.label());
+	comp &= (label_color() == a.label_color());
+	comp &= (location() == a.location());
+	comp &= (location_percent_hcenter() == a.location_percent_hcenter());
+	comp &= (location_percent_vcenter() == a.location_percent_vcenter());
+	comp &= (padding_horiz() == a.padding_horiz());
+	comp &= (padding_vert() == a.padding_vert());
+	
+	return comp;
+}
+
+LLBadge::LLBadge(const LLBadge::Params& p)
+	: LLUICtrl(p)
+	, mOwner(p.owner)
+	, mBorderImage(p.border_image)
+	, mBorderColor(p.border_color)
+	, mGLFont(p.font)
+	, mImage(p.image)
+	, mImageColor(p.image_color)
+	, mLabel(p.label)
+	, mLabelColor(p.label_color)
+	, mLocation(p.location)
+	, mLocationPercentHCenter(0.5f)
+	, mLocationPercentVCenter(0.5f)
+	, mPaddingHoriz(p.padding_horiz)
+	, mPaddingVert(p.padding_vert)
+{
+	if (mImage.isNull())
+	{
+		llwarns << "Badge: " << getName() << " with no image!" << llendl;
+	}
+
+	//
+	// The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter
+	// based on the Location enum and our horizontal and vertical location percentages.  The
+	// draw code then uses this on the owner rectangle to compute the screen location for
+	// the badge.
+	//
+
+	if (!LLRelPos::IsCenter(mLocation))
+	{
+		F32 h_center = p.location_percent_hcenter * 0.01f;
+		F32 v_center = p.location_percent_vcenter * 0.01f;
+
+		if (LLRelPos::IsRight(mLocation))
+		{
+			mLocationPercentHCenter = 0.5f * (1.0f + h_center);
+		}
+		else if (LLRelPos::IsLeft(mLocation))
+		{
+			mLocationPercentHCenter = 0.5f * (1.0f - h_center);
+		}
+			
+		if (LLRelPos::IsTop(mLocation))
+		{
+			mLocationPercentVCenter = 0.5f * (1.0f + v_center);
+		}
+		else if (LLRelPos::IsBottom(mLocation))
+		{
+			mLocationPercentVCenter = 0.5f * (1.0f - v_center);
+		}
+	}
+}
+
+LLBadge::~LLBadge()
+{
+}
+
+void LLBadge::setLabel(const LLStringExplicit& label)
+{
+	mLabel = label;
+}
+
+//
+// This is a fallback function to render a rectangle for badges without a valid image
+//
+void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, const LLColor4U &color)
+{
+	gGL.pushUIMatrix();
+	gGL.loadUIIdentity();
+	gGL.setSceneBlendType(LLRender::BT_REPLACE);
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	
+	gGL.color4ubv(color.mV);
+	gGL.texCoord2i(0, 0);
+	
+	F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f;
+	F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f;
+	
+	LLRectf screen_rect(llround(x),
+						llround(y),
+						llround(x) + width,
+						llround(y) + height);
+	
+	LLVector3 vertices[4];
+	vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop,    1.0f);
+	vertices[1] = LLVector3(screen_rect.mLeft,  screen_rect.mTop,    1.0f);
+	vertices[2] = LLVector3(screen_rect.mLeft,  screen_rect.mBottom, 1.0f);
+	vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
+	
+	gGL.begin(LLRender::QUADS);
+	{
+		gGL.vertexBatchPreTransformed(vertices, 4);
+	}
+	gGL.end();
+	
+	gGL.popUIMatrix();
+}
+
+
+// virtual
+void LLBadge::draw()
+{
+	if (!mLabel.empty())
+	{
+		LLView* owner_view = mOwner.get();
+
+		if (owner_view)
+		{
+			//
+			// Calculate badge position based on owner
+			//
+			
+			LLRect owner_rect;
+			owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this);
+			
+			F32 badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter;
+			F32 badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter;
+
+			//
+			// Calculate badge size based on label text
+			//
+
+			LLWString badge_label_wstring = mLabel;
+			
+			S32 badge_label_begin_offset = 0;
+			S32 badge_char_length = S32_MAX;
+			S32 badge_pixel_length = S32_MAX;
+			F32 *right_position_out = NULL;
+			BOOL do_not_use_ellipses = false;
+
+			F32 badge_width = (2.0f * mPaddingHoriz) +
+				mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length);
+
+			F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight();
+
+			//
+			// Draw button image, if available.
+			// Otherwise draw basic rectangular button.
+			//
+
+			F32 alpha = getDrawContext().mAlpha;
+
+			if (!mImage.isNull())
+			{
+				F32 badge_x = badge_center_x - badge_width * 0.5f;
+				F32 badge_y = badge_center_y - badge_height * 0.5f;
+			
+				mImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mImageColor % alpha);
+
+				if (!mBorderImage.isNull())
+				{
+					mBorderImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mBorderColor % alpha);
+				}
+			}
+			else
+			{
+				lldebugs << "No image for badge " << getName() << " on owner " << owner_view->getName() << llendl;
+				
+				renderBadgeBackground(badge_center_x, badge_center_y,
+									  badge_width, badge_height,
+									  mImageColor % alpha);
+			}
+
+			//
+			// Draw the label
+			//
+
+			mGLFont->render(badge_label_wstring, badge_label_begin_offset,
+							badge_center_x, badge_center_y,
+							mLabelColor % alpha,
+							LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
+							LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
+							LLFontGL::DROP_SHADOW_SOFT,
+							badge_char_length, badge_pixel_length,
+							right_position_out, do_not_use_ellipses);
+		}
+	}
+}
+
+
+namespace LLInitParam
+{
+	void TypeValues<LLRelPos::Location>::declareValues()
+	{
+		declare("bottom",		LLRelPos::BOTTOM);
+		declare("bottom_left",	LLRelPos::BOTTOM_LEFT);
+		declare("bottom_right", LLRelPos::BOTTOM_RIGHT);
+		declare("center",		LLRelPos::CENTER);
+		declare("left",			LLRelPos::LEFT);
+		declare("right",		LLRelPos::RIGHT);
+		declare("top",			LLRelPos::TOP);
+		declare("top_left",		LLRelPos::TOP_LEFT);
+		declare("top_right",	LLRelPos::TOP_RIGHT);
+	}
+}
+
+
+// eof
diff --git a/indra/llui/llbadge.h b/indra/llui/llbadge.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f923ef01b78e856928049a08d2bf6c5bee7bdf4
--- /dev/null
+++ b/indra/llui/llbadge.h
@@ -0,0 +1,159 @@
+/** 
+ * @file llbadge.h
+ * @brief Header for badges
+ *
+ * $LicenseInfo:firstyear=2001&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_LLBADGE_H
+#define LL_LLBADGE_H
+
+#include <string>
+
+#include "lluicolor.h"
+#include "lluictrl.h"
+#include "llstring.h"
+#include "lluiimage.h"
+#include "llview.h"
+
+//
+// Declarations
+//
+
+class LLUICtrlFactory;
+class LLFontGL;
+
+//
+// Relative Position Alignment
+//
+
+namespace LLRelPos
+{
+	enum Location
+	{
+		CENTER	= 0,
+
+		LEFT	= (1 << 0),
+		RIGHT	= (1 << 1),
+
+		TOP		= (1 << 2),
+		BOTTOM	= (1 << 3),
+
+		BOTTOM_LEFT		= (BOTTOM | LEFT),
+		BOTTOM_RIGHT	= (BOTTOM | RIGHT),
+
+		TOP_LEFT		= (TOP | LEFT),
+		TOP_RIGHT		= (TOP | RIGHT),
+	};
+
+	inline bool IsBottom(Location relPos)	{ return (relPos & BOTTOM) == BOTTOM; }
+	inline bool IsCenter(Location relPos)	{ return (relPos == CENTER); }
+	inline bool IsLeft(Location relPos)		{ return (relPos & LEFT) == LEFT; }
+	inline bool IsRight(Location relPos)	{ return (relPos & RIGHT) == RIGHT; }
+	inline bool IsTop(Location relPos)		{ return (relPos & TOP) == TOP; }
+}
+
+// NOTE: This needs to occur before Optional<LLRelPos::Location> declaration for proper compilation.
+namespace LLInitParam
+{
+	template<>
+	struct TypeValues<LLRelPos::Location> : public TypeValuesHelper<LLRelPos::Location>
+	{
+		static void declareValues();
+	};
+}
+
+//
+// Classes
+//
+
+class LLBadge
+: public LLUICtrl
+{
+public:
+	struct Params 
+	: public LLInitParam::Block<Params, LLUICtrl::Params>
+	{
+		Optional< LLHandle<LLView> >	owner;	// Mandatory in code but not in xml
+		
+		Optional< LLUIImage* >			border_image;
+		Optional< LLUIColor >			border_color;
+
+		Optional< LLUIImage* >			image;
+		Optional< LLUIColor >			image_color;
+		
+		Optional< std::string >			label;
+		Optional< LLUIColor >			label_color;
+
+		Optional< LLRelPos::Location >	location;
+		Optional< U32 >					location_percent_hcenter;
+		Optional< U32 >					location_percent_vcenter;
+
+		Optional< F32 >					padding_horiz;
+		Optional< F32 >					padding_vert;
+		
+		Params();
+		
+		bool equals(const Params&) const;
+	};
+	
+protected:
+	friend class LLUICtrlFactory;
+	LLBadge(const Params& p);
+
+public:
+
+	~LLBadge();
+	
+	virtual void		draw();
+
+	const std::string	getLabel() const { return wstring_to_utf8str(mLabel); }
+	void				setLabel( const LLStringExplicit& label);
+
+private:
+	LLPointer< LLUIImage >	mBorderImage;
+	LLUIColor				mBorderColor;
+
+	const LLFontGL*			mGLFont;
+	
+	LLPointer< LLUIImage >	mImage;
+	LLUIColor				mImageColor;
+	
+	LLUIString				mLabel;
+	LLUIColor				mLabelColor;
+
+	LLRelPos::Location		mLocation;
+	F32						mLocationPercentHCenter;
+	F32						mLocationPercentVCenter;
+	
+	LLHandle< LLView >		mOwner;
+
+	F32						mPaddingHoriz;
+	F32						mPaddingVert;
+};
+
+// Build time optimization, generate once in .cpp file
+#ifndef LLBADGE_CPP
+extern template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+#endif
+
+#endif  // LL_LLBADGE_H
diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..77f15567bf655d5a155605c55d11a3f6336a1d9c
--- /dev/null
+++ b/indra/llui/llbadgeowner.cpp
@@ -0,0 +1,126 @@
+/** 
+ * @file llbadgeowner.cpp
+ * @brief Class to manage badges attached to a UI control
+ *
+ * $LicenseInfo:firstyear=2001&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 "linden_common.h"
+
+#include "llbadgeowner.h"
+#include "llpanel.h"
+
+//
+// Classes
+//
+
+LLBadgeOwner::LLBadgeOwner(LLHandle< LLView > viewHandle)
+	: mBadge(NULL)
+	, mBadgeOwnerView(viewHandle)
+{
+}
+
+void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
+{
+	if (!p.equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
+	{
+		mBadge = createBadge(p);
+	}
+}
+
+void LLBadgeOwner::setBadgeLabel(const LLStringExplicit& label)
+{
+	if (mBadge == NULL)
+	{
+		mBadge = createBadge(LLUICtrlFactory::getDefaultParams<LLBadge>());
+
+		addBadgeToParentPanel();
+	}
+
+	if (mBadge)
+	{
+		mBadge->setLabel(label);
+
+		//
+		// Push the badge to the front so it renders on top
+		//
+
+		LLView * parent = mBadge->getParent();
+
+		if (parent)
+		{
+			parent->sendChildToFront(mBadge);
+		}
+	}
+}
+
+void LLBadgeOwner::setBadgeVisibility(bool visible)
+{
+	if (mBadge)
+	{
+		mBadge->setVisible(visible);
+	}
+}
+
+void LLBadgeOwner::addBadgeToParentPanel()
+{
+	LLView * owner_view = mBadgeOwnerView.get();
+	
+	if (mBadge && owner_view)
+	{
+		// Badge parent is badge owner by default
+		LLView * badge_parent = owner_view;
+
+		// Find the appropriate parent for the badge
+		LLView * parent = owner_view->getParent();
+
+		while (parent)
+		{
+			LLPanel * parent_panel = dynamic_cast<LLPanel *>(parent);
+
+			if (parent_panel && parent_panel->acceptsBadge())
+			{
+				badge_parent = parent;
+				break;
+			}
+
+			parent = parent->getParent();
+		}
+
+		if (badge_parent)
+		{
+			badge_parent->addChild(mBadge);
+		}
+		else
+		{
+			llwarns << "Unable to find parent panel for badge " << mBadge->getName() << " on " << owner_view->getName() << llendl;
+		}
+	}
+}
+
+LLBadge* LLBadgeOwner::createBadge(const LLBadge::Params& p)
+{
+	LLBadge::Params badge_params(p);
+	badge_params.owner = mBadgeOwnerView;
+
+	return LLUICtrlFactory::create<LLBadge>(badge_params);
+}
diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2399189a5530b832b7fa828468005833569d1ea
--- /dev/null
+++ b/indra/llui/llbadgeowner.h
@@ -0,0 +1,61 @@
+/** 
+ * @file llbadgeowner.h
+ * @brief Header for badge owners
+ *
+ * $LicenseInfo:firstyear=2001&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_LLBADGEOWNER_H
+#define LL_LLBADGEOWNER_H
+
+#include "llbadge.h"
+#include "llview.h"
+
+//
+// Classes
+//
+
+class LLBadgeOwner
+{
+public:
+
+	LLBadgeOwner(LLHandle< LLView > viewHandle);
+
+	void initBadgeParams(const LLBadge::Params& p);
+	void addBadgeToParentPanel();
+	
+	bool badgeHasParent() const { return (mBadge && mBadge->getParent()); }
+
+	void setBadgeLabel(const LLStringExplicit& label);
+	void setBadgeVisibility(bool visible);
+
+private:
+
+	LLBadge* createBadge(const LLBadge::Params& p);
+
+private:
+
+	LLBadge*			mBadge;
+	LLHandle< LLView >	mBadgeOwnerView;
+};
+
+#endif  // LL_LLBADGEOWNER_H
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 45ceaff69693e9149130fcedc8063016dbd03927..7b015bd57694a4d12ffb280b84f6dabbca7c5d3c 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -99,7 +99,9 @@ LLButton::Params::Params()
 	scale_image("scale_image", true),
 	hover_glow_amount("hover_glow_amount"),
 	commit_on_return("commit_on_return", true),
-	use_draw_context_alpha("use_draw_context_alpha", true)
+	use_draw_context_alpha("use_draw_context_alpha", true),
+	badge("badge"),
+	handle_right_mouse("handle_right_mouse")
 {
 	addSynonym(is_toggle, "toggle");
 	held_down_delay.seconds = 0.5f;
@@ -109,6 +111,7 @@ LLButton::Params::Params()
 
 LLButton::LLButton(const LLButton::Params& p)
 :	LLUICtrl(p),
+	LLBadgeOwner(LLView::getHandle()),
 	mMouseDownFrame(0),
 	mMouseHeldDownCount(0),
 	mBorderEnabled( FALSE ),
@@ -160,8 +163,8 @@ LLButton::LLButton(const LLButton::Params& p)
 	mMouseDownSignal(NULL),
 	mMouseUpSignal(NULL),
 	mHeldDownSignal(NULL),
-	mUseDrawContextAlpha(p.use_draw_context_alpha)
-
+	mUseDrawContextAlpha(p.use_draw_context_alpha),
+	mHandleRightMouse(p.handle_right_mouse)
 {
 	static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
 	static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
@@ -244,6 +247,11 @@ LLButton::LLButton(const LLButton::Params& p)
 	{
 		setHeldDownCallback(initCommitCallback(p.mouse_held_callback));
 	}
+
+	if (p.badge.isProvided())
+	{
+		LLBadgeOwner::initBadgeParams(p.badge());
+	}
 }
 
 LLButton::~LLButton()
@@ -327,8 +335,12 @@ boost::signals2::connection LLButton::setHeldDownCallback( button_callback_t cb,
 BOOL LLButton::postBuild()
 {
 	autoResize();
-	return TRUE;
+
+	addBadgeToParentPanel();
+
+	return LLUICtrl::postBuild();
 }
+
 BOOL LLButton::handleUnicodeCharHere(llwchar uni_char)
 {
 	BOOL handled = FALSE;
@@ -447,7 +459,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
 
 BOOL	LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
-	if (!childrenHandleRightMouseDown(x, y, mask))
+	if (mHandleRightMouse && !childrenHandleRightMouseDown(x, y, mask))
 	{
 		// Route future Mouse messages here preemptively.  (Release on mouse up.)
 		gFocusMgr.setMouseCapture( this );
@@ -460,37 +472,42 @@ BOOL	LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask)
 //		if (pointInView(x, y))
 //		{
 //		}
+		// send the mouse down signal
+		LLUICtrl::handleRightMouseDown(x,y,mask);
+		// *TODO: Return result of LLUICtrl call above?  Should defer to base class
+		// but this might change the mouse handling of existing buttons in a bad way
+		// if they are not mouse opaque.
 	}
-	// send the mouse down signal
-	LLUICtrl::handleRightMouseDown(x,y,mask);
-	// *TODO: Return result of LLUICtrl call above?  Should defer to base class
-	// but this might change the mouse handling of existing buttons in a bad way
-	// if they are not mouse opaque.
+
 	return TRUE;
 }
 
 BOOL	LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask)
 {
-	// We only handle the click if the click both started and ended within us
-	if( hasMouseCapture() )
+	if (mHandleRightMouse)
 	{
-		// Always release the mouse
-		gFocusMgr.setMouseCapture( NULL );
+		// We only handle the click if the click both started and ended within us
+		if( hasMouseCapture() )
+		{
+			// Always release the mouse
+			gFocusMgr.setMouseCapture( NULL );
 
-//		if (pointInView(x, y))
-//		{
-//			mRightMouseUpSignal(this, x,y,mask);
-//		}
-	}
-	else 
-	{
-		childrenHandleRightMouseUp(x, y, mask);
+	//		if (pointInView(x, y))
+	//		{
+	//			mRightMouseUpSignal(this, x,y,mask);
+	//		}
+		}
+		else 
+		{
+			childrenHandleRightMouseUp(x, y, mask);
+		}
+	
+		// send the mouse up signal
+		LLUICtrl::handleRightMouseUp(x,y,mask);
+		// *TODO: Return result of LLUICtrl call above?  Should defer to base class
+		// but this might change the mouse handling of existing buttons in a bad way.
+		// if they are not mouse opaque.
 	}
-	// send the mouse up signal
-	LLUICtrl::handleRightMouseUp(x,y,mask);
-	// *TODO: Return result of LLUICtrl call above?  Should defer to base class
-	// but this might change the mouse handling of existing buttons in a bad way.
-	// if they are not mouse opaque.
 	return TRUE;
 }
 
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 0cfc393e05053f56a72ecec85d6fcc14adebe779..59689160060716520320afa126f7f9b9606323d1 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -27,6 +27,8 @@
 #ifndef LL_LLBUTTON_H
 #define LL_LLBUTTON_H
 
+#include "lluuid.h"
+#include "llbadgeowner.h"
 #include "llcontrol.h"
 #include "lluictrl.h"
 #include "v4color.h"
@@ -52,15 +54,13 @@ S32 round_up(S32 grid, S32 value);
 
 
 class LLUICtrlFactory;
-class LLUIImage;
-class LLUUID;
 
 //
 // Classes
 //
 
 class LLButton
-: public LLUICtrl
+: public LLUICtrl, public LLBadgeOwner
 {
 public:
 	struct Params 
@@ -125,7 +125,11 @@ public:
 		Optional<F32>				hover_glow_amount;
 		Optional<TimeIntervalParam>	held_down_delay;
 
-		Optional<bool>			use_draw_context_alpha;
+		Optional<bool>				use_draw_context_alpha;
+		
+		Optional<LLBadge::Params>	badge;
+
+		Optional<bool>				handle_right_mouse;
 
 		Params();
 	};
@@ -249,7 +253,7 @@ public:
 	void			setImageDisabledSelected(LLPointer<LLUIImage> image);
 	void			setImageFlash(LLPointer<LLUIImage> image);
 	void			setImagePressed(LLPointer<LLUIImage> image);
-
+	
 	void			setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
 	BOOL			getCommitOnReturn() const { return mCommitOnReturn; }
 
@@ -357,6 +361,8 @@ private:
 	bool						mForcePressedState;
 
 	LLFrameTimer				mFlashingTimer;
+
+	bool						mHandleRightMouse;
 };
 
 // Build time optimization, generate once in .cpp file
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 9b6830a8163cfab0e9963969c73eb79e38d71cdf..6a91ec56e409232ad9fa465c8373d1a7a10642fc 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -49,6 +49,8 @@ void LLLayoutStack::OrientationNames::declareValues()
 //
 LLLayoutPanel::LLLayoutPanel(const Params& p)	
 :	LLPanel(p),
+	mExpandedMinDimSpecified(false),
+	mExpandedMinDim(p.min_dim),
  	mMinDim(p.min_dim), 
  	mMaxDim(p.max_dim), 
  	mAutoResize(p.auto_resize),
@@ -58,6 +60,13 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
 	mVisibleAmt(1.f), // default to fully visible
 	mResizeBar(NULL) 
 {
+	// Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value
+	if (p.expanded_min_dim.isProvided())
+	{
+		mExpandedMinDimSpecified = true;
+		mExpandedMinDim = p.expanded_min_dim();
+	}
+	
 	// panels initialized as hidden should not start out partially visible
 	if (!getVisible())
 	{
@@ -78,20 +87,20 @@ LLLayoutPanel::~LLLayoutPanel()
 	delete mResizeBar;
 	mResizeBar = NULL;
 }
-	
+
 F32 LLLayoutPanel::getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation)
 {
 	if (orientation == LLLayoutStack::HORIZONTAL)
 	{
 		F32 collapse_amt = 
-		clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinDim / (F32)llmax(1, getRect().getWidth()));
+			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth()));
 		return mVisibleAmt * collapse_amt;
 	}
 	else
 	{
-			F32 collapse_amt = 
-			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinDim / (F32)llmax(1, getRect().getHeight())));
-			return mVisibleAmt * collapse_amt;
+		F32 collapse_amt = 
+			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getHeight())));
+		return mVisibleAmt * collapse_amt;
 	}
 }
 
@@ -182,14 +191,14 @@ BOOL LLLayoutStack::postBuild()
 }
 
 bool LLLayoutStack::addChild(LLView* child, S32 tab_group)
-		{
+{
 	LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child);
-			if (panelp)
-			{
+	if (panelp)
+	{
 		mPanels.push_back(panelp);
-			}
+	}
 	return LLView::addChild(child, tab_group);
-		}
+}
 
 
 S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
@@ -281,9 +290,9 @@ bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp
 {
 	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
 
-	if (panel)
+	if (panel && min_dimp)
 	{
-		if (min_dimp) *min_dimp = panel->mMinDim;
+		*min_dimp = panel->getRelevantMinDim();
 	}
 
 	return NULL != panel;
@@ -316,23 +325,23 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 	e_panel_list_t::iterator panel_it;
 	for (panel_it = mPanels.begin(); panel_it != mPanels.end();	++panel_it)
 	{
-		LLPanel* panelp = (*panel_it);
+		LLLayoutPanel* panelp = (*panel_it);
 		if (panelp->getVisible()) 
 		{
 			if (mAnimate)
 			{
 				if (!mAnimatedThisFrame)
 				{
-					(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant));
-					if ((*panel_it)->mVisibleAmt > 0.99f)
+					panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant));
+					if (panelp->mVisibleAmt > 0.99f)
 					{
-						(*panel_it)->mVisibleAmt = 1.f;
+						panelp->mVisibleAmt = 1.f;
 					}
 				}
 			}
 			else
 			{
-				(*panel_it)->mVisibleAmt = 1.f;
+				panelp->mVisibleAmt = 1.f;
 			}
 		}
 		else // not visible
@@ -341,36 +350,36 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 			{
 				if (!mAnimatedThisFrame)
 				{
-					(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
-					if ((*panel_it)->mVisibleAmt < 0.001f)
+					panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+					if (panelp->mVisibleAmt < 0.001f)
 					{
-						(*panel_it)->mVisibleAmt = 0.f;
+						panelp->mVisibleAmt = 0.f;
 					}
 				}
 			}
 			else
 			{
-				(*panel_it)->mVisibleAmt = 0.f;
+				panelp->mVisibleAmt = 0.f;
 			}
 		}
 
-		if ((*panel_it)->mCollapsed)
+		if (panelp->mCollapsed)
 		{
-			(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+			panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
 		}
 		else
 		{
-			(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+			panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
 		}
 
 		if (mOrientation == HORIZONTAL)
 		{
 			// enforce minimize size constraint by default
-			if (panelp->getRect().getWidth() < (*panel_it)->mMinDim)
+			if (panelp->getRect().getWidth() < panelp->getRelevantMinDim())
 			{
-				panelp->reshape((*panel_it)->mMinDim, panelp->getRect().getHeight());
+				panelp->reshape(panelp->getRelevantMinDim(), panelp->getRect().getHeight());
 			}
-        	total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor(mOrientation));
+        	total_width += llround(panelp->getRect().getWidth() * panelp->getCollapseFactor(mOrientation));
         	// want n-1 panel gaps for n panels
 			if (panel_it != mPanels.begin())
 			{
@@ -380,11 +389,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 		else //VERTICAL
 		{
 			// enforce minimize size constraint by default
-			if (panelp->getRect().getHeight() < (*panel_it)->mMinDim)
+			if (panelp->getRect().getHeight() < panelp->getRelevantMinDim())
 			{
-				panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinDim);
+				panelp->reshape(panelp->getRect().getWidth(), panelp->getRelevantMinDim());
 			}
-			total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor(mOrientation));
+			total_height += llround(panelp->getRect().getHeight() * panelp->getCollapseFactor(mOrientation));
 			if (panel_it != mPanels.begin())
 			{
 				total_height += mPanelSpacing;
@@ -403,34 +412,23 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 			continue;
 		}
 
+		S32 relevant_dimension = (mOrientation == HORIZONTAL) ? (*panel_it)->getRect().getWidth() : (*panel_it)->getRect().getHeight();
+		S32 relevant_min = (*panel_it)->getRelevantMinDim();
+		
 		// if currently resizing a panel or the panel is flagged as not automatically resizing
 		// only track total available headroom, but don't use it for automatic resize logic
 		if ((*panel_it)->mResizeBar->hasMouseCapture() 
 			|| (!(*panel_it)->mAutoResize 
 				&& !force_resize))
 		{
-			if (mOrientation == HORIZONTAL)
-			{
-				shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
-			}
-			else //VERTICAL
-			{
-				shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
-			}
+			shrink_headroom_total += relevant_dimension - relevant_min;
 		}
 		else
 		{
 			num_resizable_panels++;
-			if (mOrientation == HORIZONTAL)
-			{
-				shrink_headroom_available += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
-				shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
-			}
-			else //VERTICAL
-			{
-				shrink_headroom_available += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
-				shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
-			}
+			
+			shrink_headroom_available += relevant_dimension - relevant_min;
+			shrink_headroom_total += relevant_dimension - relevant_min;
 		}
 	}
 
@@ -452,27 +450,28 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 
 	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
 	{
-		LLPanel* panelp = (*panel_it);
+		LLLayoutPanel* panelp = (*panel_it);
 
 		S32 cur_width = panelp->getRect().getWidth();
 		S32 cur_height = panelp->getRect().getHeight();
 		S32 new_width = cur_width;
-		S32 new_height = cur_height; 
+		S32 new_height = cur_height;
+		S32 relevant_min = panelp->getRelevantMinDim();
 
 		if (mOrientation == HORIZONTAL)
 		{
-			new_width = llmax((*panel_it)->mMinDim, new_width);
+			new_width = llmax(relevant_min, new_width);
 		}
 		else
 		{
-			new_height = llmax((*panel_it)->mMinDim, new_height);
+			new_height = llmax(relevant_min, new_height);
 		}
 		S32 delta_size = 0;
 
 		// if panel can automatically resize (not animating, and resize flag set)...
-		if ((*panel_it)->getCollapseFactor(mOrientation) == 1.f 
-			&& (force_resize || (*panel_it)->mAutoResize) 
-			&& !(*panel_it)->mResizeBar->hasMouseCapture()) 
+		if (panelp->getCollapseFactor(mOrientation) == 1.f 
+			&& (force_resize || panelp->mAutoResize) 
+			&& !panelp->mResizeBar->hasMouseCapture()) 
 		{
 			if (mOrientation == HORIZONTAL)
 			{
@@ -481,8 +480,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 				{
 					// shrink proportionally to amount over minimum
 					// so we can do this in one pass
-					delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
-					shrink_headroom_available -= (cur_width - (*panel_it)->mMinDim);
+					delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - relevant_min) / (F32)shrink_headroom_available)) : 0;
+					shrink_headroom_available -= (cur_width - relevant_min);
 				}
 				else
 				{
@@ -491,7 +490,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 					num_resizable_panels--;
 				}
 				pixels_to_distribute -= delta_size;
-				new_width = llmax((*panel_it)->mMinDim, cur_width + delta_size);
+				new_width = llmax(relevant_min, cur_width + delta_size);
 			}
 			else
 			{
@@ -504,8 +503,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 				{
 					// shrink proportionally to amount over minimum
 					// so we can do this in one pass
-					delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
-					shrink_headroom_available -= (cur_height - (*panel_it)->mMinDim);
+					delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - relevant_min) / (F32)shrink_headroom_available)) : 0;
+					shrink_headroom_available -= (cur_height - relevant_min);
 				}
 				else
 				{
@@ -513,7 +512,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 					num_resizable_panels--;
 				}
 				pixels_to_distribute -= delta_size;
-				new_height = llmax((*panel_it)->mMinDim, cur_height + delta_size);
+				new_height = llmax(relevant_min, cur_height + delta_size);
 			}
 			else
 			{
@@ -566,19 +565,20 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
 	LLLayoutPanel* last_resizeable_panel = NULL;
 	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
 	{
-		LLPanel* panelp = (*panel_it);
+		LLLayoutPanel* panelp = (*panel_it);
+		S32 relevant_min = panelp->getRelevantMinDim();
 
 		if (mOrientation == HORIZONTAL)
 		{
 			(*panel_it)->mResizeBar->setResizeLimits(
-				(*panel_it)->mMinDim, 
-				(*panel_it)->mMinDim + shrink_headroom_total);
+				relevant_min, 
+				relevant_min + shrink_headroom_total);
 		}
 		else //VERTICAL
 		{
 			(*panel_it)->mResizeBar->setResizeLimits(
-				(*panel_it)->mMinDim, 
-				(*panel_it)->mMinDim + shrink_headroom_total);
+				relevant_min, 
+				relevant_min + shrink_headroom_total);
 		}
 
 		// toggle resize bars based on panel visibility, resizability, etc
@@ -658,7 +658,7 @@ void LLLayoutStack::calcMinExtents()
 	{
 		if (mOrientation == HORIZONTAL)
 		{
-            mMinWidth += (*panel_it)->mMinDim;
+            mMinWidth += (*panel_it)->getRelevantMinDim();
 			if (panel_it != mPanels.begin())
 			{
 				mMinWidth += mPanelSpacing;
@@ -666,7 +666,7 @@ void LLLayoutStack::calcMinExtents()
 		}
 		else //VERTICAL
 		{
-			mMinHeight += (*panel_it)->mMinDim;
+			mMinHeight += (*panel_it)->getRelevantMinDim();
 			if (panel_it != mPanels.begin())
 			{
 				mMinHeight += mPanelSpacing;
@@ -688,7 +688,7 @@ void LLLayoutStack::createResizeBars()
 			LLResizeBar::Params resize_params;
 			resize_params.name("resize");
 			resize_params.resizing_view(lp);
-			resize_params.min_size(lp->mMinDim);
+			resize_params.min_size(lp->getRelevantMinDim());
 			resize_params.side(side);
 			resize_params.snapping_enabled(false);
 			LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 4ac8ef0ee9a66ccd299d56fbf85bcabd293bd9e9..d8ef0aeaca39c274a5c7ff7e8dc9b2fd12405a52 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -30,10 +30,10 @@
 
 #include "llpanel.h"
 
-class LLPanel;
 
 class LLLayoutPanel;
 
+
 class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
 {
 public:
@@ -149,6 +149,7 @@ private:
 	F32 mCloseTimeConstant;
 }; // end class LLLayoutStack
 
+
 class LLLayoutPanel : public LLPanel
 {
 friend class LLLayoutStack;
@@ -156,13 +157,15 @@ friend class LLUICtrlFactory;
 public:
 	struct Params : public LLInitParam::Block<Params, LLPanel::Params>
 	{
-		Optional<S32>			min_dim,
+		Optional<S32>			expanded_min_dim,
+								min_dim,
 								max_dim;
 		Optional<bool>			user_resize,
 								auto_resize;
 
 		Params()
-		:	min_dim("min_dim", 0),
+		:	expanded_min_dim("expanded_min_dim", 0),
+			min_dim("min_dim", 0),
 			max_dim("max_dim", 0),
 			user_resize("user_resize", true),
 			auto_resize("auto_resize", true)
@@ -177,15 +180,36 @@ public:
 	~LLLayoutPanel();
 
 	void initFromParams(const Params& p);
-	void setMinDim(S32 value) { mMinDim = value; }
+
+	S32 getMinDim() const { return mMinDim; }
+	void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; }
+
+	S32 getMaxDim() const { return mMaxDim; }
 	void setMaxDim(S32 value) { mMaxDim = value; }
 
-protected:
-	LLLayoutPanel(const Params& p)	;
+	S32 getExpandedMinDim() const { return mExpandedMinDim; }
+	void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; }
+	
+	S32 getRelevantMinDim() const
+	{
+		S32 min_dim = mMinDim;
+		
+		if (!mCollapsed)
+		{
+			min_dim = mExpandedMinDim;
+		}
+		
+		return min_dim;
+	}
 
+protected:
+	LLLayoutPanel(const Params& p);
 	
 	F32 getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation);
 
+	bool mExpandedMinDimSpecified;
+	S32 mExpandedMinDim;
+	
 	S32 mMinDim;
 	S32 mMaxDim;
 	BOOL mAutoResize;
diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h
index 4c47cc267cc96df4da59b263d4e6d51cd63f7d7c..7c444788483bd898c6d4a0d7eb6c0cecd8d37b4f 100644
--- a/indra/llui/llloadingindicator.h
+++ b/indra/llui/llloadingindicator.h
@@ -86,6 +86,8 @@ public:
 	 */
 	void start();
 
+	void reset() { mCurImageIdx = 0; }
+
 private:
 	LLLoadingIndicator(const Params&);
 	void initFromParams(const Params&);
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index b2383106a86c05cbbeddb602237c95bce6beb51b..1dcdd79efae5cd37e7ae925ec8871e490e4f52d3 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -87,7 +87,8 @@ LLPanel::Params::Params()
 	filename("filename"),
 	class_name("class"),
 	help_topic("help_topic"),
-	visible_callback("visible_callback")
+	visible_callback("visible_callback"),
+	accepts_badge("accepts_badge")
 {
 	name = "panel";
 	addSynonym(background_visible, "bg_visible");
@@ -113,7 +114,8 @@ LLPanel::LLPanel(const LLPanel::Params& p)
 	mCommitCallbackRegistrar(false),
 	mEnableCallbackRegistrar(false),
 	mXMLFilename(p.filename),
-	mVisibleSignal(NULL)
+	mVisibleSignal(NULL),
+	mAcceptsBadge(p.accepts_badge)
 	// *NOTE: Be sure to also change LLPanel::initFromParams().  We have too
 	// many classes derived from LLPanel to retrofit them all to pass in params.
 {
@@ -485,6 +487,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
 	mBgAlphaImage = p.bg_alpha_image();
 	mBgOpaqueImageOverlay = p.bg_opaque_image_overlay;
 	mBgAlphaImageOverlay = p.bg_alpha_image_overlay;
+
+	mAcceptsBadge = p.accepts_badge;
 }
 
 static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 7bbbeaf709cacfa8f93c5cff9623ebd53d3f1bac..67674fab7e9ca9f56727787907585f1c7392d796 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -89,6 +89,8 @@ public:
 		Multiple<LocalizedString>	strings;
 		
 		Optional<CommitCallbackParam> visible_callback;
+
+		Optional<bool>			accepts_badge;
 		
 		Params();
 	};
@@ -250,6 +252,8 @@ public:
 	
 	boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb );
 
+	bool acceptsBadge() const { return mAcceptsBadge; }
+
 protected:
 	// Override to set not found list
 	LLButton*		getDefaultButton() { return mDefaultBtn; }
@@ -264,6 +268,7 @@ protected:
 	static factory_stack_t	sFactoryStack;
 	
 private:
+	bool			mAcceptsBadge;
 	BOOL			mBgVisible;				// any background at all?
 	BOOL			mBgOpaque;				// use opaque color or image
 	LLUIColor		mBgOpaqueColor;
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 0a06b5e74f6b38480b9f1e3df73b9fd69687c2a8..d58df5801bec40247347736bd5e2cf9bb793dad4 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -68,6 +68,7 @@ LLUICtrl::ControlVisibility::ControlVisibility()
 LLUICtrl::Params::Params()
 :	tab_stop("tab_stop", true),
 	chrome("chrome", false),
+	requests_front("requests_front", false),
 	label("label"),
 	initial_value("value"),
 	init_callback("init_callback"),
@@ -96,9 +97,10 @@ const LLUICtrl::Params& LLUICtrl::getDefaultParams()
 
 LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel) 
 :	LLView(p),
-	mTentative(FALSE),
 	mIsChrome(FALSE),
+	mRequestsFront(p.requests_front),
 	mTabStop(FALSE),
+	mTentative(FALSE),
     mViewModel(viewmodel),
 	mControlVariable(NULL),
 	mEnabledControlVariable(NULL),
@@ -123,6 +125,8 @@ void LLUICtrl::initFromParams(const Params& p)
 {
 	LLView::initFromParams(p);
 
+	mRequestsFront = p.requests_front;
+
 	setIsChrome(p.chrome);
 	setControlName(p.control_name);
 	if(p.enabled_controls.isProvided())
@@ -403,6 +407,36 @@ LLViewModel* LLUICtrl::getViewModel() const
 	return mViewModel;
 }
 
+//virtual
+BOOL LLUICtrl::postBuild()
+{
+	//
+	// Find all of the children that want to be in front and move them to the front
+	//
+
+	if (getChildCount() > 0)
+	{
+		std::vector<LLUICtrl*> childrenToMoveToFront;
+
+		for (LLView::child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it)
+		{
+			LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(*child_it);
+
+			if (uictrl && uictrl->mRequestsFront)
+			{
+				childrenToMoveToFront.push_back(uictrl);
+			}
+		}
+
+		for (std::vector<LLUICtrl*>::iterator it = childrenToMoveToFront.begin(); it != childrenToMoveToFront.end(); ++it)
+		{
+			sendChildToFront(*it);
+		}
+	}
+
+	return LLView::postBuild();
+}
+
 bool LLUICtrl::setControlValue(const LLSD& value)
 {
 	if (mControlVariable)
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index b37e9f6b1b4d5818a811b91db300e26e4aac6a9c..09bed9b958e896c9a7bfba6bd7111bbc087f2aee 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -94,7 +94,8 @@ public:
 	{
 		Optional<std::string>			label;
 		Optional<bool>					tab_stop,
-										chrome;
+										chrome,
+										requests_front;
 		Optional<LLSD>					initial_value;
 
 		Optional<CommitCallbackParam>	init_callback,
@@ -143,6 +144,8 @@ protected:
 	virtual LLViewModel* getViewModel() const;
     // We shouldn't ever need to set this directly
     //virtual void    setViewModel(const LLViewModelPtr&);
+
+	virtual BOOL	postBuild();
 	
 public:
 	// LLView interface
@@ -301,8 +304,9 @@ protected:
 
 private:
 
-	BOOL			mTabStop;
 	BOOL			mIsChrome;
+	BOOL			mRequestsFront;
+	BOOL			mTabStop;
 	BOOL			mTentative;
 	LLRootHandle<LLUICtrl> mUICtrlHandle;
 
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 245126d1780c1e3b71369372746bc42e181c72e8..8803d106ba2c0cd16ccf42797d0583156614b717 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1299,15 +1299,7 @@ void LLView::drawChildren()
 {
 	if (!mChildList.empty())
 	{
-		static const LLRect* rootRect = NULL;
-		
-		if (!mParentView)
-		{
-			rootRect = &mRect;
-		}
-
-		LLRect screenRect;
-
+		LLView* rootp = LLUI::getRootView();		
 		++sDepth;
 
 		for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();)  // ++child_iter)
@@ -1317,9 +1309,8 @@ void LLView::drawChildren()
 
 			if (viewp->getVisible() && viewp->getRect().isValid())
 			{
-				// Only draw views that are within the root view
-				localRectToScreen(viewp->getRect(),&screenRect);
-				if ( rootRect->overlaps(screenRect)  && LLUI::sDirtyRect.overlaps(screenRect))
+				LLRect screen_rect = viewp->calcScreenRect();
+				if ( rootp->getLocalRect().overlaps(screen_rect)  && LLUI::sDirtyRect.overlaps(screen_rect))
 				{
 					LLUI::pushMatrix();
 					{
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index e09ef33d4911d8e5bca022eabbcead4e4f1baac7..3cd61e574e68e6191614e51a5a709e23717be044 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -95,7 +95,7 @@ namespace LLInitParam
 	{
 		const U8* my_addr = reinterpret_cast<const U8*>(this);
 		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
-		mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+		mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr));
 	}
 
 	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; }
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index b3312798dddc283e6c000e8a3ed05be928d6afdb..c024fd405e7c947dd5d9de13d66b226b84eafeb4 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -40,7 +40,7 @@ namespace LLInitParam
 	{
 		const U8* my_addr = reinterpret_cast<const U8*>(this);
 		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
-		mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+		mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr));
 	}
 
 	//
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index a853999e9456d7112d2dcf7ab94191ccf020a803..35c889b69fa2704cade2036f3493c96ead61f7ef 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -34,6 +34,8 @@
 #include <boost/unordered_map.hpp>
 #include <boost/shared_ptr.hpp>
 
+#include "llerror.h"
+
 namespace LLInitParam
 {
 	template<typename T> const T& defaultValue() { static T value; return value; }
@@ -302,8 +304,9 @@ namespace LLInitParam
 	private:
 		friend class BaseBlock;
 
-		U16			mEnclosingBlockOffset;
-		bool		mIsProvided;
+		U32		mEnclosingBlockOffset:31;
+		U32		mIsProvided:1;
+
 	};
 
 	// various callbacks and constraints associated with an individual param
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index 27f3c7260e318312980441b6753e6123d46c3d34..fca071c628ed75a15d2d96ec3ea85299466e6329 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -1168,19 +1168,11 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
 				authResponse(message_in);
 			}
 			else
-			if(message_name == "js_expose_object")
+			if(message_name == "js_enable_object")
 			{
 #if LLQTWEBKIT_API_VERSION >= 9
-				bool expose_object = message_in.getValueBoolean( "expose" );
-				LLQtWebKit::getInstance()->setExposeObject( expose_object );
-#endif
-			}
-			else
-			if(message_name == "js_values_valid")
-			{
-#if LLQTWEBKIT_API_VERSION >= 9
-				bool valid = message_in.getValueBoolean( "valid" );
-				LLQtWebKit::getInstance()->setValuesValid( valid );
+				bool enable = message_in.getValueBoolean( "enable" );
+				LLQtWebKit::getInstance()->setSLObjectEnabled( enable );
 #endif
 			}
 			else
@@ -1191,6 +1183,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
 				F32 y = message_in.getValueReal("y");
 				F32 z = message_in.getValueReal("z");
 				LLQtWebKit::getInstance()->setAgentLocation( x, y, z );
+				LLQtWebKit::getInstance()->emitLocation();
 #endif
 			}
 			else
@@ -1201,6 +1194,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
 				F32 y = message_in.getValueReal("y");
 				F32 z = message_in.getValueReal("z");
 				LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z );
+				LLQtWebKit::getInstance()->emitLocation();
 #endif
 			}
 			else			
@@ -1209,6 +1203,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
 #if LLQTWEBKIT_API_VERSION >= 9
 				F32 angle = message_in.getValueReal("angle");
 				LLQtWebKit::getInstance()->setAgentOrientation( angle );
+				LLQtWebKit::getInstance()->emitLocation();
 #endif
 			}
 			else
@@ -1217,14 +1212,25 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
 #if LLQTWEBKIT_API_VERSION >= 9
 				const std::string& region = message_in.getValue("region");
 				LLQtWebKit::getInstance()->setAgentRegion( region );
+				LLQtWebKit::getInstance()->emitLocation();
 #endif
 			}
 			else
-			if(message_name == "js_agent_maturity")
+				if(message_name == "js_agent_maturity")
+				{
+#if LLQTWEBKIT_API_VERSION >= 9
+					const std::string& maturity = message_in.getValue("maturity");
+					LLQtWebKit::getInstance()->setAgentMaturity( maturity );
+					LLQtWebKit::getInstance()->emitMaturity();
+#endif
+				}
+			else
+			if(message_name == "js_agent_language")
 			{
 #if LLQTWEBKIT_API_VERSION >= 9
-				const std::string& maturity = message_in.getValue("maturity");
-				LLQtWebKit::getInstance()->setAgentMaturity( maturity );
+				const std::string& language = message_in.getValue("language");
+				LLQtWebKit::getInstance()->setAgentLanguage( language );
+				LLQtWebKit::getInstance()->emitLanguage();
 #endif
 			}
 			else
@@ -1384,3 +1390,5 @@ int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void
 
 	return 0;
 }
+
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 367d3de0c9690d43470f5448b3d4b44652d2a9cc..da9a14542345938a7c7ab6fd237d96aa188c2fe2 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -363,6 +363,9 @@ set(viewer_SOURCE_FILES
     llpanellogin.cpp
     llpanelloginlistener.cpp
     llpanelmaininventory.cpp
+    llpanelmarketplaceinbox.cpp
+    llpanelmarketplaceinboxinventory.cpp
+    llpanelmarketplaceoutbox.cpp
     llpanelmediasettingsgeneral.cpp
     llpanelmediasettingspermissions.cpp
     llpanelmediasettingssecurity.cpp
@@ -913,6 +916,9 @@ set(viewer_HEADER_FILES
     llpanellogin.h
     llpanelloginlistener.h
     llpanelmaininventory.h
+    llpanelmarketplaceinbox.h
+    llpanelmarketplaceinboxinventory.h
+    llpanelmarketplaceoutbox.h
     llpanelmediasettingsgeneral.h
     llpanelmediasettingspermissions.h
     llpanelmediasettingssecurity.h
@@ -1470,7 +1476,7 @@ set(PACKAGE ON CACHE BOOL
     "Add a package target that builds an installer package.")
 
 if (WINDOWS)
-	set_target_properties(${VIEWER_BINARY_NAME}
+    set_target_properties(${VIEWER_BINARY_NAME}
         PROPERTIES
         # *TODO -reenable this once we get server usage sorted out
         #LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\""
diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/keys.xml
index d085475c6ca009d262a84094bf9adb1c8ba72ff7..6e3673e7d968fa9dae733c0340932d87de717dd1 100644
--- a/indra/newview/app_settings/keys.xml
+++ b/indra/newview/app_settings/keys.xml
@@ -181,7 +181,7 @@
     <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
   </third_person>
 
-  # Basic editing camera control
+  <!-- Basic editing camera control -->
   <edit>
     <binding key="A" mask="NONE" command="spin_around_cw"/>
     <binding key="D" mask="NONE" command="spin_around_ccw"/>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 01daf1ceb2d59f20b5e45e2f38b2808b1c643176..4b62e376b5dea3fdd972424acc5d89165fef51cd 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4179,6 +4179,28 @@
       <string>F32</string>
       <key>Value</key>
       <real>1.0</real>
+    </map>
+    <key>InventoryDisplayInbox</key>
+    <map>
+        <key>Comment</key>
+        <string>Override received items inventory inbox display</string>
+        <key>Persist</key>
+        <integer>0</integer>
+        <key>Type</key>
+        <string>Boolean</string>
+        <key>Value</key>
+        <integer>0</integer>
+    </map>
+    <key>InventoryDisplayOutbox</key>
+    <map>
+        <key>Comment</key>
+        <string>Override merchant inventory outbox display</string>
+        <key>Persist</key>
+        <integer>0</integer>
+        <key>Type</key>
+        <string>Boolean</string>
+        <key>Value</key>
+        <integer>0</integer>
     </map>
 	<key>InventoryLinking</key>
 	<map>
@@ -4422,6 +4444,17 @@
       <key>Value</key>
         <real>2.0</real>
     </map>
+    <key>LastInventoryInboxExpand</key>
+    <map>
+        <key>Comment</key>
+        <string>The last time the received items inbox was expanded.</string>
+        <key>Persist</key>
+        <integer>1</integer>
+        <key>Type</key>
+        <string>String</string>
+        <key>Value</key>
+        <string />
+    </map>
     <key>LCDDestination</key>
     <map>
       <key>Comment</key>
@@ -6546,7 +6579,28 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-
+   <key>PostFirstLoginIntroURL</key>
+   <map>
+     <key>Comment</key>
+     <string>URL of intro presenatation after first time users first login</string>
+     <key>Persist</key>
+     <integer>1</integer>
+     <key>Type</key>
+     <string>String</string>
+     <key>Value</key>
+     <string></string>
+   </map>
+  <key>PostFirstLoginIntroViewed</key>
+  <map>
+    <key>Comment</key>
+    <string>Flag indicating if user has seen intro presenatation after first time users first login</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <string>0</string>
+  </map>
     <key>PrecachingDelay</key>
     <map>
       <key>Comment</key>
@@ -7182,7 +7236,7 @@
     </array>
   </map>
 
-  <key>RenderAnisotropic</key>
+    <key>RenderAnisotropic</key>
     <map>
       <key>Comment</key>
       <string>Render textures using anisotropic filtering</string>
@@ -9627,7 +9681,7 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>0</integer>
+      <integer>1</integer>
     </map>
     <key>ShowSnapshotButton</key>
     <map>
@@ -13346,5 +13400,43 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+     <key>WebProfileRect</key>
+    <map>
+      <key>Comment</key>
+      <string>Web profile dimensions</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Rect</string>
+      <key>Value</key>
+      <array>
+        <integer>0</integer>
+        <integer>650</integer>
+        <integer>490</integer>
+        <integer>0</integer>
+      </array>    
+    </map>
+   <key>HelpFloaterOpen</key>
+    <map>
+      <key>Comment</key>
+      <string>Show Help Floater on login?</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+     <key>ShowHelpOnFirstLogin</key>
+    <map>
+      <key>Comment</key>
+      <string>Show Help Floater on first login</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
 </map>
 </llsd>
diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml
index 70a75cb4ca96adb551d5b9eacd185080c5e85f90..29e52ab054ae5c2e427e55064799c1a3bb8223b1 100644
--- a/indra/newview/app_settings/settings_minimal.xml
+++ b/indra/newview/app_settings/settings_minimal.xml
@@ -459,5 +459,16 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-  </map>
+    <key>ShowHelpOnFirstLogin</key>
+    <map>
+      <key>Comment</key>
+      <string>Show Help Floater on first login</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    </map>
 </llsd>
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index d426afb17cc23af8b547dea7f1631cd63d5bbadb..36272f0c7ca3c0abf52f99bb9a203a4901c967f5 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -33,7 +33,6 @@
 #include "llagentwearablesfetch.h"
 #include "llappearancemgr.h"
 #include "llcallbacklist.h"
-#include "llfolderview.h"
 #include "llgesturemgr.h"
 #include "llinventorybridge.h"
 #include "llinventoryfunctions.h"
@@ -45,6 +44,7 @@
 #include "llsidepanelappearance.h"
 #include "llsidetray.h"
 #include "lltexlayer.h"
+#include "lltooldraganddrop.h"
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
 #include "llwearable.h"
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 955f19c82c64de7fcd28cae540d3d92a8bff6901..8344b08bfb24c5e6e6ef004580ec9886c4cef1bd 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -49,6 +49,7 @@
 #include "llfloaterpay.h"
 #include "llfloaterwebcontent.h"
 #include "llfloaterworldmap.h"
+#include "llfolderview.h"
 #include "llgiveinventory.h"
 #include "llinventorybridge.h"
 #include "llinventorymodel.h"	// for gInventory.findCategoryUUIDForType
@@ -69,6 +70,7 @@
 #include "lltrans.h"
 #include "llcallingcard.h"
 #include "llslurl.h"			// IDEVO
+#include "llsidepanelinventory.h"
 
 // static
 void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
@@ -312,7 +314,9 @@ static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarNa
 	std::string url = getProfileURL(username);
 
 	// PROFILES: open in webkit window
-	LLWeb::loadWebURLInternal(url, "", agent_id.asString());
+	const bool show_chrome = false;
+	static LLCachedControl<LLRect> profile_rect(gSavedSettings, "WebProfileRect");
+	LLFloaterWebContent::create(url, "", agent_id.asString(), show_chrome, profile_rect);
 }
 
 // static
@@ -444,8 +448,6 @@ void LLAvatarActions::share(const LLUUID& id)
 
 namespace action_give_inventory
 {
-	typedef std::set<LLUUID> uuid_set_t;
-
 	/**
 	 * Returns a pointer to 'Add More' inventory panel of Edit Outfit SP.
 	 */
@@ -475,18 +477,16 @@ namespace action_give_inventory
 	/**
 	 * Checks My Inventory visibility.
 	 */
+
 	static bool is_give_inventory_acceptable()
 	{
-		LLInventoryPanel* active_panel = get_active_inventory_panel();
-		if (!active_panel) return false;
-
 		// check selection in the panel
-		const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
 		if (inventory_selected_uuids.empty()) return false; // nothing selected
 
 		bool acceptable = false;
-		uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
-		const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+		std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+		const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
 		for (; it != it_end; ++it)
 		{
 			LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
@@ -529,12 +529,12 @@ namespace action_give_inventory
 		}
 	}
 
-	static void build_items_string(const uuid_set_t& inventory_selected_uuids , std::string& items_string)
+	static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
 	{
 		llassert(inventory_selected_uuids.size() > 0);
 
 		const std::string& separator = LLTrans::getString("words_separator");
-		for (uuid_set_t::const_iterator it = inventory_selected_uuids.begin(); ; )
+		for (std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); ; )
 		{
 			LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
 			if (NULL != inv_cat)
@@ -570,10 +570,7 @@ namespace action_give_inventory
 			return;
 		}
 
-		LLInventoryPanel* active_panel = get_active_inventory_panel();
-		if (!active_panel) return;
-
-		const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
 		if (inventory_selected_uuids.empty())
 		{
 			return;
@@ -590,8 +587,8 @@ namespace action_give_inventory
 			// We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710
 			const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid);
 
-			uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
-			const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+			std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+			const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
 
 			const std::string& separator = LLTrans::getString("words_separator");
 			std::string noncopy_item_names;
@@ -654,10 +651,7 @@ namespace action_give_inventory
 	{
 		llassert(avatar_names.size() == avatar_uuids.size());
 
-		LLInventoryPanel* active_panel = get_active_inventory_panel();
-		if (!active_panel) return;
-
-		const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
 		if (inventory_selected_uuids.empty())
 		{
 			return;
@@ -678,6 +672,33 @@ namespace action_give_inventory
 	}
 }
 
+
+
+//static
+std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
+{
+	std::set<LLUUID> inventory_selected_uuids;
+
+	LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
+	if (active_panel)
+	{
+		inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+	}
+
+	if (inventory_selected_uuids.empty())
+	{
+		LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+		LLInventoryPanel * inbox = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+		if (inbox)
+		{
+			inventory_selected_uuids = inbox->getRootFolder()->getSelectionList();
+		}
+
+	}
+
+	return inventory_selected_uuids;
+}
+
 //static
 void LLAvatarActions::shareWithAvatars()
 {
@@ -705,12 +726,12 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL
 
 	// check selection in the panel
 	LLFolderView* root_folder = inv_panel->getRootFolder();
-	const uuid_set_t inventory_selected_uuids = root_folder->getSelectionList();
+	const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList();
 	if (inventory_selected_uuids.empty()) return false; // nothing selected
 
 	bool can_share = true;
-	uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
-	const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+	std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+	const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
 	for (; it != it_end; ++it)
 	{
 		LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 956fed746147e569f5557b5d7c1b55993953b2b8..fbfd815f41174330c57bd5b2923a767b69b8e8f4 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -36,6 +36,7 @@
 
 class LLInventoryPanel;
 
+
 /**
  * Friend-related actions (add, remove, offer teleport, etc)
  */
@@ -196,6 +197,8 @@ public:
 	 */
 	static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL);
 
+	static std::set<LLUUID> getInventorySelectedUUIDs();
+
 private:
 	static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
 	static bool handleRemove(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp
index cd5e779c4d751d6f911a19af41c8f9fdc5a206de..a29ccf2b6ddccd6cd3d396fc64705dd018142e5e 100644
--- a/indra/newview/llfilteredwearablelist.cpp
+++ b/indra/newview/llfilteredwearablelist.cpp
@@ -31,6 +31,7 @@
 #include "llinventoryfunctions.h"
 #include "llinventoryitemslist.h"
 #include "llinventorymodel.h"
+#include "llviewerinventory.h"
 
 
 LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector)
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index 627defd006890cb965fb47f52ccae1cd7d931788..3012638d44ea7450916932c83e5a898ad85568b4 100644
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -71,9 +71,18 @@ void LLFloaterHelpBrowser::buildURLHistory()
 	}
 }
 
+void LLFloaterHelpBrowser::onOpen(const LLSD& key)
+{
+	gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
+}
+
 //virtual
 void LLFloaterHelpBrowser::onClose(bool app_quitting)
 {
+	if (!app_quitting)
+	{
+		gSavedSettings.setBOOL("HelpFloaterOpen", FALSE);
+	}
 	// really really destroy the help browser when it's closed, it'll be recreated.
 	destroy(); // really destroy this dialog on closure, it's relatively heavyweight.
 }
diff --git a/indra/newview/llfloaterhelpbrowser.h b/indra/newview/llfloaterhelpbrowser.h
index 2731c81b9c461e2963ed888ab4b03c66e1f3663f..afe0f4df690b6c868e74a211fead813a60266f1d 100644
--- a/indra/newview/llfloaterhelpbrowser.h
+++ b/indra/newview/llfloaterhelpbrowser.h
@@ -42,6 +42,7 @@ class LLFloaterHelpBrowser :
 
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onClose(bool app_quitting);
+	/*virtual*/ void onOpen(const LLSD& key);
 
 	// inherited from LLViewerMediaObserver
 	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 058567492be7ad57ee9a8a14cfd6b812b3827788..43eecbf0485f1c796f37c2a98e98ec4ac0ec9c3b 100644
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -99,7 +99,7 @@ void LLFloaterWebContent::initializeURLHistory()
 }
 
 //static
-void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid )
+void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid,  bool show_chrome, const LLRect& preferred_media_size)
 {
 	lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl;
 
@@ -155,6 +155,20 @@ void LLFloaterWebContent::create( const std::string &url, const std::string& tar
 		// tell the browser instance to load the specified URL
 		browser->open_media(url, target);
 		LLViewerMedia::proxyWindowOpened(target, uuid);
+
+		browser->getChild<LLLayoutPanel>("status_bar")->setVisible(show_chrome);
+		browser->getChild<LLLayoutPanel>("nav_controls")->setVisible(show_chrome);
+
+		if (!show_chrome)
+		{
+			browser->setResizeLimits(100, 100);
+		}
+
+		if (!preferred_media_size.isEmpty())
+		{
+			//ignore x, y for now
+			browser->geometryChanged(browser->getRect().mLeft, browser->getRect().mBottom, preferred_media_size.getWidth(), preferred_media_size.getHeight());
+		}
 	}
 }
 
@@ -210,7 +224,7 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
 
 	lldebugs << "geometry change: " << geom << llendl;
 
-	handleReshape(geom,false);
+	setShape(geom);
 }
 
 void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target)
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index ecc7e970d865c5ac94f181abe08224e0962cdf7b..56b6ef12c8ea30b7f38a6750359ee34d6848d9d6 100644
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -46,7 +46,7 @@ public:
 
 	void initializeURLHistory();
 
-	static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null);
+	static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null, bool show_chrome = true, const LLRect& preferred_media_size = LLRect() );
 
 	static void closeRequest(const std::string &uuid);
 	static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 3884b94b60e18a0a2fbf06d7b2860277dd482f51..e90b6c1c3d720411d1b308f202e6b598079a2c3c 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -167,13 +167,23 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
 ///----------------------------------------------------------------------------
 /// Class LLFolderView
 ///----------------------------------------------------------------------------
+LLFolderView::Params::Params()
+:	task_id("task_id"),
+	title("title"),
+	use_label_suffix("use_label_suffix"),
+	allow_multiselect("allow_multiselect", true),
+	show_load_status("show_load_status", true),
+	use_ellipses("use_ellipses", false)
+{
+}
+
 
 // Default constructor
 LLFolderView::LLFolderView(const Params& p)
 :	LLFolderViewFolder(p),
 	mScrollContainer( NULL ),
 	mPopupMenuHandle(),
-	mAllowMultiSelect(TRUE),
+	mAllowMultiSelect(p.allow_multiselect),
 	mShowFolderHierarchy(FALSE),
 	mSourceID(p.task_id),
 	mRenameItem( NULL ),
@@ -194,10 +204,14 @@ LLFolderView::LLFolderView(const Params& p)
 	mDragAndDropThisFrame(FALSE),
 	mCallbackRegistrar(NULL),
 	mParentPanel(p.parent_panel),
-	mUseEllipses(false),
+	mUseEllipses(p.use_ellipses),
 	mDraggingOverItem(NULL),
 	mStatusTextBox(NULL)
 {
+	mRoot = this;
+
+	mShowLoadStatus = p.show_load_status();
+
 	LLRect rect = p.rect;
 	LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);
 	setRect( rect );
@@ -263,6 +277,7 @@ LLFolderView::LLFolderView(const Params& p)
 	menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
 	mPopupMenuHandle = menu->getHandle();
 
+	mListener->openItem();
 }
 
 // Destroys the object
@@ -308,15 +323,10 @@ void LLFolderView::setSortOrder(U32 order)
 	if (order != mSortOrder)
 	{
 		LLFastTimer t(FTM_SORT);
+		
 		mSortOrder = order;
 
-		for (folders_t::iterator iter = mFolders.begin();
-			 iter != mFolders.end();)
-		{
-			folders_t::iterator fit = iter++;
-			(*fit)->sortBy(order);
-		}
-
+		sortBy(order);
 		arrangeAll();
 	}
 }
@@ -342,7 +352,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
 	{
 		recursiveIncrementNumDescendantsSelected(folder->numSelected());
 	}
-	folder->setShowLoadStatus(true);
+	folder->setShowLoadStatus(mShowLoadStatus);
 	folder->setOrigin(0, 0);
 	folder->reshape(getRect().getWidth(), 0);
 	folder->setVisible(FALSE);
@@ -424,11 +434,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen
 									(folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
 		}
 
-		// Need to call arrange regardless of visibility, since children's visibility
-		// might need to be changed too (e.g. even though a folder is invisible, its
-		// children also need to be set invisible for state-tracking purposes, e.g.
-		// llfolderviewitem::filter).
-		// if (folderp->getVisible())
+		if (folderp->getVisible())
 		{
 			S32 child_height = 0;
 			S32 child_width = 0;
@@ -764,7 +770,7 @@ void LLFolderView::sanitizeSelection()
 		}
 
 		// Don't allow invisible items (such as root folders) to be selected.
-		if (item->getHidden())
+		if (item == getRoot())
 		{
 			items_to_remove.push_back(item);
 		}
@@ -787,7 +793,7 @@ void LLFolderView::sanitizeSelection()
 				parent_folder;
 				parent_folder = parent_folder->getParentFolder())
 			{
-				if (parent_folder->potentiallyVisible() && !parent_folder->getHidden())
+				if (parent_folder->potentiallyVisible())
 				{
 					// give initial selection to first ancestor folder that potentially passes the filter
 					if (!new_selection)
@@ -806,13 +812,7 @@ void LLFolderView::sanitizeSelection()
 		}
 		else
 		{
-			// nothing selected to start with, so pick "My Inventory" as best guess
-			new_selection = getItemByID(gInventory.getRootFolderID());
-			// ... except if it's hidden from the UI.
-			if (new_selection && new_selection->getHidden())
-			{
-				new_selection = NULL;
-			}
+			new_selection = NULL;
 		}
 
 		if (new_selection)
@@ -931,14 +931,15 @@ void LLFolderView::draw()
 		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
 		{
 			mStatusText = LLTrans::getString("Searching");
-			//font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL,  LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
 		}
 		else
 		{
-			LLStringUtil::format_map_t args;
-			args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig());
-			mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args);
-			//font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL,  LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
+			if (getFilter())
+			{
+				LLStringUtil::format_map_t args;
+				args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig());
+				mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args);
+			}
 		}
 		mStatusTextBox->setValue(mStatusText);
 		mStatusTextBox->setVisible( TRUE );
@@ -962,7 +963,9 @@ void LLFolderView::draw()
 		
 	}
 
-	LLFolderViewFolder::draw();
+	// skip over LLFolderViewFolder::draw since we don't want the folder icon, label, 
+	// and arrow for the root folder
+	LLView::draw();
 
 	mDragAndDropThisFrame = FALSE;
 }
@@ -1642,11 +1645,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
 			LLFolderViewItem* parent_folder = last_selected->getParentFolder();
 			if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder())
 			{
-				// Don't change selectin to hidden folder. See EXT-5328.
-				if (!parent_folder->getHidden())
-				{
-					setSelection(parent_folder, FALSE, TRUE);
-				}
+				setSelection(parent_folder, FALSE, TRUE);
 			}
 			else
 			{
@@ -1911,7 +1910,14 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 	// by the folder which is the hierarchy root.
 	if (!handled && !hasVisibleChildren())
 	{
-		handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+		if (mFolders.empty())
+		{
+			handled = handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+		}
+		else
+		{
+			handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+		}
 	}
 
 	if (handled)
@@ -1927,8 +1933,11 @@ void LLFolderView::deleteAllChildren()
 	closeRenamer();
 	LLView::deleteViewByHandle(mPopupMenuHandle);
 	mPopupMenuHandle = LLHandle<LLView>();
-	mRenamer = NULL;
+	mScrollContainer = NULL;
 	mRenameItem = NULL;
+	mRenamer = NULL;
+	mStatusTextBox = NULL;
+	
 	clearSelection();
 	LLView::deleteAllChildren();
 }
@@ -2031,7 +2040,7 @@ void LLFolderView::removeItemID(const LLUUID& id)
 
 LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
 {
-	if (id.isNull())
+	if (id == getListener()->getUUID())
 	{
 		return this;
 	}
@@ -2048,7 +2057,7 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
 
 LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id)
 {
-	if (id.isNull())
+	if (id == getListener()->getUUID())
 	{
 		return this;
 	}
@@ -2173,7 +2182,7 @@ void LLFolderView::doIdle()
 	// filter to determine visiblity before arranging
 	filterFromRoot();
 
-	// automatically show matching items, and select first one
+	// automatically show matching items, and select first one if we had a selection
 	// do this every frame until user puts keyboard focus into the inventory window
 	// signaling the end of the automatic update
 	// only do this when mNeedsFilter is set, meaning filtered items have
@@ -2183,7 +2192,7 @@ void LLFolderView::doIdle()
 		LLFastTimer t3(FTM_AUTO_SELECT);
 		// select new item only if a filtered item not currently selected
 		LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
-		if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride)
+		if ((selected_itemp && !selected_itemp->getFiltered()) && !mAutoSelectOverride)
 		{
 			// select first filtered item
 			LLSelectFirstFilteredItem filter;
@@ -2496,11 +2505,6 @@ BOOL LLFolderView::isFilterModified()
 	return mFilter->isNotDefault();
 }
 
-BOOL LLFolderView::getAllowMultiSelect()
-{
-	return mAllowMultiSelect;
-}
-
 void delete_selected_item(void* user_data)
 {
 	if(user_data)
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 1464a058d8c6cef20e415263502262757b5b9177..0b92548fd0f76737a0cf71a6ed35e58a32ee4dad 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -58,22 +58,6 @@ class LLScrollContainer;
 class LLUICtrl;
 class LLTextBox;
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFolderViewFunctor
-//
-// Simple abstract base class for applying a functor to folders and
-// items in a folder view hierarchy. This is suboptimal for algorithms
-// that only work folders or only work on items, but I'll worry about
-// that later when it's determined to be too slow.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLFolderViewFunctor
-{
-public:
-	virtual ~LLFolderViewFunctor() {}
-	virtual void doFolder(LLFolderViewFolder* folder) = 0;
-	virtual void doItem(LLFolderViewItem* item) = 0;
-};
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLFolderView
 //
@@ -89,7 +73,12 @@ public:
 		Mandatory<LLPanel*>	    parent_panel;
 		Optional<LLUUID>        task_id;
 		Optional<std::string>   title;
-		Optional<bool>			use_label_suffix;
+		Optional<bool>			use_label_suffix,
+								allow_multiselect,
+								show_load_status,
+								use_ellipses;
+
+		Params();
 	};
 	LLFolderView(const Params&);
 	virtual ~LLFolderView( void );
@@ -102,7 +91,6 @@ public:
 	// and resort the items if necessary.
 	void setSortOrder(U32 order);
 	void setFilterPermMask(PermissionMask filter_perm_mask);
-	void setAllowMultiSelect(BOOL allow) { mAllowMultiSelect = allow; }
 	
 	typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;
 	void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }
@@ -117,7 +105,6 @@ public:
 	//LLInventoryFilter::EFolderShow getShowFolderState();
 	U32 getSortOrder() const;
 	BOOL isFilterModified();
-	BOOL getAllowMultiSelect();
 
 	// Close all folders in the view
 	void closeAllFolders();
@@ -238,7 +225,6 @@ public:
 	void setShowSingleSelection(BOOL show);
 	BOOL getShowSingleSelection() { return mShowSingleSelection; }
 	F32  getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
-	void setUseEllipses(bool use_ellipses) { mUseEllipses = use_ellipses; }
 	bool getUseEllipses() { return mUseEllipses; }
 
 	void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index e9d1ad3a9e306e7b6dbe398eb4bd54d0fb66438e..6e4f55fb2f087259c3077554dc782f09da265f36 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -30,8 +30,10 @@
 // viewer includes
 #include "llfolderview.h"		// Items depend extensively on LLFolderViews
 #include "llfoldervieweventlistener.h"
+#include "llviewerfoldertype.h"
 #include "llinventorybridge.h"	// for LLItemBridge in LLInventorySort::operator()
 #include "llinventoryfilter.h"
+#include "llinventoryfunctions.h"
 #include "llinventorymodelbackgroundfetch.h"
 #include "llpanel.h"
 #include "llviewercontrol.h"	// gSavedSettings
@@ -130,10 +132,14 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
 	mIconOpen(p.icon_open),
 	mIconOverlay(p.icon_overlay),
 	mListener(p.listener),
-	mHidden(false),
 	mShowLoadStatus(false)
+{
+}
+
+BOOL LLFolderViewItem::postBuild()
 {
 	refresh();
+	return TRUE;
 }
 
 // Destroys the object
@@ -195,7 +201,7 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)
 	LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );
 
 	// Skip over items that are invisible or are hidden from the UI.
-	while(itemp && (!itemp->getVisible() || itemp->getHidden()))
+	while(itemp && !itemp->getVisible())
 	{
 		LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );
 		if (itemp == next_itemp) 
@@ -351,7 +357,10 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,
 									 BOOL take_keyboard_focus)
 {
 	LLFolderView* root = getRoot();
+	if (getParentFolder())
+	{
 	getParentFolder()->requestArrange();
+	}
 	if(set_selection)
 	{
 		setSelectionFromRoot(this, TRUE, take_keyboard_focus);
@@ -442,23 +451,20 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
 
 S32 LLFolderViewItem::getItemHeight()
 {
-	if (getHidden()) return 0;
-
 	return mItemHeight;
 }
 
 void LLFolderViewItem::filter( LLInventoryFilter& filter)
 {
 	const BOOL previous_passed_filter = mPassedFilter;
-	const BOOL passed_filter = mListener && filter.check(this);
+	const BOOL passed_filter = filter.check(this);
 
 	// If our visibility will change as a result of this filter, then
 	// we need to be rearranged in our parent folder
 	if (mParentFolder)
 	{
-		if (getVisible() != passed_filter)
-			mParentFolder->requestArrange();
-		if (passed_filter != previous_passed_filter)
+		if (getVisible() != passed_filter
+			||	previous_passed_filter != passed_filter )
 			mParentFolder->requestArrange();
 	}
 
@@ -863,11 +869,6 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 
 void LLFolderViewItem::draw()
 {
-	if (getHidden())
-	{
-		return;
-	}
-
 	static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
 	static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
 	static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
@@ -891,8 +892,8 @@ void LLFolderViewItem::draw()
 	// Draw open folder arrow
 	//
 	const bool up_to_date = mListener && mListener->isUpToDate();
-	const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) || // we fetched our children and some of them have passed the filter...
-										(!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter)
+	const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter...
+										|| (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter)
 	if (possibly_has_children)
 	{
 		LLUIImage* arrow_image = default_params.folder_arrow_image;
@@ -1054,8 +1055,11 @@ void LLFolderViewItem::draw()
 	{
 		root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress();
 	}
-	if ((mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) ||
-		(LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && root_is_loading && (mShowLoadStatus || mHidden)))
+	if ((mIsLoading
+		&&	mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
+			||	(LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
+				&&	root_is_loading
+				&&	mShowLoadStatus))
 	{
 		std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) ";
 		font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor,
@@ -1119,7 +1123,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
 	mLastCalculatedWidth(0),
 	mCompletedFilterGeneration(-1),
 	mMostFilteredDescendantGeneration(-1),
-	mNeedsSort(false)
+	mNeedsSort(false),
+	mPassedFolderFilter(FALSE)
 {
 }
 
@@ -1131,6 +1136,17 @@ LLFolderViewFolder::~LLFolderViewFolder( void )
 	gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
 }
 
+void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation)
+{
+	mPassedFolderFilter = filtered;
+	mLastFilterGeneration = filter_generation;
+}
+
+bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation)
+{
+	return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration();
+}
+
 // addToFolder() returns TRUE if it succeeds. FALSE otherwise
 BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
 {
@@ -1157,8 +1173,6 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
 
 	mHasVisibleChildren = hasFilteredDescendants(filter_generation);
 
-	LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getFilter()->getShowFolderState();
-
 	// calculate height as a single item (without any children), and reshapes rectangle to match
 	LLFolderViewItem::arrange( width, height, filter_generation );
 
@@ -1190,8 +1204,10 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
 				}
 				else
 				{
-					folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders?
-						(folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
+					folderp->setVisible( folderp->getListener()
+										&&	(folderp->getFiltered(filter_generation)
+											||	(folderp->getFilteredFolder(filter_generation) 
+												&& folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter
 				}
 
 				if (folderp->getVisible())
@@ -1311,7 +1327,9 @@ void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recur
 	mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation);
 	mCompletedFilterGeneration = generation;
 	// only aggregate up if we are a lower (older) value
-	if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration())
+	if (recurse_up
+		&& mParentFolder
+		&& generation < mParentFolder->getCompletedFilterGeneration())
 	{
 		mParentFolder->setCompletedFilterGeneration(generation, TRUE);
 	}
@@ -1336,21 +1354,19 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 	// filter folder itself
 	if (getLastFilterGeneration() < filter_generation)
 	{
-		if (getLastFilterGeneration() >= must_pass_generation &&		// folder has been compared to a valid precursor filter
-			!mPassedFilter)													// and did not pass the filter
+		if (getLastFilterGeneration() >= must_pass_generation	// folder has been compared to a valid precursor filter
+			&& !mPassedFilter)									// and did not pass the filter
 		{
 			// go ahead and flag this folder as done
 			mLastFilterGeneration = filter_generation;			
 		}
-		else
+		else // filter self only on first pass through
 		{
-			// filter self only on first pass through
+			// filter against folder rules
+			filterFolder(filter);
+			// and then item rules
 			LLFolderViewItem::filter( filter );
 		}
-		if (mHidden)
-		{
-			setOpen();
-		}
 	}
 
 	if (getRoot()->getDebugFilters())
@@ -1377,7 +1393,10 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 	}
 
 	// when applying a filter, matching folders get their contents downloaded first
-	if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
+	if (filter.isNotDefault()
+		&& getFiltered(filter.getMinRequiredGeneration())
+		&&	(mListener
+			&& !gInventory.isCategoryComplete(mListener->getUUID())))
 	{
 		LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID());
 	}
@@ -1403,6 +1422,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 			if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration()))
 			{
 				mMostFilteredDescendantGeneration = filter_generation;
+				requestArrange();
 			}
 			// just skip it, it has already been filtered
 			continue;
@@ -1415,6 +1435,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 		if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation))
 		{
 			mMostFilteredDescendantGeneration = filter_generation;
+			requestArrange();
 			if (getRoot()->needsAutoSelect() && autoopen_folders)
 			{
 				folder->setOpenArrangeRecursively(TRUE);
@@ -1436,6 +1457,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 			if (item->getFiltered())
 			{
 				mMostFilteredDescendantGeneration = filter_generation;
+				requestArrange();
 			}
 			continue;
 		}
@@ -1454,6 +1476,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 		if (item->getFiltered(filter.getMinRequiredGeneration()))
 		{
 			mMostFilteredDescendantGeneration = filter_generation;
+			requestArrange();
 		}
 	}
 
@@ -1467,6 +1490,31 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 	}
 }
 
+void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter)
+{
+	const BOOL previous_passed_filter = mPassedFolderFilter;
+	const BOOL passed_filter = filter.checkFolder(this);
+
+	// If our visibility will change as a result of this filter, then
+	// we need to be rearranged in our parent folder
+	if (mParentFolder)
+	{
+		if (getVisible() != passed_filter
+			|| previous_passed_filter != passed_filter )
+		{
+			mParentFolder->requestArrange();
+		}
+	}
+
+	setFilteredFolder(passed_filter, filter.getCurrentGeneration());
+	filter.decrementFilterCount();
+
+	if (getRoot()->getDebugFilters())
+	{
+		mStatusText = llformat("%d", mLastFilterGeneration);
+	}
+}
+
 void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation)
 {
 	// if this folder is now filtered, but wasn't before
@@ -1488,6 +1536,23 @@ void LLFolderViewFolder::dirtyFilter()
 	LLFolderViewItem::dirtyFilter();
 }
 
+BOOL LLFolderViewFolder::getFiltered() 
+{ 
+	return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration()) 
+		&& LLFolderViewItem::getFiltered(); 
+}
+
+BOOL LLFolderViewFolder::getFiltered(S32 filter_generation) 
+{
+	return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation);
+}
+
+BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation)
+{ 
+	return mMostFilteredDescendantGeneration >= filter_generation; 
+}
+
+
 BOOL LLFolderViewFolder::hasFilteredDescendants()
 {
 	return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration();
@@ -1743,7 +1808,7 @@ void LLFolderViewFolder::destroyView()
 		folderp->destroyView(); // removes entry from mFolders
 	}
 
-	deleteAllChildren();
+	//deleteAllChildren();
 
 	if (mParentFolder)
 	{
@@ -1843,8 +1908,12 @@ void LLFolderViewFolder::sortBy(U32 order)
 		(*fit)->sortBy(order);
 	}
 
-	mFolders.sort(mSortFunction);
-	mItems.sort(mSortFunction);
+	// Don't sort the topmost folders (My Inventory and Library)
+	if (mListener->getUUID().notNull())
+	{
+		mFolders.sort(mSortFunction);
+		mItems.sort(mSortFunction);
+	}
 
 	if (order & LLInventoryFilter::SO_DATE)
 	{
@@ -1981,6 +2050,13 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
 	item->dirtyFilter();
 	requestArrange();
 	requestSort();
+	LLFolderViewFolder* parentp = getParentFolder();
+	while (parentp && parentp->mSortFunction.isByDate())
+	{
+		// parent folder doesn't have a time stamp yet, so get it from us
+		parentp->requestSort();
+		parentp = parentp->getParentFolder();
+	}
 	return TRUE;
 }
 
@@ -2000,6 +2076,13 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
 	// rearrange all descendants too, as our indentation level might have changed
 	folder->requestArrange(TRUE);
 	requestSort();
+	LLFolderViewFolder* parentp = getParentFolder();
+	while (parentp && !parentp->mSortFunction.isByDate())
+	{
+		// parent folder doesn't have a time stamp yet, so get it from us
+		parentp->requestSort();
+		parentp = parentp->getParentFolder();
+	}
 	return TRUE;
 }
 
@@ -2059,7 +2142,9 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r
 			(*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN);		/* Flawfinder: ignore */
 		}
 	}
-	if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN))
+	if (mParentFolder
+		&&	(recurse == RECURSE_UP
+			|| recurse == RECURSE_UP_DOWN))
 	{
 		mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);
 	}
@@ -2301,13 +2386,16 @@ void LLFolderViewFolder::draw()
 
 	bool possibly_has_children = false;
 	bool up_to_date = mListener && mListener->isUpToDate();
-	if(!up_to_date && mListener && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
+	if(!up_to_date
+		&& mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
 	{
 		possibly_has_children = true;
 	}
 
 
-	BOOL loading = ( mIsOpen && possibly_has_children && !up_to_date );
+	BOOL loading = (mIsOpen
+					&& possibly_has_children
+					&& !up_to_date );
 
 	if ( loading && !mIsLoading )
 	{
@@ -2330,6 +2418,41 @@ void LLFolderViewFolder::draw()
 
 time_t LLFolderViewFolder::getCreationDate() const
 {
+	// folders have no creation date try to create one from an item somewhere in our folder hierarchy
+	if (!mCreationDate)
+	{
+		for (items_t::const_iterator iit = mItems.begin();
+			 iit != mItems.end(); ++iit)
+		{
+			LLFolderViewItem* itemp = (*iit);
+
+			const time_t item_creation_date = itemp->getCreationDate();
+			
+			if (item_creation_date)
+			{
+				mCreationDate = item_creation_date;
+				break;
+			}
+		}
+		
+		if (!mCreationDate)
+		{
+			for (folders_t::const_iterator fit = mFolders.begin();
+				 fit != mFolders.end(); ++fit)
+			{
+				LLFolderViewFolder* folderp = (*fit);
+				
+				const time_t folder_creation_date = folderp->getCreationDate();
+				
+				if (folder_creation_date)
+				{
+					mCreationDate = folder_creation_date;
+					break;
+				}
+			}
+		}
+	}
+
 	return llmax<time_t>(mCreationDate, mSubtreeCreationDate);
 }
 
@@ -2573,7 +2696,8 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde
 {
 	// ignore sort order for landmarks in the Favorites folder.
 	// they should be always sorted as in Favorites bar. See EXT-719
-	if (a->getSortGroup() == SG_ITEM && b->getSortGroup() == SG_ITEM
+	if (a->getSortGroup() == SG_ITEM
+		&& b->getSortGroup() == SG_ITEM
 		&& a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK
 		&& b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
 	{
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index fc941510ab2395382a72a7d6cb1a16eb8422507f..e2f94a2b633130f4b688ddff01d3de38355a00b3 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -66,6 +66,7 @@ public:
 	// Returns true if order has changed
 	bool updateSort(U32 order);
 	U32 getSort() { return mSortOrder; }
+	bool isByDate() { return mByDate; }
 
 	bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b);
 private:
@@ -94,7 +95,7 @@ public:
 		Optional<LLUIImage*>					icon_open;  // used for folders
 		Optional<LLUIImage*>					icon_overlay;  // for links
 		Optional<LLFolderView*>					root;
-		Optional<LLFolderViewEventListener*>	listener;
+		Mandatory<LLFolderViewEventListener*>	listener;
 
 		Optional<LLUIImage*>					folder_arrow_image;
 		Optional<S32>							folder_indentation; // pixels
@@ -135,7 +136,7 @@ protected:
 	std::string					mSearchableLabel;
 	S32							mLabelWidth;
 	bool						mLabelWidthDirty;
-	time_t						mCreationDate;
+	mutable time_t				mCreationDate;
 	LLFolderViewFolder*			mParentFolder;
 	LLFolderViewEventListener*	mListener;
 	BOOL						mIsCurSelection;
@@ -157,7 +158,6 @@ protected:
 	BOOL						mDragAndDropTarget;
 	BOOL                        mIsLoading;
 	LLTimer                     mTimeSinceRequestStart;
-	bool						mHidden;
 	bool						mShowLoadStatus;
 
 	// helper function to change the selection from the root.
@@ -167,13 +167,15 @@ protected:
 	void extendSelectionFromRoot(LLFolderViewItem* selection);
 
 	// this is an internal method used for adding items to folders. A
-	// no-op at this leve, but reimplemented in derived classes.
+	// no-op at this level, but reimplemented in derived classes.
 	virtual BOOL addItem(LLFolderViewItem*) { return FALSE; }
 	virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
 
 	static LLFontGL* getLabelFontForStyle(U8 style);
 
 public:
+	BOOL postBuild();
+
 	// This function clears the currently selected item, and records
 	// the specified selected item appropriately for display and use
 	// in the UI. If open is TRUE, then folders are opened up along
@@ -202,11 +204,6 @@ public:
 	virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
 	virtual S32 getItemHeight();
 
-	// Hide the folder from the UI, such as if you want to hide the root
-	// folder in an inventory panel.
-	void setHidden(bool hidden) { mHidden = hidden; }
-	bool getHidden() const { return mHidden; }
-
 	// applies filters to control visibility of inventory items
 	virtual void filter( LLInventoryFilter& filter);
 
@@ -366,6 +363,9 @@ public:
 		UNKNOWN, TRASH, NOT_TRASH
 	} ETrash;
 
+	typedef std::list<LLFolderViewItem*> items_t;
+	typedef std::list<LLFolderViewFolder*> folders_t;
+
 private:
 	S32		mNumDescendantsSelected;
 
@@ -374,8 +374,6 @@ public:		// Accessed needed by LLFolderViewItem
 	S32 numSelected(void) const { return mNumDescendantsSelected + (isSelected() ? 1 : 0); }
 
 protected:
-	typedef std::list<LLFolderViewItem*> items_t;
-	typedef std::list<LLFolderViewFolder*> folders_t;
 	items_t mItems;
 	folders_t mFolders;
 	LLInventorySort	mSortFunction;
@@ -392,6 +390,8 @@ protected:
 	S32			mCompletedFilterGeneration;
 	S32			mMostFilteredDescendantGeneration;
 	bool		mNeedsSort;
+	bool		mPassedFolderFilter;
+
 public:
 	typedef enum e_recurse_type
 	{
@@ -425,13 +425,21 @@ public:
 	virtual void	setCompletedFilterGeneration(S32 generation, BOOL recurse_up);
 	virtual S32		getCompletedFilterGeneration() { return mCompletedFilterGeneration; }
 
-	BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; }
+	BOOL hasFilteredDescendants(S32 filter_generation);
 	BOOL hasFilteredDescendants();
 
 	// applies filters to control visibility of inventory items
 	virtual void filter( LLInventoryFilter& filter);
 	virtual void setFiltered(BOOL filtered, S32 filter_generation);
+	virtual BOOL getFiltered();
+	virtual BOOL getFiltered(S32 filter_generation);
+
 	virtual void dirtyFilter();
+	
+	// folder-specific filtering (filter status propagates top down instead of bottom up)
+	void filterFolder(LLInventoryFilter& filter);
+	void setFilteredFolder(bool filtered, S32 filter_generation);
+	bool getFilteredFolder(S32 filter_generation);
 
 	// Passes selection information on to children and record
 	// selection information if necessary.
@@ -537,6 +545,10 @@ public:
 	time_t getCreationDate() const;
 	bool isTrash() const;
 	S32 getNumSelectedDescendants(void) const { return mNumDescendantsSelected; }
+
+	folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); }
+	folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); }
+	folders_t::size_type getFoldersCount() const { return mFolders.size(); }
 };
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 86c8a1a9b58d16fd543c6c4dba3132be78c48a2b..75d4c4e80d4b6da20f7c62c6bfb381df38ce3c06 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -40,6 +40,7 @@
 #include "llfloateropenobject.h"
 #include "llfloaterreg.h"
 #include "llfloaterworldmap.h"
+#include "llfolderview.h"
 #include "llfriendcard.h"
 #include "llgesturemgr.h"
 #include "llgiveinventory.h" 
@@ -571,8 +572,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 		}
 	}
 
-	// Don't allow items to be pasted directly into the COF.
-	if (!isCOFFolder())
+	// Don't allow items to be pasted directly into the COF or the inbox
+	if (!isCOFFolder() && !isInboxFolder())
 	{
 		items.push_back(std::string("Paste"));
 	}
@@ -781,6 +782,18 @@ BOOL LLInvFVBridge::isCOFFolder() const
 	return LLAppearanceMgr::instance().getIsInCOF(mUUID);
 }
 
+BOOL LLInvFVBridge::isInboxFolder() const
+{
+	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false);
+	
+	if (inbox_id.isNull())
+	{
+		return FALSE;
+	}
+	
+	return gInventory.isObjectDescendentOf(mUUID, inbox_id);
+}
+
 BOOL LLInvFVBridge::isItemPermissive() const
 {
 	return FALSE;
@@ -1786,6 +1799,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 			else
 			{
+				if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+				{
+					set_dad_inbox_object(inv_cat->getUUID());
+				}
 
 				// Reparent the folder and restamp children if it's moving
 				// into trash.
@@ -2525,6 +2542,7 @@ void LLFolderBridge::folderOptionsMenu()
 			{
 				mItems.push_back(std::string("Add To Outfit"));
 			}
+
 			mItems.push_back(std::string("Replace Outfit"));
 		}
 		if (is_ensemble)
@@ -2614,15 +2632,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		// Not sure what the right thing is to do here.
 		if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
 		{
-			// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
-			if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
-				mItems.push_back(std::string("New Folder"));
-			mItems.push_back(std::string("New Script"));
-			mItems.push_back(std::string("New Note"));
-			mItems.push_back(std::string("New Gesture"));
-			mItems.push_back(std::string("New Clothes"));
-			mItems.push_back(std::string("New Body Parts"));
-
+			if (!isInboxFolder()) // don't allow creation in inbox
+			{
+				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+					mItems.push_back(std::string("New Folder"));
+				mItems.push_back(std::string("New Script"));
+				mItems.push_back(std::string("New Note"));
+				mItems.push_back(std::string("New Gesture"));
+				mItems.push_back(std::string("New Clothes"));
+				mItems.push_back(std::string("New Body Parts"));
+			}
 #if SUPPORT_ENSEMBLES
 			// Changing folder types is an unfinished unsupported feature
 			// and can lead to unexpected behavior if enabled.
@@ -3161,6 +3181,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			// (move the item, restamp if into trash)
 			else
 			{
+				// set up observer to select item once drag and drop from inbox is complete 
+				if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+				{
+					set_dad_inbox_object(inv_item->getUUID());
+				}
+
 				LLInvFVBridge::changeItemParent(
 					model,
 					(LLViewerInventoryItem*)inv_item,
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 1e849c88121c32a7802c1f7a6263054105c2936b..15629c0c75465c025e5a53b1563165c8db9e0de1 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -139,6 +139,7 @@ protected:
 
 	BOOL isAgentInventory() const; // false if lost or in the inventory library
 	BOOL isCOFFolder() const; // true if COF or descendent of
+	BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox
 	virtual BOOL isItemPermissive() const;
 	static void changeItemParent(LLInventoryModel* model,
 								 LLViewerInventoryItem* item,
@@ -584,6 +585,9 @@ protected:
 };
 
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Recent Inventory Panel related classes
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 // Overridden version of the Inventory-Folder-View-Bridge for Folders
 class LLRecentItemsFolderBridge : public LLFolderBridge
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index dee15a1efdc55c609879e9891f08ac33e2e3d775..d6278a5fda98470eb80e5b807e19ca92c78fd7b0 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -107,6 +107,32 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item)
 	return passed;
 }
 
+bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder)
+{
+	// we're showing all folders, overriding filter
+	if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
+	{
+		return true;
+	}
+
+	const LLFolderViewEventListener* listener = folder->getListener();
+	const LLUUID folder_id = listener->getUUID();
+
+	if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
+	{
+		// Can only filter categories for items in your inventory
+		// (e.g. versus in-world object contents).
+		const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
+		if (!cat)
+			return false;
+		LLFolderType::EType cat_type = cat->getPreferredType();
+		if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))
+			return false;
+	}
+
+	return true;
+}
+
 BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const
 {
 	const LLFolderViewEventListener* listener = item->getListener();
@@ -137,30 +163,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
 		}
 	}
 	
-	
-	////////////////////////////////////////////////////////////////////////////////
-	// FILTERTYPE_CATEGORY
-	// Pass if this item is a category of the filter type, or
-	// if its parent is a category of the filter type.
-	if (filterTypes & FILTERTYPE_CATEGORY)
-	{
-		// Can only filter categories for items in your inventory 
-		// (e.g. versus in-world object contents).
-		if (!object) return FALSE;
-
-		LLUUID cat_id = object_id;
-		if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY)
-		{
-			cat_id = object->getParentUUID();
-		}
-		const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
-		if (!cat) 
-			return FALSE;
-		if ((1LL << cat->getPreferredType() & mFilterOps.mFilterCategoryTypes) == U64(0))
-			return FALSE;
-	}
-
-
 	////////////////////////////////////////////////////////////////////////////////
 	// FILTERTYPE_UUID
 	// Pass if this item is the target UUID or if it links to the target UUID
@@ -172,7 +174,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
 			return FALSE;
 	}
 
-
 	////////////////////////////////////////////////////////////////////////////////
 	// FILTERTYPE_DATE
 	// Pass if this item is within the date range.
@@ -293,15 +294,15 @@ BOOL LLInventoryFilter::isModifiedAndClear()
 	return ret;
 }
 
-void LLInventoryFilter::setFilterObjectTypes(U64 types)
+void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
 {
-	if (mFilterOps.mFilterObjectTypes != types)
+	if (current_types != types)
 	{
 		// keep current items only if no type bits getting turned off
-		BOOL fewer_bits_set = (mFilterOps.mFilterObjectTypes & ~types);
-		BOOL more_bits_set = (~mFilterOps.mFilterObjectTypes & types);
+		bool fewer_bits_set = (current_types & ~types) != 0;
+		bool more_bits_set = (~current_types & types) != 0;
 
-		mFilterOps.mFilterObjectTypes = types;
+		current_types = types;
 		if (more_bits_set && fewer_bits_set)
 		{
 			// neither less or more restrive, both simultaneously
@@ -318,62 +319,23 @@ void LLInventoryFilter::setFilterObjectTypes(U64 types)
 			setModified(FILTER_MORE_RESTRICTIVE);
 		}
 	}
+}
+
+void LLInventoryFilter::setFilterObjectTypes(U64 types)
+{
+	updateFilterTypes(types, mFilterOps.mFilterObjectTypes);
 	mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
 }
 
 void LLInventoryFilter::setFilterCategoryTypes(U64 types)
 {
-	if (mFilterOps.mFilterCategoryTypes != types)
-	{
-		// keep current items only if no type bits getting turned off
-		BOOL fewer_bits_set = (mFilterOps.mFilterCategoryTypes & ~types);
-		BOOL more_bits_set = (~mFilterOps.mFilterCategoryTypes & types);
-
-		mFilterOps.mFilterCategoryTypes = types;
-		if (more_bits_set && fewer_bits_set)
-		{
-			// neither less or more restrive, both simultaneously
-			// so we need to filter from scratch
-			setModified(FILTER_RESTART);
-		}
-		else if (more_bits_set)
-		{
-			// target is only one of all requested types so more type bits == less restrictive
-			setModified(FILTER_LESS_RESTRICTIVE);
-		}
-		else if (fewer_bits_set)
-		{
-			setModified(FILTER_MORE_RESTRICTIVE);
-		}
-	}
-	mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
+	updateFilterTypes(types, mFilterOps.mFilterCategoryTypes);
+	mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY;
 }
 
 void LLInventoryFilter::setFilterWearableTypes(U64 types)
 {
-	if (mFilterOps.mFilterWearableTypes != types)
-	{
-		// keep current items only if no type bits getting turned off
-		BOOL fewer_bits_set = (mFilterOps.mFilterWearableTypes & ~types);
-		BOOL more_bits_set = (~mFilterOps.mFilterWearableTypes & types);
-
-		mFilterOps.mFilterWearableTypes = types;
-		if (more_bits_set && fewer_bits_set)
-		{
-			// neither less or more restrive, both simultaneously
-			// so we need to filter from scratch
-			setModified(FILTER_RESTART);
-		}
-		else if (more_bits_set)
-		{
-			// target is only one of all requested types so more type bits == less restrictive
-			setModified(FILTER_LESS_RESTRICTIVE);
-		}
-		else if (fewer_bits_set)
-		{
-			setModified(FILTER_MORE_RESTRICTIVE);
-		}
-	}
+	updateFilterTypes(types, mFilterOps.mFilterWearableTypes);
 	mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE;
 }
 
@@ -898,11 +860,16 @@ void LLInventoryFilter::fromLLSD(LLSD& data)
 	}
 }
 
-U32 LLInventoryFilter::getFilterObjectTypes() const
+U64 LLInventoryFilter::getFilterObjectTypes() const
 {
 	return mFilterOps.mFilterObjectTypes;
 }
 
+U64 LLInventoryFilter::getFilterCategoryTypes() const
+{
+	return mFilterOps.mFilterCategoryTypes;
+}
+
 BOOL LLInventoryFilter::hasFilterString() const
 {
 	return mFilterSubString.size() > 0;
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 39e6f797a24dae9c70933350fe7951d5d668e39b..f9460822f7d54c8ba5d80e9c442b72540d74cc09 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -31,6 +31,7 @@
 #include "llpermissionsflags.h"
 
 class LLFolderViewItem;
+class LLFolderViewFolder;
 
 class LLInventoryFilter
 {
@@ -81,11 +82,13 @@ public:
 	// + Parameters
 	// +-------------------------------------------------------------------+
 	void 				setFilterObjectTypes(U64 types);
-	U32 				getFilterObjectTypes() const;
+	U64 				getFilterObjectTypes() const;
+	U64					getFilterCategoryTypes() const;
 	BOOL 				isFilterObjectTypesWith(LLInventoryType::EType t) const;
 	void 				setFilterCategoryTypes(U64 types);
 	void 				setFilterUUID(const LLUUID &object_id);
 	void				setFilterWearableTypes(U64 types);
+	void				updateFilterTypes(U64 types, U64& current_types);
 
 	void 				setFilterSubString(const std::string& string);
 	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;
@@ -110,6 +113,7 @@ public:
 	// + Execution And Results
 	// +-------------------------------------------------------------------+
 	BOOL 				check(const LLFolderViewItem* item);
+	bool				checkFolder(const LLFolderViewFolder* folder);
 	BOOL 				checkAgainstFilterType(const LLFolderViewItem* item) const;
 	BOOL 				checkAgainstPermissions(const LLFolderViewItem* item) const;
 	BOOL 				checkAgainstFilterLinks(const LLFolderViewItem* item) const;
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index cfe1747fd4d7435adb8e128c3cfac90a215742f9..2016b92666d9ea168425196e462be886dc7bc2f6 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -28,9 +28,9 @@
 #ifndef LL_LLINVENTORYFUNCTIONS_H
 #define LL_LLINVENTORYFUNCTIONS_H
 
-#include "llinventorytype.h"
-#include "llfolderview.h"
-#include "llfolderviewitem.h"
+#include "llinventorymodel.h"
+#include "llinventory.h"
+#include "llwearabletype.h"
 
 /********************************************************************************
  **                                                                            **
@@ -417,6 +417,24 @@ public:
 /**                    Inventory Collector Functions
  **                                                                            **
  *******************************************************************************/
+class LLFolderViewItem;
+class LLFolderViewFolder;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFolderViewFunctor
+//
+// Simple abstract base class for applying a functor to folders and
+// items in a folder view hierarchy. This is suboptimal for algorithms
+// that only work folders or only work on items, but I'll worry about
+// that later when it's determined to be too slow.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFolderViewFunctor
+{
+public:
+	virtual ~LLFolderViewFunctor() {}
+	virtual void doFolder(LLFolderViewFolder* folder) = 0;
+	virtual void doItem(LLFolderViewItem* item) = 0;
+};
 
 class LLInventoryState
 {
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 318beafe657a97e1e029c98036468d353a9267f4..21d5de9a5b8a971a5f3e98480e10efbdecce034b 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2589,7 +2589,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 		LLInventoryState::sWearNewClothing = FALSE;
 	}
 
-	if (tid == LLInventoryState::sWearNewClothingTransactionID)
+	if (tid.notNull() && tid == LLInventoryState::sWearNewClothingTransactionID)
 	{
 		count = wearable_ids.size();
 		for (i = 0; i < count; ++i)
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 7b1ff102e704ce89afb7cabd15f25e338cdfecb2..afaf660cb71a7661e6fd60aaa64e3ec791757cfe 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -31,7 +31,9 @@
 #include "llappviewer.h"
 #include "llcallbacklist.h"
 #include "llinventorypanel.h"
+#include "llinventorymodel.h"
 #include "llviewercontrol.h"
+#include "llviewerinventory.h"
 #include "llviewermessage.h"
 #include "llviewerregion.h"
 #include "llviewerwindow.h"
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 6bf19e346db340cc7adfee84908fd92f99e124b0..ceba4a019127624634d7489989f57acfcffb9455 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -601,6 +601,34 @@ void LLInventoryAddedObserver::changed(U32 mask)
 	}
 }
 
+void LLInventoryCategoryAddedObserver::changed(U32 mask)
+{
+	if (!(mask & LLInventoryObserver::ADD))
+	{
+		return;
+	}
+	
+	const LLInventoryModel::changed_items_t& changed_ids = gInventory.getChangedIDs();
+	
+	for (LLInventoryModel::changed_items_t::const_iterator cit = changed_ids.begin(); cit != changed_ids.end(); ++cit)
+	{
+		LLViewerInventoryCategory* cat = gInventory.getCategory(*cit);
+		
+		if (cat)
+		{
+			mAddedCategories.push_back(cat);
+		}
+	}
+	
+	if (!mAddedCategories.empty())
+	{
+		done();
+		
+		mAddedCategories.clear();
+	}
+}
+
+
 LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransactionID& transaction_id) :
 	mTransactionID(transaction_id)
 {
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index 2d9021961e2e72497a333f904f181af8af281f98..aa1eae84d707cf32c1589b13799fc0fa19960f02 100644
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -218,6 +218,28 @@ protected:
 	uuid_vec_t mAdded;
 };
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryCategoryAddedObserver
+//
+//   Base class for doing something when a new category is created in the
+//   inventory.
+//   It does not watch for a certain UUID, rather it acts when anything is added
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryCategoryAddedObserver : public LLInventoryObserver
+{
+public:
+	
+	typedef std::vector<LLViewerInventoryCategory*>	cat_vec_t;
+	
+	LLInventoryCategoryAddedObserver() : mAddedCategories() {}
+	/*virtual*/ void changed(U32 mask);
+	
+protected:
+	virtual void done() = 0;
+	
+	cat_vec_t	mAddedCategories;
+};
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInventoryTransactionObserver
 //
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 1dcb91ad4d28893ac1bf1e15bc24965a01d9ae1a..702e8d5a1f1dbde5898663ea807dd148b2260d25 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -35,6 +35,7 @@
 #include "llavataractions.h"
 #include "llfloaterinventory.h"
 #include "llfloaterreg.h"
+#include "llfolderview.h"
 #include "llimfloater.h"
 #include "llimview.h"
 #include "llinventorybridge.h"
@@ -42,7 +43,6 @@
 #include "llinventorymodelbackgroundfetch.h"
 #include "llsidepanelinventory.h"
 #include "llsidetray.h"
-#include "llscrollcontainer.h"
 #include "llviewerattachmenu.h"
 #include "llviewerfoldertype.h"
 #include "llvoavatarself.h"
@@ -131,9 +131,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mInventory(p.inventory),
 	mAllowMultiSelect(p.allow_multi_select),
 	mShowItemLinkOverlays(p.show_item_link_overlays),
+	mShowLoadStatus(p.show_load_status),
 	mViewsInitialized(false),
-	mStartFolderString(p.start_folder),	
-	mBuildDefaultHierarchy(true),
 	mInvFVBridgeBuilder(NULL)
 {
 	mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
@@ -146,11 +145,88 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2));
 	mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
 	mCommitCallbackRegistrar.add("Inventory.Share",  boost::bind(&LLAvatarActions::shareWithAvatars));
+
+}
+
+void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
+{
+	// Determine the root folder in case specified, and
+	// build the views starting with that folder.
+	
+	std::string start_folder_name(params.start_folder());
+	
+	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(start_folder_name);
+
+	LLUUID root_id;
+
+	if ("LIBRARY" == params.start_folder())
+	{
+		root_id = gInventory.getLibraryRootFolderID();
+	}
+	// leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+	else if (preferred_type == LLFolderType::FT_INBOX)
+	{
+		LLInventoryModel::cat_array_t* cats;
+		LLInventoryModel::item_array_t* items;
+		
+		gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+		
+		if (cats)
+		{
+			for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+			{
+				LLInventoryCategory* cat = *cat_it;
+				
+				if (cat->getName() == "Received Items")
+				{
+					root_id = cat->getUUID();
+				}
+			}
+		}
+	}
+	// leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+	else if (preferred_type == LLFolderType::FT_OUTBOX)
+	{
+		LLInventoryModel::cat_array_t* cats;
+		LLInventoryModel::item_array_t* items;
+		
+		gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+		
+		if (cats)
+		{
+			for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+			{
+				LLInventoryCategory* cat = *cat_it;
+				
+				if (cat->getName() == "Merchant Outbox")
+				{
+					root_id = cat->getUUID();
+				}
+			}
+		}
+	}
+	// leslie -- end temporary HACK
+	else
+	{
+		root_id = (preferred_type != LLFolderType::FT_NONE)
+				? gInventory.findCategoryUUIDForType(preferred_type, false, false) 
+				: LLUUID::null;
+	}
 	
-	if (mStartFolderString != "")
+	if ((root_id == LLUUID::null) && !start_folder_name.empty())
 	{
-		mBuildDefaultHierarchy = false;
+		llwarns << "No category found that matches start_folder: " << start_folder_name << llendl;
+		root_id = LLUUID::generateNewID();
 	}
+	
+	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+																	LLAssetType::AT_CATEGORY,
+																	LLInventoryType::IT_CATEGORY,
+																	this,
+																	NULL,
+																	root_id);
+	
+	mFolderRoot = createFolderView(new_listener, params.use_label_suffix());
 }
 
 void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
@@ -159,22 +235,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
 
 	mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
 	
-	// Create root folder
-	{
-		LLRect folder_rect(0,
-						   0,
-						   getRect().getWidth(),
-						   0);
-		LLFolderView::Params p;
-		p.name = getName();
-		p.title = getLabel();
-		p.rect = folder_rect;
-		p.parent_panel = this;
-		p.tool_tip = p.name;
-		p.use_label_suffix = params.use_label_suffix;
-		mFolderRoot = LLUICtrlFactory::create<LLFolderView>(p);
-		mFolderRoot->setAllowMultiSelect(mAllowMultiSelect);
-	}
+	buildFolderView(params);
 
 	mCommitCallbackRegistrar.popScope();
 	
@@ -184,13 +245,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
 	{
 		LLRect scroller_view_rect = getRect();
 		scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
-		LLScrollContainer::Params p;
-		p.name("Inventory Scroller");
-		p.rect(scroller_view_rect);
-		p.follows.flags(FOLLOWS_ALL);
-		p.reserve_scroll_corner(true);
-		p.tab_stop(true);
-		mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+		LLScrollContainer::Params scroller_params(params.scroll());
+		scroller_params.rect(scroller_view_rect);
+		mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroller_params);
 		addChild(mScroller);
 		mScroller->addChild(mFolderRoot);
 		mFolderRoot->setScrollContainer(mScroller);
@@ -206,7 +263,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
 
 	// Build view of inventory if we need default full hierarchy and inventory ready,
 	// otherwise wait for idle callback.
-	if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mViewsInitialized)
+	if (mInventory->isInventoryUsable() && !mViewsInitialized)
 	{
 		initializeViews();
 	}
@@ -222,6 +279,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
 	}
 	mFolderRoot->setSortOrder(getFilter()->getSortOrder());
 
+	// hide inbox
+	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX));
+
 	// Initialize base class params.
 	LLPanel::initFromParams(params);
 }
@@ -264,6 +324,15 @@ LLInventoryFilter* LLInventoryPanel::getFilter()
 	return NULL;
 }
 
+const LLInventoryFilter* LLInventoryPanel::getFilter() const
+{
+	if (mFolderRoot)
+	{
+		return mFolderRoot->getFilter();
+	}
+	return NULL;
+}
+
 void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type)
 {
 	if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT)
@@ -272,6 +341,17 @@ void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType
 		getFilter()->setFilterCategoryTypes(types);
 }
 
+U32 LLInventoryPanel::getFilterObjectTypes() const 
+{ 
+	return mFolderRoot->getFilterObjectTypes(); 
+}
+
+U32 LLInventoryPanel::getFilterPermMask() const 
+{ 
+	return mFolderRoot->getFilterPermissions(); 
+}
+
+
 void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
 {
 	getFilter()->setFilterPermissions(filter_perm_mask);
@@ -287,6 +367,12 @@ void LLInventoryPanel::setFilterSubString(const std::string& string)
 	getFilter()->setFilterSubString(string);
 }
 
+const std::string LLInventoryPanel::getFilterSubString() 
+{ 
+	return mFolderRoot->getFilterSubString(); 
+}
+
+
 void LLInventoryPanel::setSortOrder(U32 order)
 {
 	getFilter()->setSortOrder(order);
@@ -298,6 +384,12 @@ void LLInventoryPanel::setSortOrder(U32 order)
 	}
 }
 
+U32 LLInventoryPanel::getSortOrder() const 
+{ 
+	return mFolderRoot->getSortOrder(); 
+}
+
+
 void LLInventoryPanel::setSinceLogoff(BOOL sl)
 {
 	getFilter()->setDateRangeLastLogoff(sl);
@@ -379,7 +471,8 @@ void LLInventoryPanel::modelChanged(U32 mask)
 			{
 				view_item->destroyView();
 			}
-			buildNewViews(item_id);
+			view_item = buildNewViews(item_id);
+			view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);
 		}
 
 		//////////////////////////////
@@ -432,11 +525,10 @@ void LLInventoryPanel::modelChanged(U32 mask)
 			//////////////////////////////
 			// STRUCTURE Operation
 			// This item already exists in both memory and UI.  It was probably reparented.
-			if (model_item && view_item)
+			else if (model_item && view_item)
 			{
-				// Don't process the item if it's hanging from the root, since its
-				// model_item's parent will be NULL.
-				if (view_item->getRoot() != view_item->getParent())
+				// Don't process the item if it is the root
+				if (view_item->getRoot() != view_item)
 				{
 					LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID());
 					// Item has been moved.
@@ -461,7 +553,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
 			//////////////////////////////
 			// REMOVE Operation
 			// This item has been removed from memory, but its associated UI element still exists.
-			if (!model_item && view_item)
+			else if (!model_item && view_item)
 			{
 				// Remove the item's UI.
 				view_item->destroyView();
@@ -470,6 +562,12 @@ void LLInventoryPanel::modelChanged(U32 mask)
 	}
 }
 
+LLFolderView* LLInventoryPanel::getRootFolder() 
+{ 
+	return mFolderRoot; 
+}
+
+
 // static
 void LLInventoryPanel::onIdle(void *userdata)
 {
@@ -488,23 +586,16 @@ void LLInventoryPanel::onIdle(void *userdata)
 	}
 }
 
+const LLUUID& LLInventoryPanel::getRootFolderID() const
+{
+	return mFolderRoot->getListener()->getUUID();
+}
+
 void LLInventoryPanel::initializeViews()
 {
 	if (!gInventory.isInventoryUsable()) return;
 
-	// Determine the root folder in case specified, and
-	// build the views starting with that folder.
-	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
-
-	if ("LIBRARY" == mStartFolderString)
-	{
-		mStartFolderID = gInventory.getLibraryRootFolderID();
-	}
-	else
-	{
-		mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
-	}
-	rebuildViewsFor(mStartFolderID);
+	rebuildViewsFor(getRootFolderID());
 
 	mViewsInitialized = true;
 	
@@ -529,132 +620,155 @@ void LLInventoryPanel::initializeViews()
 	}
 }
 
-void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
+LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
 {
 	// Destroy the old view for this ID so we can rebuild it.
 	LLFolderViewItem* old_view = mFolderRoot->getItemByID(id);
-	if (old_view && id.notNull())
+	if (old_view)
 	{
 		old_view->destroyView();
 	}
 
-	buildNewViews(id);
+	return buildNewViews(id);
 }
 
-void LLInventoryPanel::buildNewViews(const LLUUID& id)
+LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix)
 {
-	LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS);
-	LLFolderViewItem* itemp = NULL;
-	LLInventoryObject* objectp = gInventory.getObject(id);
-	if (objectp)
+	LLRect folder_rect(0,
+					   0,
+					   getRect().getWidth(),
+					   0);
+
+	LLFolderView::Params p;
+	
+	p.name = getName();
+	p.title = getLabel();
+	p.rect = folder_rect;
+	p.parent_panel = this;
+	p.tool_tip = p.name;
+	p.listener =  bridge;
+	p.use_label_suffix = useLabelSuffix;
+	p.allow_multiselect = mAllowMultiSelect;
+	p.show_load_status = mShowLoadStatus;
+
+	return LLUICtrlFactory::create<LLFolderView>(p);
+}
+
+LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
+{
+	LLFolderViewFolder::Params params;
+
+	params.name = bridge->getDisplayName();
+	params.icon = bridge->getIcon();
+	params.icon_open = bridge->getOpenIcon();
+
+	if (mShowItemLinkOverlays) // if false, then links show up just like normal items
 	{
-		const LLUUID &parent_id = objectp->getParentUUID();
-		LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id);
-		if (id == mStartFolderID)
-		{
-			parent_folder = mFolderRoot;
-		}
-		else if ((mStartFolderID != LLUUID::null) && (!gInventory.isObjectDescendentOf(id, mStartFolderID)))
-		{
-			// This item exists outside the inventory's hierarchy, so don't add it.
-			return;
-		}
-		
-		if (objectp->getType() <= LLAssetType::AT_NONE ||
-			objectp->getType() >= LLAssetType::AT_COUNT)
-		{
-			llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
-					<< ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() 
-					<< llendl;
-			return;
-		}
-		
-		if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
-			(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
-		{
-			LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
-																			objectp->getType(),
-																			LLInventoryType::IT_CATEGORY,
-																			this,
-																			mFolderRoot,
-																			objectp->getUUID());
-			if (new_listener)
-			{
-				LLFolderViewFolder::Params params;
-				params.name = new_listener->getDisplayName();
-				params.icon = new_listener->getIcon();
-				params.icon_open = new_listener->getOpenIcon();
-				if (mShowItemLinkOverlays) // if false, then links show up just like normal items
-				{
-					params.icon_overlay = LLUI::getUIImage("Inv_Link");
-				}
-				params.root = mFolderRoot;
-				params.listener = new_listener;
-				params.tool_tip = params.name;
-				LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(params);
-				folderp->setItemSortOrder(mFolderRoot->getSortOrder());
-				itemp = folderp;
-
-				// Hide the root folder, so we can show the contents of a folder flat
-				// but still have the parent folder present for listener-related operations.
-				if (id == mStartFolderID)
-				{
-					folderp->setHidden(TRUE);
-				}
-				const LLViewerInventoryCategory *cat = dynamic_cast<LLViewerInventoryCategory *>(objectp);
-				if (cat && getIsHiddenFolderType(cat->getPreferredType()))
-				{
-					folderp->setHidden(TRUE);
-				}
-			}
-		}
-		else 
-		{
-			// Build new view for item.
-			LLInventoryItem* item = (LLInventoryItem*)objectp;
-			LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
-																			item->getActualType(),
-																			item->getInventoryType(),
-																			this,
-																			mFolderRoot,
-																			item->getUUID(),
-																			item->getFlags());
-
-			if (new_listener)
-			{
-				LLFolderViewItem::Params params;
-				params.name = new_listener->getDisplayName();
-				params.icon = new_listener->getIcon();
-				params.icon_open = new_listener->getOpenIcon();
-				if (mShowItemLinkOverlays) // if false, then links show up just like normal items
-				{
-					params.icon_overlay = LLUI::getUIImage("Inv_Link");
-				}
-				params.creation_date = new_listener->getCreationDate();
-				params.root = mFolderRoot;
-				params.listener = new_listener;
-				params.rect = LLRect (0, 0, 0, 0);
-				params.tool_tip = params.name;
-				itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
-			}
-		}
+		params.icon_overlay = LLUI::getUIImage("Inv_Link");
+	}
+	
+	params.root = mFolderRoot;
+	params.listener = bridge;
+	params.tool_tip = params.name;
 
-		if (itemp)
-		{
-			itemp->addToFolder(parent_folder, mFolderRoot);
+	return LLUICtrlFactory::create<LLFolderViewFolder>(params);
+}
 
-			// Don't add children of hidden folders unless this is the panel's root folder.
-			if (itemp->getHidden() && (id != mStartFolderID))
-			{
-				return;
-			}
+LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge)
+{
+	LLFolderViewItem::Params params;
+	
+	params.name = bridge->getDisplayName();
+	params.icon = bridge->getIcon();
+	params.icon_open = bridge->getOpenIcon();
+
+	if (mShowItemLinkOverlays) // if false, then links show up just like normal items
+	{
+		params.icon_overlay = LLUI::getUIImage("Inv_Link");
+	}
+
+	params.creation_date = bridge->getCreationDate();
+	params.root = mFolderRoot;
+	params.listener = bridge;
+	params.rect = LLRect (0, 0, 0, 0);
+	params.tool_tip = params.name;
+	
+	return LLUICtrlFactory::create<LLFolderViewItem>(params);
+}
+
+LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
+{
+ 	LLInventoryObject const* objectp = gInventory.getObject(id);
+ 	LLUUID root_id = mFolderRoot->getListener()->getUUID();
+ 	LLFolderViewFolder* parent_folder = NULL;
+	LLFolderViewItem* itemp = NULL;
+	
+ 	if (id == root_id)
+ 	{
+ 		parent_folder = mFolderRoot;
+ 	}
+ 	else if (objectp)
+ 	{
+ 		const LLUUID &parent_id = objectp->getParentUUID();
+ 		parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id);
+  		
+  		if (parent_folder)
+  		{
+  			if (objectp->getType() <= LLAssetType::AT_NONE ||
+  				objectp->getType() >= LLAssetType::AT_COUNT)
+  			{
+  				llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
+  						<< ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
+  						<< llendl;
+  				return NULL;
+  			}
+  		
+  			if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
+  				(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
+  			{
+  				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+  																				objectp->getType(),
+  																				LLInventoryType::IT_CATEGORY,
+  																				this,
+  																				mFolderRoot,
+  																				objectp->getUUID());
+  				if (new_listener)
+  				{
+					LLFolderViewFolder* folderp = createFolderViewFolder(new_listener);
+  					folderp->setItemSortOrder(mFolderRoot->getSortOrder());
+  					itemp = folderp;
+  				}
+  			}
+  			else
+  			{
+  				// Build new view for item.
+  				LLInventoryItem* item = (LLInventoryItem*)objectp;
+  				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+  																				item->getActualType(),
+  																				item->getInventoryType(),
+  																				this,
+  																				mFolderRoot,
+  																				item->getUUID(),
+  																				item->getFlags());
+ 
+  				if (new_listener)
+  				{
+					itemp = createFolderViewItem(new_listener);
+  				}
+  			}
+ 
+  			if (itemp)
+  			{
+  				itemp->addToFolder(parent_folder, mFolderRoot);
+   			}
 		}
 	}
 
 	// If this is a folder, add the children of the folder and recursively add any 
 	// child folders.
-	if ((id == mStartFolderID) ||
-		(objectp && objectp->getType() == LLAssetType::AT_CATEGORY))
+	if (id.isNull()
+		||	(objectp
+			&& objectp->getType() == LLAssetType::AT_CATEGORY))
 	{
 		LLViewerInventoryCategory::cat_array_t* categories;
 		LLViewerInventoryItem::item_array_t* items;
@@ -671,7 +785,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
 			}
 		}
 		
-		if(items)
+		if(items && parent_folder)
 		{
 			for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();
 				 item_iter != items->end();
@@ -683,28 +797,25 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
 		}
 		mInventory->unlockDirectDescendentArrays(id);
 	}
+	
+	return itemp;
 }
 
 // bit of a hack to make sure the inventory is open.
 void LLInventoryPanel::openStartFolderOrMyInventory()
 {
-	if (mStartFolderString != "")
+	// Find My Inventory folder and open it up by name
+	for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child))
 	{
-		mFolderRoot->openFolder(mStartFolderString);
-	}
-	else
-	{
-		// Find My Inventory folder and open it up by name
-		for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child))
+		LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
+		if (fchild
+			&& fchild->getListener()
+				&& fchild->getListener()->getUUID() == gInventory.getRootFolderID())
 		{
-			LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
-			if (fchild && fchild->getListener() &&
-				(fchild->getListener()->getUUID() == gInventory.getRootFolderID()))
-			{
-				const std::string& child_name = child->getName();
-				mFolderRoot->openFolder(child_name);
-				break;
-			}
+			const std::string& child_name = child->getName();
+			mFolderRoot->openFolder(child_name);
+			mFolderRoot->clearSelection();	// No need to keep it selected though!
+			break;
 		}
 	}
 }
@@ -723,6 +834,12 @@ void LLInventoryPanel::openSelected()
 	bridge->openItem();
 }
 
+void LLInventoryPanel::unSelectAll()	
+{ 
+	mFolderRoot->setSelection(NULL, FALSE, FALSE); 
+}
+
+
 BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
 {
 	BOOL handled = LLView::handleHover(x, y, mask);
@@ -802,7 +919,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc
 	mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus);
 }
 
-void LLInventoryPanel::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) 
+void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb) 
 { 
 	if (mFolderRoot) 
 	{
@@ -1067,15 +1184,12 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
 
 void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type)
 {
-	if (!getIsHiddenFolderType(folder_type))
-	{
-		mHiddenFolderTypes.push_back(folder_type);
-	}
+	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << folder_type));
 }
 
 BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const
 {
-	return (std::find(mHiddenFolderTypes.begin(), mHiddenFolderTypes.end(), folder_type) != mHiddenFolderTypes.end());
+	return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type));
 }
 
 
@@ -1092,6 +1206,13 @@ public:
 	struct Params :	public LLInitParam::Block<Params, LLInventoryPanel::Params>
 	{};
 
+	void initFromParams(const Params& p)
+	{
+		LLInventoryPanel::initFromParams(p);
+		// turn on inbox for recent items
+		getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX));
+	}
+
 protected:
 	LLInventoryRecentItemsPanel (const Params&);
 	friend class LLUICtrlFactory;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 9da9f7d8ba93bdcc4bf0ae4894d870fcbfcc4e0c..a4287a438e790965f45ab9c33555cad90e886c40 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -33,11 +33,13 @@
 #include "llfloater.h"
 #include "llinventory.h"
 #include "llinventoryfilter.h"
-#include "llfolderview.h"
 #include "llinventorymodel.h"
+#include "llscrollcontainer.h"
 #include "lluictrlfactory.h"
 #include <set>
 
+class LLFolderView;
+class LLFolderViewFolder;
 class LLFolderViewItem;
 class LLInventoryFilter;
 class LLInventoryModel;
@@ -46,7 +48,6 @@ class LLInventoryFVBridgeBuilder;
 class LLMenuBarGL;
 class LLCheckBoxCtrl;
 class LLSpinCtrl;
-class LLScrollContainer;
 class LLTextBox;
 class LLIconCtrl;
 class LLSaveFolderState;
@@ -83,6 +84,8 @@ public:
 		Optional<Filter>					filter;
 		Optional<std::string>               start_folder;
 		Optional<bool>						use_label_suffix;
+		Optional<bool>						show_load_status;
+		Optional<LLScrollContainer::Params>	scroll;
 
 		Params()
 		:	sort_order_setting("sort_order_setting"),
@@ -91,7 +94,9 @@ public:
 			show_item_link_overlays("show_item_link_overlays", false),
 			filter("filter"),
 			start_folder("start_folder"),
-			use_label_suffix("use_label_suffix", true)
+			use_label_suffix("use_label_suffix", true),
+			show_load_status("show_load_status"),
+			scroll("scroll")
 		{}
 	};
 
@@ -123,16 +128,17 @@ public:
 	// Call this method to set the selection.
 	void openAllFolders();
 	void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
-	void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
+	void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
 	void clearSelection();
 	LLInventoryFilter* getFilter();
+	const LLInventoryFilter* getFilter() const;
 	void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT);
-	U32 getFilterObjectTypes() const { return mFolderRoot->getFilterObjectTypes(); }
+	U32 getFilterObjectTypes() const;
 	void setFilterPermMask(PermissionMask filter_perm_mask);
-	U32 getFilterPermMask() const { return mFolderRoot->getFilterPermissions(); }
+	U32 getFilterPermMask() const;
 	void setFilterWearableTypes(U64 filter);
 	void setFilterSubString(const std::string& string);
-	const std::string getFilterSubString() { return mFolderRoot->getFilterSubString(); }
+	const std::string getFilterSubString();
 	void setSinceLogoff(BOOL sl);
 	void setHoursAgo(U32 hours);
 	BOOL getSinceLogoff();
@@ -140,10 +146,9 @@ public:
 
 	void setShowFolderState(LLInventoryFilter::EFolderShow show);
 	LLInventoryFilter::EFolderShow getShowFolderState();
-	void setAllowMultiSelect(BOOL allow) { mFolderRoot->setAllowMultiSelect(allow); }
 	// This method is called when something has changed about the inventory.
 	void modelChanged(U32 mask);
-	LLFolderView* getRootFolder() { return mFolderRoot; }
+	LLFolderView* getRootFolder();
 	LLScrollContainer* getScrollableContainer() { return mScroller; }
 	
 	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
@@ -158,7 +163,7 @@ public:
 	static void dumpSelectionInformation(void* user_data);
 
 	void openSelected();
-	void unSelectAll()	{ mFolderRoot->setSelection(NULL, FALSE, FALSE); }
+	void unSelectAll();
 	
 	static void onIdle(void* user_data);
 
@@ -175,6 +180,7 @@ protected:
 	LLInvPanelComplObserver*	mCompletionObserver;
 	BOOL 						mAllowMultiSelect;
 	BOOL 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons
+	BOOL						mShowLoadStatus;
 
 	LLFolderView*				mFolderRoot;
 	LLScrollContainer*			mScroller;
@@ -198,7 +204,7 @@ public:
 	static const std::string INHERIT_SORT_ORDER;
 	
 	void setSortOrder(U32 order);
-	U32 getSortOrder() const { return mFolderRoot->getSortOrder(); }
+	U32 getSortOrder() const;
 private:
 	std::string					mSortOrderSetting;
 
@@ -207,29 +213,27 @@ private:
 	//--------------------------------------------------------------------
 public:
 	void addHideFolderType(LLFolderType::EType folder_type);
-protected:
-	BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const;
-private:
-	std::vector<LLFolderType::EType> mHiddenFolderTypes;
 
-	//--------------------------------------------------------------------
-	// Initialization routines for building up the UI ("views")
-	//--------------------------------------------------------------------
 public:
 	BOOL 				getIsViewsInitialized() const { return mViewsInitialized; }
-	const LLUUID&		getStartFolderID() const { return mStartFolderID; }
-	const std::string&  getStartFolderString() { return mStartFolderString; }
+	const LLUUID&		getRootFolderID() const;
 protected:
 	// Builds the UI.  Call this once the inventory is usable.
 	void 				initializeViews();
-	void rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
-	virtual void buildNewViews(const LLUUID& id);
+	LLFolderViewItem*	rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
+
+	virtual void		buildFolderView(const LLInventoryPanel::Params& params);
+	LLFolderViewItem*	buildNewViews(const LLUUID& id);
+	BOOL				getIsHiddenFolderType(LLFolderType::EType folder_type) const;
+	
+	virtual LLFolderView*		createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix);
+	virtual LLFolderViewFolder*	createFolderViewFolder(LLInvFVBridge * bridge);
+	virtual LLFolderViewItem*	createFolderViewItem(LLInvFVBridge * bridge);
 private:
 	BOOL				mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild()
 	BOOL				mViewsInitialized; // Views have been generated
 	// UUID of category from which hierarchy should be built.  Set with the 
 	// "start_folder" xml property.  Default is LLUUID::null that means total Inventory hierarchy. 
-	std::string         mStartFolderString;
 	LLUUID				mStartFolderID;
 };
 
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index b3ad9efeb242e7027892f83a0fc715adf99abbcf..03ccabc99441b8b2e3d88c0e51ae02b10df158e2 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -38,6 +38,7 @@
 #include "llviewermedia.h"
 #include "llviewertexture.h"
 #include "llviewerwindow.h"
+#include "lldebugmessagebox.h"
 #include "llweb.h"
 #include "llrender.h"
 #include "llpluginclassmedia.h"
@@ -708,6 +709,8 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
 //
 void LLMediaCtrl::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
+
 	if ( gRestoreGL == 1 )
 	{
 		LLRect r = getRect();
@@ -746,21 +749,11 @@ void LLMediaCtrl::draw()
 		}
 	}
 	
-//	if(mHidingInitialLoad)
-//	{
-//		// If we're hiding loading, don't draw at all.
-//		draw_media = false;
-//	}
-	
 	bool background_visible = isBackgroundVisible();
 	bool background_opaque = isBackgroundOpaque();
 	
 	if(draw_media)
 	{
-		// alpha off for this
-		LLGLSUIDefault gls_ui;
-		LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
-
 		gGL.pushUIMatrix();
 		{
 			if (mIgnoreUIScale)
@@ -775,7 +768,8 @@ void LLMediaCtrl::draw()
 
 			// scale texture to fit the space using texture coords
 			gGL.getTexUnit(0)->bind(media_texture);
-			gGL.color4fv( LLColor4::white.mV );
+			LLColor4 media_color = LLColor4::white % alpha;
+			gGL.color4fv( media_color.mV );
 			F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth();
 			F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight();
 
@@ -827,7 +821,6 @@ void LLMediaCtrl::draw()
 			}
 
 			// draw the browser
-			gGL.setSceneBlendType(LLRender::BT_REPLACE);
 			gGL.begin( LLRender::QUADS );
 			if (! media_plugin->getTextureCoordsOpenGL())
 			{
@@ -860,7 +853,6 @@ void LLMediaCtrl::draw()
 				gGL.vertex2i( x_offset + width, y_offset );
 			}
 			gGL.end();
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
 		}
 		gGL.popUIMatrix();
 	
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 6435126fc0c5d10c7ec081ea734b640d7d178feb..10887aa53aa5b4aa70d01d4bda1659eb6d32db99 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -364,8 +364,8 @@ LLOutfitsList::~LLOutfitsList()
 	if (gInventory.containsObserver(mCategoriesObserver))
 	{
 		gInventory.removeObserver(mCategoriesObserver);
-		delete mCategoriesObserver;
 	}
+	delete mCategoriesObserver;
 }
 
 BOOL LLOutfitsList::postBuild()
diff --git a/indra/newview/llpanelappearancetab.cpp b/indra/newview/llpanelappearancetab.cpp
index 9910a3a2ac476458b34bed02c51806fed38a398f..8fa8867c696fca1358eda2c37a006b8899bac65c 100644
--- a/indra/newview/llpanelappearancetab.cpp
+++ b/indra/newview/llpanelappearancetab.cpp
@@ -31,6 +31,7 @@
 
 #include "llinventoryfunctions.h"
 #include "llinventorymodel.h"
+#include "llviewerinventory.h"
 
 //virtual
 bool LLPanelAppearanceTab::canTakeOffSelected()
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 0cc5dcda82040724a864f6210757f718bb5d932a..e370f2f622cdd387615bbde402028852222ee033 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -71,7 +71,7 @@ void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &ch
 
 void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
 {
-	updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
+	updateButtons(new_state);
 }
 
 void LLPanelChatControlPanel::updateCallButton()
@@ -96,11 +96,15 @@ void LLPanelChatControlPanel::updateCallButton()
 	getChildView("call_btn")->setEnabled(enable_connect);
 }
 
-void LLPanelChatControlPanel::updateButtons(bool is_call_started)
+void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state)
 {
+	bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED;
 	getChildView("end_call_btn_panel")->setVisible( is_call_started);
-	getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started);
+	getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel"));
 	getChildView("call_btn_panel")->setVisible( ! is_call_started);
+	
+	getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED);
+	
 	updateCallButton();
 	
 }
@@ -135,7 +139,7 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
 		mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
 		
 		//call (either p2p, group or ad-hoc) can be already in started state
-		updateButtons(voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+		updateButtons(voice_channel->getState());
 	}
 }
 
@@ -156,6 +160,13 @@ BOOL LLPanelIMControlPanel::postBuild()
 	childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
 	childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this));
 	childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this));
+
+	childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this));
+	childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this));
+	childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this));
+	
+	getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2));
+
 	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
 
 	setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this));
@@ -163,6 +174,79 @@ BOOL LLPanelIMControlPanel::postBuild()
 	return LLPanelChatControlPanel::postBuild();
 }
 
+void LLPanelIMControlPanel::draw()
+{
+	bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID);
+
+	getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted);
+	getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted);
+
+	if (getChildView("volume_ctrl_panel")->getVisible())
+	{
+
+		bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
+		mute_btn->setValue( is_muted_voice );
+
+		LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider");
+		volume_slider->setEnabled( !is_muted_voice );
+
+		F32 volume;
+
+		if (is_muted_voice)
+		{
+			// it's clearer to display their volume as zero
+			volume = 0.f;
+		}
+		else
+		{
+			// actual volume
+			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID);
+		}
+		volume_slider->setValue( (F64)volume );
+	}
+
+	LLPanelChatControlPanel::draw();
+}
+
+void LLPanelIMControlPanel::onClickMuteVolume()
+{
+	// By convention, we only display and toggle voice mutes, not all mutes
+	LLMuteList* mute_list = LLMuteList::getInstance();
+	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+	if (!is_muted)
+	{
+		mute_list->add(mute, LLMute::flagVoiceChat);
+	}
+	else
+	{
+		mute_list->remove(mute, LLMute::flagVoiceChat);
+	}
+}
+
+void LLPanelIMControlPanel::onClickBlock()
+{
+	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+	
+	LLMuteList::getInstance()->add(mute);
+}
+
+void LLPanelIMControlPanel::onClickUnblock()
+{
+	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+
+	LLMuteList::getInstance()->remove(mute);
+}
+
+void LLPanelIMControlPanel::onVolumeChange(const LLSD& data)
+{
+	F32 volume = (F32)data.asReal();
+	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume);
+}
+
 void LLPanelIMControlPanel::onTeleportButtonClicked()
 {
 	LLAvatarActions::offerTeleport(mAvatarID);
@@ -262,6 +346,9 @@ void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& ful
 		std::string avatar_name = full_name;
 		getChild<LLTextBox>("avatar_name")->setValue(avatar_name);
 		getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name);
+
+		bool is_linden = LLStringUtil::endsWith(full_name, " Linden");
+		getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden);
 	}
 }
 
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 3bbe24ecb9e0d8f375196f8fa2141efe0b69a26c..bba847b5d4e59616acb36e04284887a8dc928447 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -54,7 +54,7 @@ public:
 
 	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
 
-	void updateButtons(bool is_call_started);
+	void updateButtons(LLVoiceChannel::EState state);
 	
 	// Enables/disables call button depending on voice availability
 	void updateCallButton();
@@ -94,6 +94,12 @@ private:
 	void onPayButtonClicked();
 	void onFocusReceived();
 
+	void onClickMuteVolume();
+	void onClickBlock();
+	void onClickUnblock();
+	/*virtual*/ void draw();
+	void onVolumeChange(const LLSD& data);
+
 	LLUUID mAvatarID;
 };
 
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index c2729fa19bd395d4d3fd5ca936c0eb55911d17e4..a9cc247d1b81ca7a728c0874c2ea9f3fff6091c0 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -46,6 +46,7 @@
 #include "llfolderviewitem.h"
 #include "llinventorymodelbackgroundfetch.h"
 #include "llinventorypanel.h"
+#include "llinventoryfunctions.h"
 #include "lllandmarkactions.h"
 #include "llmenubutton.h"
 #include "llplacesinventorybridge.h"
@@ -529,7 +530,7 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
 // virtual
 void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
 {
-	llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+	llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
 }
 
 
@@ -645,7 +646,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI
 	// Start background fetch, mostly for My Inventory and Library
 	if (expanded)
 	{
-		const LLUUID &cat_id = inventory_list->getStartFolderID();
+		const LLUUID &cat_id = inventory_list->getRootFolderID();
 		// Just because the category itself has been fetched, doesn't mean its child folders have.
 		/*
 		  if (!gInventory.isCategoryComplete(cat_id))
@@ -1414,7 +1415,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin
 
 static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)
 {
-	LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID());
+	LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getRootFolderID());
 	if (category)
 	{
 		return category->getDescendentCount() > 0;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index bc4998dd0cfd170244cfc4a15a285525360704e0..1920cc29409675b14f6c9751f40741ba51275430 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1,6 +1,6 @@
 /** 
- * @file llsidepanelmaininventory.cpp
- * @brief Implementation of llsidepanelmaininventory.
+ * @file llpanelmaininventory.cpp
+ * @brief Implementation of llpanelmaininventory.
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -95,8 +95,8 @@ private:
 /// LLPanelMainInventory
 ///----------------------------------------------------------------------------
 
-LLPanelMainInventory::LLPanelMainInventory()
-	: LLPanel(),
+LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
+	: LLPanel(p),
 	  mActivePanel(NULL),
 	  mSavedFolderState(NULL),
 	  mFilterText(""),
@@ -193,6 +193,9 @@ BOOL LLPanelMainInventory::postBuild()
 	mMenuAdd->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
 	mMenuAdd->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
 
+	// Trigger callback for focus received so we can deselect items in inbox/outbox
+	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
+
 	return TRUE;
 }
 
@@ -572,6 +575,27 @@ void LLPanelMainInventory::updateItemcountText()
 	getChild<LLUICtrl>("ItemcountText")->setValue(text);
 }
 
+void LLPanelMainInventory::onFocusReceived()
+{
+	LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+	LLInventoryPanel * inbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+
+	if (inbox_panel)
+	{
+		inbox_panel->clearSelection();
+	}
+
+	LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
+
+	if (outbox_panel)
+	{
+		outbox_panel->clearSelection();
+	}
+
+	sidepanel_inventory->updateVerbs();
+}
+
 void LLPanelMainInventory::setFilterTextFromFilter() 
 { 
 	mFilterText = mActivePanel->getFilter()->getFilterText(); 
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 2b2ee1c0c9fc17c83a01562dbfcb5b14b70bddf8..899931aa89778182194223d8fe5407f913c1a774 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -57,7 +57,7 @@ class LLPanelMainInventory : public LLPanel, LLInventoryObserver
 public:
 	friend class LLFloaterInventoryFinder;
 
-	LLPanelMainInventory();
+	LLPanelMainInventory(const LLPanel::Params& p = getDefaultParams());
 	~LLPanelMainInventory();
 
 	BOOL postBuild();
@@ -114,6 +114,8 @@ protected:
 	bool isSaveTextureEnabled(const LLSD& userdata);
 	void updateItemcountText();
 
+	void onFocusReceived();
+
 private:
 	LLFloaterInventoryFinder* getFinder();
 
diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..af74f8f26133ae010dab2d97c57463531e9667eb
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinbox.cpp
@@ -0,0 +1,248 @@
+/** 
+ * @file llpanelmarketplaceinbox.cpp
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&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 "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinbox.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llinventorypanel.h"
+#include "llfolderview.h"
+#include "llsidepanelinventory.h"
+
+
+#define SUPPORTING_FRESH_ITEM_COUNT	0
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceInbox> t_panel_marketplace_inbox("panel_marketplace_inbox");
+
+const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams() 
+{ 
+	return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceInbox>(); 
+}
+
+// protected
+LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p)
+	: LLPanel(p)
+	, mInventoryPanel(NULL)
+{
+}
+
+LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox()
+{
+}
+
+// virtual
+BOOL LLPanelMarketplaceInbox::postBuild()
+{
+	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceInbox::handleLoginComplete, this));
+
+	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this));
+	
+	return TRUE;
+}
+
+void LLPanelMarketplaceInbox::onSelectionChange()
+{
+	LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+		
+	sidepanel_inventory->updateVerbs();
+}
+
+
+void LLPanelMarketplaceInbox::handleLoginComplete()
+{
+	// Set us up as the class to drive the badge value for the sidebar_inventory button
+	LLSideTray::getInstance()->setTabButtonBadgeDriver("sidebar_inventory", this);
+}
+
+void LLPanelMarketplaceInbox::setupInventoryPanel()
+{
+	LLView * inbox_inventory_placeholder = getChild<LLView>("inbox_inventory_placeholder");
+	LLView * inbox_inventory_parent = inbox_inventory_placeholder->getParent();
+
+	mInventoryPanel = 
+		LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_inbox_inventory.xml",
+														  inbox_inventory_parent,
+														  LLInventoryPanel::child_registry_t::instance());
+	
+	// Reshape the inventory to the proper size
+	LLRect inventory_placeholder_rect = inbox_inventory_placeholder->getRect();
+	mInventoryPanel->setShape(inventory_placeholder_rect);
+	
+	// Set the sort order newest to oldest, and a selection change callback
+	mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	
+	mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));
+
+	// Set up the note to display when the inbox is empty
+	mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems");
+	
+	// Hide the placeholder text
+	inbox_inventory_placeholder->setVisible(FALSE);
+}
+
+void LLPanelMarketplaceInbox::onFocusReceived()
+{
+	LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+	if (sidepanel_inventory)
+	{
+		LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
+
+		if (inv_panel)
+		{
+			inv_panel->clearSelection();
+		}
+	
+		LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
+
+		if (outbox_panel)
+		{
+			outbox_panel->clearSelection();
+		}
+		
+		sidepanel_inventory->updateVerbs();
+	}
+}
+
+BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
+{
+	*accept = ACCEPT_NO;
+	return TRUE;
+}
+
+U32 LLPanelMarketplaceInbox::getFreshItemCount() const
+{
+#if SUPPORTING_FRESH_ITEM_COUNT
+	
+	//
+	// NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably
+	//       will return "2" for the Inventory and LIBRARY top-levels when that happens.
+	//
+	
+	U32 fresh_item_count = 0;
+
+	if (mInventoryPanel)
+	{
+		const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+		
+		if (inbox_folder)
+		{
+			LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin();
+			LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd();
+
+			for (; folders_it != folders_end; ++folders_it)
+			{
+				const LLFolderViewFolder * folder = *folders_it;
+
+				// TODO: Replace this check with new "fresh" flag
+				if (folder->getCreationDate() > 1500)
+				{
+					fresh_item_count++;
+				}
+			}
+		}
+	}
+
+	return fresh_item_count;
+#else
+	return getTotalItemCount();
+#endif
+}
+
+U32 LLPanelMarketplaceInbox::getTotalItemCount() const
+{
+	U32 item_count = 0;
+	
+	if (mInventoryPanel)
+	{
+		const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+		
+		if (inbox_folder)
+		{
+			item_count += inbox_folder->getFoldersCount();
+		}
+	}
+	
+	return item_count;
+}
+
+std::string LLPanelMarketplaceInbox::getBadgeString() const
+{
+	std::string item_count_str("");
+
+	// If the inbox is visible, and the side panel is collapsed or expanded and not the inventory panel
+	if (getParent()->getVisible() &&
+		(LLSideTray::getInstance()->getCollapsed() || !LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")))
+	{
+		U32 item_count = getFreshItemCount();
+
+		if (item_count)
+		{
+			item_count_str = llformat("%d", item_count);
+		}
+	}
+
+	return item_count_str;
+}
+
+void LLPanelMarketplaceInbox::draw()
+{
+	U32 item_count = getTotalItemCount();
+
+	LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count");
+
+	if (item_count > 0)
+	{
+		std::string item_count_str = llformat("%d", item_count);
+
+		LLStringUtil::format_map_t args;
+		args["[NUM]"] = item_count_str;
+		getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args));
+
+#if SUPPORTING_FRESH_ITEM_COUNT
+		// set green text to fresh item count
+		U32 fresh_item_count = getFreshItemCount();
+		fresh_new_count_view->setVisible((fresh_item_count > 0));
+
+		if (fresh_item_count > 0)
+		{
+			getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count));
+		}
+#else
+		fresh_new_count_view->setVisible(FALSE);
+#endif
+	}
+	else
+	{
+		getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg"));
+
+		fresh_new_count_view->setVisible(FALSE);
+	}
+		
+	LLPanel::draw();
+}
diff --git a/indra/newview/llpanelmarketplaceinbox.h b/indra/newview/llpanelmarketplaceinbox.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ecea29304295719ca31440414f5dc396d9312f4
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinbox.h
@@ -0,0 +1,78 @@
+/** 
+ * @file llpanelmarketplaceinbox.h
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&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_LLPANELMARKETPLACEINBOX_H
+#define LL_LLPANELMARKETPLACEINBOX_H
+
+#include "llpanel.h"
+#include "llsidetray.h"
+
+class LLInventoryPanel;
+
+class LLPanelMarketplaceInbox : public LLPanel, public LLSideTrayTabBadgeDriver
+{
+public:
+
+	struct Params :	public LLInitParam::Block<Params, LLPanel::Params>
+	{
+		Params() {}
+	};
+
+	LOG_CLASS(LLPanelMarketplaceInbox);
+
+	// RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
+	static const LLPanelMarketplaceInbox::Params& getDefaultParams();
+
+	LLPanelMarketplaceInbox(const Params& p = getDefaultParams());
+	~LLPanelMarketplaceInbox();
+
+	/*virtual*/ BOOL postBuild();
+	
+	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg);
+
+	/*virtual*/ void draw();
+	
+	void setupInventoryPanel();
+
+	U32 getFreshItemCount() const;
+	U32 getTotalItemCount() const;
+
+	std::string getBadgeString() const;
+
+private:
+	void handleLoginComplete();
+
+	void onSelectionChange();
+
+	void onFocusReceived();
+
+private:
+	LLInventoryPanel* mInventoryPanel;
+};
+
+
+#endif //LL_LLPANELMARKETPLACEINBOX_H
+
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b644f0e5cbeb6a7740ec6402005052e3424dca67
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp
@@ -0,0 +1,167 @@
+/** 
+ * @file llpanelmarketplaceinboxinventory.cpp
+ * @brief LLInboxInventoryPanel  class definition
+ *
+ * $LicenseInfo:firstyear=2009&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 "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinboxinventory.h"
+
+#include "llfolderview.h"
+#include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llpanellandmarks.h"
+#include "llplacesinventorybridge.h"
+#include "llviewerfoldertype.h"
+
+
+//
+// statics
+//
+
+static LLDefaultChildRegistry::Register<LLInboxInventoryPanel> r1("inbox_inventory_panel");
+static LLDefaultChildRegistry::Register<LLInboxFolderViewFolder> r2("inbox_folder_view_folder");
+
+
+//
+// LLInboxInventoryPanel Implementation
+//
+
+LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params& p)
+	: LLInventoryPanel(p)
+{
+}
+
+LLInboxInventoryPanel::~LLInboxInventoryPanel()
+{
+}
+
+// virtual
+void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
+{
+	// Determine the root folder in case specified, and
+	// build the views starting with that folder.
+	
+	LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false);
+	
+	// leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+	if (root_id.isNull())
+	{
+		std::string start_folder_name(params.start_folder());
+		
+		LLInventoryModel::cat_array_t* cats;
+		LLInventoryModel::item_array_t* items;
+		
+		gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+		
+		if (cats)
+		{
+			for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+			{
+				LLInventoryCategory* cat = *cat_it;
+				
+				if (cat->getName() == start_folder_name)
+				{
+					root_id = cat->getUUID();
+					break;
+				}
+			}
+		}
+		
+		if (root_id == LLUUID::null)
+		{
+			llwarns << "No category found that matches inbox inventory panel start_folder: " << start_folder_name << llendl;
+		}
+	}
+	// leslie -- end temporary HACK
+	
+	if (root_id == LLUUID::null)
+	{
+		llwarns << "Inbox inventory panel has no root folder!" << llendl;
+		root_id = LLUUID::generateNewID();
+	}
+	
+	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+																	LLAssetType::AT_CATEGORY,
+																	LLInventoryType::IT_CATEGORY,
+																	this,
+																	NULL,
+																	root_id);
+	
+	mFolderRoot = createFolderView(new_listener, params.use_label_suffix());
+}
+
+LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
+{
+	LLInboxFolderViewFolder::Params params;
+	
+	params.name = bridge->getDisplayName();
+	params.icon = bridge->getIcon();
+	params.icon_open = bridge->getOpenIcon();
+	
+	if (mShowItemLinkOverlays) // if false, then links show up just like normal items
+	{
+		params.icon_overlay = LLUI::getUIImage("Inv_Link");
+	}
+	
+	params.root = mFolderRoot;
+	params.listener = bridge;
+	params.tool_tip = params.name;
+	
+	return LLUICtrlFactory::create<LLInboxFolderViewFolder>(params);
+}
+
+
+//
+// LLInboxFolderViewFolder Implementation
+//
+
+LLInboxFolderViewFolder::LLInboxFolderViewFolder(const Params& p)
+	: LLFolderViewFolder(p)
+	, LLBadgeOwner(getHandle())
+	, mFresh(false)
+{
+	initBadgeParams(p.new_badge());
+}
+
+LLInboxFolderViewFolder::~LLInboxFolderViewFolder()
+{
+}
+
+// virtual
+void LLInboxFolderViewFolder::draw()
+{
+	if (!badgeHasParent())
+	{
+		addBadgeToParentPanel();
+	}
+	
+	setBadgeVisibility(mFresh);
+
+	LLFolderViewFolder::draw();
+}
+
+
+// eof
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f198c41c1aa69b98f0c3a3d41ddd8b5efde8db9
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinboxinventory.h
@@ -0,0 +1,77 @@
+/** 
+ * @file llpanelmarketplaceinboxinventory.h
+ * @brief LLInboxInventoryPanel class declaration
+ *
+ * $LicenseInfo:firstyear=2009&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_INBOXINVENTORYPANEL_H
+#define LL_INBOXINVENTORYPANEL_H
+
+
+#include "llbadgeowner.h"
+#include "llinventorypanel.h"
+#include "llfolderviewitem.h"
+
+class LLInboxInventoryPanel : public LLInventoryPanel
+{
+public:
+	struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+	{
+		Params() {}
+	};
+	
+	LLInboxInventoryPanel(const Params& p);
+	~LLInboxInventoryPanel();
+
+	// virtual
+	void buildFolderView(const LLInventoryPanel::Params& params);
+
+	// virtual
+	class LLFolderViewFolder*	createFolderViewFolder(LLInvFVBridge * bridge);
+};
+
+
+class LLInboxFolderViewFolder : public LLFolderViewFolder, public LLBadgeOwner
+{
+public:
+	struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params>
+	{
+		Optional<LLBadge::Params>	new_badge;
+		
+		Params()
+		: new_badge("new_badge")
+		{
+		}
+	};
+	
+	LLInboxFolderViewFolder(const Params& p);
+	~LLInboxFolderViewFolder();
+	
+	void draw();
+	
+protected:
+	bool	mFresh;
+};
+
+
+#endif //LL_INBOXINVENTORYPANEL_H
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74d0de3b304d239816bfa2f7e9e2c35545952add
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -0,0 +1,209 @@
+/** 
+ * @file llpanelmarketplaceoutbox.cpp
+ * @brief Panel for marketplace outbox
+ *
+* $LicenseInfo:firstyear=2011&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 "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceoutbox.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llinventorypanel.h"
+#include "llloadingindicator.h"
+#include "llpanelmarketplaceinbox.h"
+#include "llsidepanelinventory.h"
+#include "llsidetray.h"
+#include "lltimer.h"
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox");
+
+const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams() 
+{ 
+	return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceOutbox>(); 
+}
+
+// protected
+LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p)
+	: LLPanel(p)
+	, mInventoryPanel(NULL)
+	, mSyncButton(NULL)
+	, mSyncIndicator(NULL)
+	, mSyncInProgress(false)
+{
+}
+
+LLPanelMarketplaceOutbox::~LLPanelMarketplaceOutbox()
+{
+}
+
+// virtual
+BOOL LLPanelMarketplaceOutbox::postBuild()
+{
+	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceOutbox::handleLoginComplete, this));
+	
+	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceOutbox::onFocusReceived, this));
+
+	return TRUE;
+}
+
+void LLPanelMarketplaceOutbox::handleLoginComplete()
+{
+	mSyncButton = getChild<LLButton>("outbox_sync_btn");
+	mSyncButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onSyncButtonClicked, this));
+	mSyncButton->setEnabled(!isOutboxEmpty());
+	
+	mSyncIndicator = getChild<LLLoadingIndicator>("outbox_sync_indicator");
+}
+
+void LLPanelMarketplaceOutbox::onFocusReceived()
+{
+	LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+	if (sidepanel_inventory)
+	{
+		LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
+
+		if (inv_panel)
+		{
+			inv_panel->clearSelection();
+		}
+
+		LLInventoryPanel * inbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+
+		if (inbox_panel)
+		{
+			inbox_panel->clearSelection();
+		}
+		
+		sidepanel_inventory->updateVerbs();
+	}
+}
+
+void LLPanelMarketplaceOutbox::onSelectionChange()
+{
+	LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+	
+	sidepanel_inventory->updateVerbs();
+}
+
+void LLPanelMarketplaceOutbox::setupInventoryPanel()
+{
+	LLView * outbox_inventory_placeholder = getChild<LLView>("outbox_inventory_placeholder");
+	LLView * outbox_inventory_parent = outbox_inventory_placeholder->getParent();
+	
+	mInventoryPanel = 
+		LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml",
+														  outbox_inventory_parent,
+														  LLInventoryPanel::child_registry_t::instance());
+	
+	// Reshape the inventory to the proper size
+	LLRect inventory_placeholder_rect = outbox_inventory_placeholder->getRect();
+	mInventoryPanel->setShape(inventory_placeholder_rect);
+	
+	// Set the sort order newest to oldest, and a selection change callback
+	mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	
+	mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this));
+	
+	// Set up the note to display when the outbox is empty
+	mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryOutboxNoItems");
+	
+	// Hide the placeholder text
+	outbox_inventory_placeholder->setVisible(FALSE);
+}
+
+bool LLPanelMarketplaceOutbox::isOutboxEmpty() const
+{
+	// TODO: Check for contents of outbox
+
+	return false;
+}
+
+bool LLPanelMarketplaceOutbox::isSyncInProgress() const
+{
+	return mSyncInProgress;
+}
+
+
+std::string gTimeDelayDebugFunc = "";
+
+void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
+{
+	waitForEventOn(self, "mainloop");
+
+	LLTimer delayTimer;
+	delayTimer.reset();
+	delayTimer.setTimerExpirySec(5.0f);
+
+	while (!delayTimer.hasExpired())
+	{
+		waitForEventOn(self, "mainloop");
+	}
+
+	outboxPanel->onSyncComplete();
+
+	gTimeDelayDebugFunc = "";
+}
+
+void LLPanelMarketplaceOutbox::onSyncButtonClicked()
+{
+	// TODO: Actually trigger sync to marketplace
+
+	mSyncInProgress = true;
+	updateSyncButtonStatus();
+
+	// Set a timer (for testing only)
+
+    gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
+}
+
+void LLPanelMarketplaceOutbox::onSyncComplete()
+{
+	mSyncInProgress = false;
+
+	updateSyncButtonStatus();
+}
+
+void LLPanelMarketplaceOutbox::updateSyncButtonStatus()
+{
+	if (isSyncInProgress())
+	{
+		mSyncButton->setVisible(false);
+
+		mSyncIndicator->setVisible(true);
+		mSyncIndicator->reset();
+		mSyncIndicator->start();
+	}
+	else
+	{
+		mSyncIndicator->stop();
+		mSyncIndicator->setVisible(false);
+
+		mSyncButton->setVisible(true);
+		mSyncButton->setEnabled(!isOutboxEmpty());
+	}
+}
diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b502127efe26b96f9bcde69d74c1ffd202edcd0
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceoutbox.h
@@ -0,0 +1,82 @@
+/** 
+ * @file llpanelmarketplaceoutbox.h
+ * @brief Panel for marketplace outbox
+ *
+* $LicenseInfo:firstyear=2011&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_LLPANELMARKETPLACEOUTBOX_H
+#define LL_LLPANELMARKETPLACEOUTBOX_H
+
+#include "llpanel.h"
+
+
+class LLButton;
+class LLInventoryPanel;
+class LLLoadingIndicator;
+
+
+class LLPanelMarketplaceOutbox : public LLPanel
+{
+public:
+	
+	struct Params :	public LLInitParam::Block<Params, LLPanel::Params>
+	{
+		Params() {}
+	};
+	
+	LOG_CLASS(LLPanelMarketplaceOutbox);
+
+	// RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
+	static const LLPanelMarketplaceOutbox::Params& getDefaultParams();
+	
+	LLPanelMarketplaceOutbox(const Params& p = getDefaultParams());
+	~LLPanelMarketplaceOutbox();
+
+	/*virtual*/ BOOL postBuild();
+
+	void setupInventoryPanel();
+
+	bool isOutboxEmpty() const;
+	bool isSyncInProgress() const;
+
+	void onSyncComplete();
+
+protected:
+	void onSyncButtonClicked();
+	void updateSyncButtonStatus();
+
+	void handleLoginComplete();
+	void onFocusReceived();
+	void onSelectionChange();
+
+private:
+	LLInventoryPanel *		mInventoryPanel;
+
+	LLButton *				mSyncButton;
+	LLLoadingIndicator *	mSyncIndicator;
+	bool					mSyncInProgress;
+};
+
+
+#endif //LL_LLPANELMARKETPLACEOUTBOX_H
+
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index bfe6cab52f378969b6b51b8874eb2e44d11b68e9..e3b61f695a3c57b23e5ed981b5a467045a8c256e 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -44,6 +44,7 @@
 #include "llcallbacklist.h"
 #include "llbuycurrencyhtml.h"
 #include "llfloaterreg.h"
+#include "llfolderview.h"
 #include "llinventorybridge.h"
 #include "llinventorydefines.h"
 #include "llinventoryfilter.h"
@@ -58,8 +59,10 @@
 #include "llselectmgr.h"
 #include "llsidetray.h"
 #include "llstatusbar.h"
+#include "lltooldraganddrop.h"
 #include "lltrans.h"
 #include "llviewerassettype.h"
+#include "llviewerinventory.h"
 #include "llviewerregion.h"
 #include "llviewerobjectlist.h"
 #include "llviewermessage.h"
@@ -761,7 +764,7 @@ void LLTaskCategoryBridge::openItem()
 BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
 {
 	//llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
-	if(mPanel)
+	if(mPanel && mUUID.notNull())
 	{
 		LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
 		if(object)
@@ -1349,79 +1352,81 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*
 	LLTaskInvFVBridge* new_bridge = NULL;
 	const LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(object);
 	const U32 itemflags = ( NULL == item ? 0 : item->getFlags() );
-	LLAssetType::EType type = object->getType();
+	LLAssetType::EType type = object ? object->getType() : LLAssetType::AT_CATEGORY;
+	LLUUID object_id = object ? object->getUUID() : LLUUID::null;
+	std::string object_name = object ? object->getName() : std::string();
 
 	switch(type)
 	{
 	case LLAssetType::AT_TEXTURE:
 		new_bridge = new LLTaskTextureBridge(panel,
-						     object->getUUID(),
-						     object->getName());
+						     object_id,
+						     object_name);
 		break;
 	case LLAssetType::AT_SOUND:
 		new_bridge = new LLTaskSoundBridge(panel,
-						   object->getUUID(),
-						   object->getName());
+						   object_id,
+						   object_name);
 		break;
 	case LLAssetType::AT_LANDMARK:
 		new_bridge = new LLTaskLandmarkBridge(panel,
-						      object->getUUID(),
-						      object->getName());
+						      object_id,
+						      object_name);
 		break;
 	case LLAssetType::AT_CALLINGCARD:
 		new_bridge = new LLTaskCallingCardBridge(panel,
-							 object->getUUID(),
-							 object->getName());
+							 object_id,
+							 object_name);
 		break;
 	case LLAssetType::AT_SCRIPT:
 		// OLD SCRIPTS DEPRECATED - JC
 		llwarns << "Old script" << llendl;
 		//new_bridge = new LLTaskOldScriptBridge(panel,
-		//									   object->getUUID(),
-		//									   object->getName());
+		//									   object_id,
+		//									   object_name);
 		break;
 	case LLAssetType::AT_OBJECT:
 		new_bridge = new LLTaskObjectBridge(panel,
-						    object->getUUID(),
-						    object->getName(),
+						    object_id,
+						    object_name,
 						    itemflags);
 		break;
 	case LLAssetType::AT_NOTECARD:
 		new_bridge = new LLTaskNotecardBridge(panel,
-						      object->getUUID(),
-						      object->getName());
+						      object_id,
+						      object_name);
 		break;
 	case LLAssetType::AT_ANIMATION:
 		new_bridge = new LLTaskAnimationBridge(panel,
-						       object->getUUID(),
-						       object->getName());
+						       object_id,
+						       object_name);
 		break;
 	case LLAssetType::AT_GESTURE:
 		new_bridge = new LLTaskGestureBridge(panel,
-						     object->getUUID(),
-						     object->getName());
+						     object_id,
+						     object_name);
 		break;
 	case LLAssetType::AT_CLOTHING:
 	case LLAssetType::AT_BODYPART:
 		new_bridge = new LLTaskWearableBridge(panel,
-						      object->getUUID(),
-						      object->getName(),
+						      object_id,
+						      object_name,
 						      itemflags);
 		break;
 	case LLAssetType::AT_CATEGORY:
 		new_bridge = new LLTaskCategoryBridge(panel,
-						      object->getUUID(),
-						      object->getName());
+						      object_id,
+						      object_name);
 		break;
 	case LLAssetType::AT_LSL_TEXT:
 		new_bridge = new LLTaskLSLBridge(panel,
-						 object->getUUID(),
-						 object->getName());
+						 object_id,
+						 object_name);
 		break;
 	case LLAssetType::AT_MESH:
 		new_bridge = new LLTaskMeshBridge(panel,
-										  object->getUUID(),
-										  object->getName());
+										  object_id,
+										  object_name);
 		break;
 	default:
 		llinfos << "Unhandled inventory type (llassetstorage.h): "
@@ -1521,6 +1526,7 @@ void LLPanelObjectInventory::reset()
 	p.task_id = getTaskUUID();
 	p.parent_panel = this;
 	p.tool_tip= LLTrans::getString("PanelContentsTooltip");
+	p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL);
 	mFolders = LLUICtrlFactory::create<LLFolderView>(p);
 	// this ensures that we never say "searching..." or "no items found"
 	mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 62f582c34366c9e4a92fca6aa8e196ba922c285e..35e2e96bab8effdac176544724408faa4ba72339 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -36,7 +36,7 @@
 #include "lloutfitobserver.h"
 #include "llcofwearables.h"
 #include "llfilteredwearablelist.h"
-#include "llfolderviewitem.h"
+#include "llfolderview.h"
 #include "llinventory.h"
 #include "llinventoryitemslist.h"
 #include "llviewercontrol.h"
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index 911a9e5ddadf064773f4c9ab943ef6ae8d3c5287..0645fd8a54a23b1728a27b111931a45c2fcf07f4 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -174,8 +174,8 @@ LLPanelWearing::~LLPanelWearing()
 	if (gInventory.containsObserver(mCategoriesObserver))
 	{
 		gInventory.removeObserver(mCategoriesObserver);
-		delete mCategoriesObserver;
 	}
+	delete mCategoriesObserver;
 }
 
 BOOL LLPanelWearing::postBuild()
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
index 29e262199e3fea24c028338b372f4b83610500bd..f7823f4fe86938cfd3dd91262a7bc28ac0da93f3 100644
--- a/indra/newview/llplacesinventorypanel.cpp
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -35,6 +35,7 @@
 #include "llinventoryfunctions.h"
 #include "llpanellandmarks.h"
 #include "llplacesinventorybridge.h"
+#include "llviewerfoldertype.h"
 
 static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel");
 
@@ -56,72 +57,44 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel()
 	delete mSavedFolderState;
 }
 
-BOOL LLPlacesInventoryPanel::postBuild()
+void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
 {
-	LLInventoryPanel::postBuild();
+	// Determine the root folder in case specified, and
+	// build the views starting with that folder.
+	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(params.start_folder);
 
-	// clear Contents();
-	{
-		mFolderRoot->destroyView();
-		mFolderRoot->getParent()->removeChild(mFolderRoot);
-		mFolderRoot->die();
-
-		if( mScroller )
-		{
-			removeChild( mScroller );
-			mScroller->die();
-			mScroller = NULL;
-		}
-		mFolderRoot = NULL;
-	}
-
-
-	mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+	LLUUID root_id;
 
-	// create root folder
+	if ("LIBRARY" == params.start_folder())
 	{
-		LLRect folder_rect(0,
-			0,
-			getRect().getWidth(),
-			0);
-		LLPlacesFolderView::Params p;
-		p.name = getName();
-		p.title = getLabel();
-		p.rect = folder_rect;
-		p.parent_panel = this;
-		mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
-		mFolderRoot->setAllowMultiSelect(mAllowMultiSelect);
+		root_id = gInventory.getLibraryRootFolderID();
 	}
-
-	mCommitCallbackRegistrar.popScope();
-
-	mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
-
-	// scroller
+	else
 	{
-		LLRect scroller_view_rect = getRect();
-		scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
-		LLScrollContainer::Params p;
-		p.name("Inventory Scroller");
-		p.rect(scroller_view_rect);
-		p.follows.flags(FOLLOWS_ALL);
-		p.reserve_scroll_corner(true);
-		p.tab_stop(true);
-		mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+		root_id = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
 	}
-	addChild(mScroller);
-	mScroller->addChild(mFolderRoot);
-
-	mFolderRoot->setScrollContainer(mScroller);
-	mFolderRoot->addChild(mFolderRoot->mStatusTextBox);
 
-
-	// cut subitems
-	mFolderRoot->setUseEllipses(true);
-
-	return TRUE;
+	LLRect folder_rect(0,
+		0,
+		getRect().getWidth(),
+		0);
+	LLPlacesFolderView::Params p;
+	p.name = getName();
+	p.title = getLabel();
+	p.rect = folder_rect;
+	p.listener =  mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+													LLAssetType::AT_CATEGORY,
+													LLInventoryType::IT_CATEGORY,
+													this,
+													NULL,
+													root_id);
+	p.parent_panel = this;
+	p.allow_multiselect = mAllowMultiSelect;
+	p.use_ellipses = true;	// truncate inventory item text so remove horizontal scroller
+	mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
 }
 
+
 // save current folder open state
 void LLPlacesInventoryPanel::saveFolderState()
 {
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
index 6641871a0bfc279b86bd2c8ac637da4726805d27..f647e7f970e5dc90f9f33b0c8bb00362f6e46f34 100644
--- a/indra/newview/llplacesinventorypanel.h
+++ b/indra/newview/llplacesinventorypanel.h
@@ -46,7 +46,7 @@ public:
 	LLPlacesInventoryPanel(const Params& p);
 	~LLPlacesInventoryPanel();
 
-	/*virtual*/ BOOL postBuild();
+	/*virtual*/ void buildFolderView(const LLInventoryPanel::Params& params);
 
 	void saveFolderState();
 	void restoreFolderState();
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 9f5c55bad124c673d14131a4cc262a23b198e822..f47928b1314896c7eabdd84c5d985ea727aa6393 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -42,6 +42,7 @@
 #include "llinventoryfunctions.h"
 #include "llinventorymodel.h"
 #include "llinventorymodelbackgroundfetch.h"
+#include "llkeyboard.h"
 #include "llmultigesture.h"
 #include "llnotificationsutil.h"
 #include "llradiogroup.h"
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 31fde5d58aedfd401c40c46aa6069055ad420a11..028891a90e5bf85a540f6a37bd1e8101d053767d 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -55,23 +55,18 @@ LLProgressView* LLProgressView::sInstance = NULL;
 
 S32 gStartImageWidth = 1;
 S32 gStartImageHeight = 1;
-const F32 FADE_IN_TIME = 1.f;
-
-const std::string ANIMATION_FILENAME = "Login Sequence ";
-const std::string ANIMATION_SUFFIX = ".jpg";
-const F32 TOTAL_LOGIN_TIME = 10.f;	// seconds, wild guess at time from GL context to actual world view
-S32 gLastStartAnimationFrame = 0;	// human-style indexing, first image = 1
-const S32 ANIMATION_FRAMES = 1; //13;
+const F32 FADE_TO_WORLD_TIME = 1.0f;
 
 static LLRegisterPanelClassWrapper<LLProgressView> r("progress_view");
 
-
 // XUI: Translate
 LLProgressView::LLProgressView() 
 :	LLPanel(),
 	mPercentDone( 0.f ),
+	mMediaCtrl( NULL ),
 	mMouseDownInActiveArea( false ),
-	mUpdateEvents("LLProgressView")
+	mUpdateEvents("LLProgressView"),
+	mFadeToWorldTimer()
 {
 	mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));
 }
@@ -80,9 +75,14 @@ BOOL LLProgressView::postBuild()
 {
 	mProgressBar = getChild<LLProgressBar>("login_progress_bar");
 
+	// media control that is used to play intro video
+	mMediaCtrl = getChild<LLMediaCtrl>("login_media_panel");
+	mMediaCtrl->setVisible( false );		// hidden initially
+	mMediaCtrl->addObserver( this );		// watch events
+
 	mCancelBtn = getChild<LLButton>("cancel_btn");
 	mCancelBtn->setClickedCallback(  LLProgressView::onCancelButtonClicked, NULL );
-	mFadeTimer.stop();
+	mFadeToWorldTimer.stop();
 
 	getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle()));
 
@@ -125,24 +125,43 @@ BOOL LLProgressView::handleKeyHere(KEY key, MASK mask)
 	return TRUE;
 }
 
+void LLProgressView::revealIntroPanel()
+{
+	// if user hasn't yet seen intro video
+	std::string intro_url = gSavedSettings.getString("PostFirstLoginIntroURL");
+	if ( intro_url.length() > 0 && 
+			gSavedSettings.getBOOL("PostFirstLoginIntroViewed" ) == FALSE )
+	{
+		// navigate to intro URL and reveal widget 
+		mMediaCtrl->navigateTo( intro_url );	
+		mMediaCtrl->setVisible( TRUE );
+
+		// flag as having seen the new user post login intro
+		gSavedSettings.setBOOL("PostFirstLoginIntroViewed", TRUE );
+	}
+	else
+	{
+		// start the timer that will control the fade through to the world view 
+		mFadeToWorldTimer.start();
+	}
+}
+
 void LLProgressView::setVisible(BOOL visible)
 {
 	// hiding progress view
 	if (getVisible() && !visible)
 	{
-		mFadeTimer.start();
+		LLPanel::setVisible(FALSE);
 	}
 	// showing progress view
-	else if (visible && (!getVisible() || mFadeTimer.getStarted()))
+	else if (visible && (!getVisible() || mFadeToWorldTimer.getStarted()))
 	{
 		setFocus(TRUE);
-		mFadeTimer.stop();
-		mProgressTimer.start();
+		mFadeToWorldTimer.stop();
 		LLPanel::setVisible(TRUE);
 	} 
 }
 
-
 void LLProgressView::draw()
 {
 	static LLTimer timer;
@@ -153,7 +172,7 @@ void LLProgressView::draw()
 	{
 		LLGLSUIDefault gls_ui;
 		gGL.getTexUnit(0)->bind(gStartTexture.get());
-		gGL.color4f(1.f, 1.f, 1.f, mFadeTimer.getStarted() ? clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, FADE_IN_TIME, 1.f, 0.f) : 1.f);
+		gGL.color4f(1.f, 1.f, 1.f, 1.f);
 		F32 image_aspect = (F32)gStartImageWidth / (F32)gStartImageHeight;
 		S32 width = getRect().getWidth();
 		S32 height = getRect().getHeight();
@@ -180,16 +199,36 @@ void LLProgressView::draw()
 	}
 	glPopMatrix();
 
-	// Handle fade-in animation
-	if (mFadeTimer.getStarted())
+	// handle fade out to world view when we're asked to
+	if (mFadeToWorldTimer.getStarted())
 	{
+		// draw fading panel
+		F32 alpha = clamp_rescale(mFadeToWorldTimer.getElapsedTimeF32(), 0.f, FADE_TO_WORLD_TIME, 1.f, 0.f);
+		LLViewDrawContext context(alpha);
 		LLPanel::draw();
-		if (mFadeTimer.getElapsedTimeF32() > FADE_IN_TIME)
+
+		// faded out completely - remove panel and reveal world
+		if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME )
 		{
+			mFadeToWorldTimer.stop();
+
 			// Fade is complete, release focus
 			gFocusMgr.releaseFocusIfNeeded( this );
+
+			// turn off panel that hosts intro so we see the world
 			LLPanel::setVisible(FALSE);
-			mFadeTimer.stop();
+
+			// stop observing events since we no longer care
+			mMediaCtrl->remObserver( this );
+
+			// hide the intro
+			mMediaCtrl->setVisible( false );
+
+			// navigate away from intro page to something innocuous since 'unload' is broken right now
+			//mMediaCtrl->navigateTo( "about:blank" );
+
+			// FIXME: this causes a crash that i haven't been able to fix
+			mMediaCtrl->unloadMediaSource();	
 
 			gStartTexture = NULL;
 		}
@@ -307,3 +346,12 @@ bool LLProgressView::onAlertModal(const LLSD& notify)
 	}
 	return false;
 }
+
+void LLProgressView::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+	if( event == MEDIA_EVENT_CLOSE_REQUEST )
+	{
+		// the intro web content calls javascript::window.close() when it's done
+		mFadeToWorldTimer.start();
+	}
+}
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index be1744f08a57e81b7e2834b231291a02e27aba83..73dd478e988e367a80cb41270c00aaaef84624c3 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -28,6 +28,7 @@
 #define LL_LLPROGRESSVIEW_H
 
 #include "llpanel.h"
+#include "llmediactrl.h"
 #include "llframetimer.h"
 #include "llevents.h"
 
@@ -35,7 +36,10 @@ class LLImageRaw;
 class LLButton;
 class LLProgressBar;
 
-class LLProgressView : public LLPanel
+class LLProgressView : 
+	public LLPanel,
+	public LLViewerMediaObserver
+
 {
 public:
 	LLProgressView();
@@ -49,25 +53,35 @@ public:
 	/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
 	/*virtual*/ void setVisible(BOOL visible);
 
+	// inherited from LLViewerMediaObserver
+	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
 	void setText(const std::string& text);
 	void setPercent(const F32 percent);
 
 	// Set it to NULL when you want to eliminate the message.
 	void setMessage(const std::string& msg);
 	
+	// turns on (under certain circumstances) the into video after login
+	void revealIntroPanel();
+
 	void setCancelButtonVisible(BOOL b, const std::string& label);
 
 	static void onCancelButtonClicked( void* );
 	static void onClickMessage(void*);
 	bool onAlertModal(const LLSD& sd);
 
+	// note - this is not just hiding the intro panel - it also hides the parent panel
+	// and is used when the intro is finished and we want to show the world
+	void removeIntroPanel();
+
 protected:
 	LLProgressBar* mProgressBar;
+	LLMediaCtrl* mMediaCtrl;
 	F32 mPercentDone;
 	std::string mMessage;
 	LLButton*	mCancelBtn;
-	LLFrameTimer	mFadeTimer;
-	LLFrameTimer mProgressTimer;
+	LLFrameTimer mFadeToWorldTimer;
 	LLRect mOutlineRect;
 	bool mMouseDownInActiveArea;
 
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 16729f045a0d4e91d1182b5a9b017b0af30e7f34..28ec11d1c7b99361ae3d888e8bf9c70c4f40b062 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -32,6 +32,7 @@
 #include "llagentcamera.h"
 #include "llagentwearables.h"
 #include "llappearancemgr.h"
+#include "llfolderview.h"
 #include "llinventorypanel.h"
 #include "llfiltereditor.h"
 #include "llfloaterreg.h"
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 31ea542743db43c87dd5b52cfe715a37fc318e44..65655f82cdbd2fa66f1d1e8ac6196454ec37cc21 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -29,33 +29,147 @@
 
 #include "llagent.h"
 #include "llappearancemgr.h"
+#include "llappviewer.h"
 #include "llavataractions.h"
 #include "llbutton.h"
+#include "lldate.h"
 #include "llfirstuse.h"
+#include "llfoldertype.h"
+#include "llhttpclient.h"
 #include "llinventorybridge.h"
 #include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llinventoryobserver.h"
 #include "llinventorypanel.h"
+#include "lllayoutstack.h"
 #include "lloutfitobserver.h"
 #include "llpanelmaininventory.h"
+#include "llpanelmarketplaceinbox.h"
+#include "llpanelmarketplaceoutbox.h"
+#include "llselectmgr.h"
 #include "llsidepaneliteminfo.h"
 #include "llsidepaneltaskinfo.h"
+#include "llstring.h"
 #include "lltabcontainer.h"
-#include "llselectmgr.h"
+#include "llviewermedia.h"
 #include "llweb.h"
 
 static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory");
 
-LLSidepanelInventory::LLSidepanelInventory()
-	:	LLPanel(),
-		mItemPanel(NULL),
-		mPanelMainInventory(NULL)
+//
+// Constants
+//
+
+static const char * const INBOX_EXPAND_TIME_SETTING = "LastInventoryInboxExpand";
+
+static const char * const INBOX_BUTTON_NAME = "inbox_btn";
+static const char * const OUTBOX_BUTTON_NAME = "outbox_btn";
+
+static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel";
+static const char * const OUTBOX_LAYOUT_PANEL_NAME = "outbox_layout_panel";
+static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel";
+
+static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox";
+static const char * const OUTBOX_INVENTORY_PANEL = "inventory_outbox";
+
+static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack";
+
+static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
+static const char * const MARKETPLACE_OUTBOX_PANEL = "marketplace_outbox";
+
+//
+// Helpers
+//
+
+class LLInboxOutboxAddedObserver : public LLInventoryCategoryAddedObserver
 {
+public:
+	LLInboxOutboxAddedObserver(LLSidepanelInventory * sidepanelInventory)
+		: LLInventoryCategoryAddedObserver()
+		, mSidepanelInventory(sidepanelInventory)
+	{
+	}
+	
+	void done()
+	{
+		for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it)
+		{
+			LLViewerInventoryCategory* added_category = *it;
+			
+			LLFolderType::EType added_category_type = added_category->getPreferredType();
+			
+			switch (added_category_type)
+			{
+				case LLFolderType::FT_INBOX:
+					mSidepanelInventory->observeInboxModifications(added_category->getUUID());
+					break;
+				case LLFolderType::FT_OUTBOX:
+					mSidepanelInventory->observeOutboxModifications(added_category->getUUID());
+					break;
+				case LLFolderType::FT_NONE:
+					// HACK until sim update to properly create folder with system type
+					if (added_category->getName() == "Received Items")
+					{
+						mSidepanelInventory->observeInboxModifications(added_category->getUUID());
+					}
+					else if (added_category->getName() == "Merchant Outbox")
+					{
+						mSidepanelInventory->observeOutboxModifications(added_category->getUUID());
+					}
+				default:
+					break;
+			}
+		}
+	}
+	
+private:
+	LLSidepanelInventory * mSidepanelInventory;
+};
 
+//
+// Implementation
+//
+
+LLSidepanelInventory::LLSidepanelInventory()
+	: LLPanel()
+	, mItemPanel(NULL)
+	, mPanelMainInventory(NULL)
+	, mInboxEnabled(false)
+	, mOutboxEnabled(false)
+	, mCategoriesObserver(NULL)
+	, mInboxOutboxAddedObserver(NULL)
+{
 	//buildFromFile( "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
 }
 
 LLSidepanelInventory::~LLSidepanelInventory()
 {
+	if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
+	{
+		gInventory.removeObserver(mCategoriesObserver);
+	}
+	delete mCategoriesObserver;
+	
+	if (mInboxOutboxAddedObserver && gInventory.containsObserver(mInboxOutboxAddedObserver))
+	{
+		gInventory.removeObserver(mInboxOutboxAddedObserver);
+	}
+	delete mInboxOutboxAddedObserver;
+}
+
+void handleInventoryDisplayInboxChanged()
+{
+	LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+	sidepanel_inventory->enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
+}
+
+void handleInventoryDisplayOutboxChanged()
+{
+	LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+	sidepanel_inventory->enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
 }
 
 BOOL LLSidepanelInventory::postBuild()
@@ -85,7 +199,7 @@ BOOL LLSidepanelInventory::postBuild()
 		mOverflowBtn = mInventoryPanel->getChild<LLButton>("overflow_btn");
 		mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this));
 		
-		mPanelMainInventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+		mPanelMainInventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
 		mPanelMainInventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2));
 		LLTabContainer* tabs = mPanelMainInventory->getChild<LLTabContainer>("inventory filter tabs");
 		tabs->setCommitCallback(boost::bind(&LLSidepanelInventory::updateVerbs, this));
@@ -103,7 +217,7 @@ BOOL LLSidepanelInventory::postBuild()
 
 	// UI elements from item panel
 	{
-		mItemPanel = findChild<LLSidepanelItemInfo>("sidepanel__item_panel");
+		mItemPanel = getChild<LLSidepanelItemInfo>("sidepanel__item_panel");
 		
 		LLButton* back_btn = mItemPanel->getChild<LLButton>("back_btn");
 		back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
@@ -119,13 +233,263 @@ BOOL LLSidepanelInventory::postBuild()
 		}
 	}
 	
+	// Marketplace inbox/outbox setup
+	{
+		LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+
+		// Disable user_resize on main inventory panel by default
+		stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false);
+		stack->setPanelUserResize(INBOX_LAYOUT_PANEL_NAME, false);
+		stack->setPanelUserResize(OUTBOX_LAYOUT_PANEL_NAME, false);
+
+		// Collapse both inbox and outbox panels
+		stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
+		stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true);
+		
+		// Set up button states and callbacks
+		LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME);
+		LLButton * outbox_button = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+
+		inbox_button->setToggleState(false);
+		outbox_button->setToggleState(false);
+
+		inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this));
+		outbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleOutboxBtn, this));
+
+		// Set the inbox and outbox visible based on debug settings (final setting comes from http request below)
+		enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
+		enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
+
+		// Trigger callback for after login so we can setup to track inbox and outbox changes after initial inventory load
+		LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::handleLoginComplete, this));
+	}
+
+	gSavedSettings.getControl("InventoryDisplayInbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayInboxChanged));
+	gSavedSettings.getControl("InventoryDisplayOutbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayOutboxChanged));
+
 	return TRUE;
 }
 
+void LLSidepanelInventory::handleLoginComplete()
+{
+	//
+	// Track inbox and outbox folder changes
+	//
+
+	const bool do_not_create_folder = false;
+	const bool do_not_find_in_library = false;
+
+	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library);
+	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
+	
+	// Set up observer to listen for creation of inbox and outbox if at least one of them doesn't exist
+	if (inbox_id.isNull() || outbox_id.isNull())
+	{
+		observeInboxOutboxCreation();
+	}
+
+	// Set up observer for inbox changes, if we have an inbox already
+	if (!inbox_id.isNull())
+	{
+		observeInboxModifications(inbox_id);
+
+		// Enable the display of the inbox if it exists
+		enableInbox(true);
+	}
+	
+	// Set up observer for outbox changes, if we have an outbox already
+	if (!outbox_id.isNull())
+	{
+		observeOutboxModifications(outbox_id);
+
+		// Enable the display of the outbox if it exists
+		//enableOutbox(true);
+		// leslie NOTE: Disabling outbox until we support it officially.
+	}
+}
+
+void LLSidepanelInventory::observeInboxOutboxCreation()
+{
+	//
+	// Set up observer to track inbox and outbox folder creation
+	//
+	
+	if (mInboxOutboxAddedObserver == NULL)
+	{
+		mInboxOutboxAddedObserver = new LLInboxOutboxAddedObserver(this);
+		
+		gInventory.addObserver(mInboxOutboxAddedObserver);
+	}
+}
+
+void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID)
+{
+	//
+	// Track inbox and outbox folder changes
+	//
+	
+	if (inboxID.isNull())
+	{
+		llwarns << "Attempting to track modifications to non-existant inbox" << llendl;
+		return;
+	}
+	
+	if (mCategoriesObserver == NULL)
+	{
+		mCategoriesObserver = new LLInventoryCategoriesObserver();
+		gInventory.addObserver(mCategoriesObserver);
+	}
+	
+	mCategoriesObserver->addCategory(inboxID, boost::bind(&LLSidepanelInventory::onInboxChanged, this, inboxID));
+	
+	//
+	// Trigger a load for the entire contents of the Inbox
+	//
+	
+	LLInventoryModelBackgroundFetch::instance().start(inboxID);
+	
+	//
+	// Set up the inbox inventory view
+	//
+	
+	LLPanelMarketplaceInbox * inbox = getChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+	inbox->setupInventoryPanel();
+}
+
+
+void LLSidepanelInventory::observeOutboxModifications(const LLUUID& outboxID)
+{
+	//
+	// Track outbox folder changes
+	//
+	
+	if (outboxID.isNull())
+	{
+		llwarns << "Attempting to track modifications to non-existant outbox" << llendl;
+		return;
+	}
+	
+	if (mCategoriesObserver == NULL)
+	{
+		mCategoriesObserver = new LLInventoryCategoriesObserver();
+		gInventory.addObserver(mCategoriesObserver);
+	}
+	
+	mCategoriesObserver->addCategory(outboxID, boost::bind(&LLSidepanelInventory::onOutboxChanged, this, outboxID));
+	
+	//
+	// Set up the outbox inventory view
+	//
+	
+	LLPanelMarketplaceOutbox * outbox = getChild<LLPanelMarketplaceOutbox>(MARKETPLACE_OUTBOX_PANEL);
+	outbox->setupInventoryPanel();
+}
+
+void LLSidepanelInventory::enableInbox(bool enabled)
+{
+	mInboxEnabled = enabled;
+	getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->setVisible(enabled);
+}
+
+void LLSidepanelInventory::enableOutbox(bool enabled)
+{
+	mOutboxEnabled = enabled;
+	getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->setVisible(enabled);
+}
+
+void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
+{
+	// Trigger a load of the entire inbox so we always know the contents and their creation dates for sorting
+	LLInventoryModelBackgroundFetch::instance().start(inbox_id);
+	
+	// Expand the inbox since we have fresh items
+	LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+	if (inbox && (inbox->getFreshItemCount() > 0))
+	{
+		getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true);
+		onToggleInboxBtn();
+	}	
+}
+
+void LLSidepanelInventory::onOutboxChanged(const LLUUID& outbox_id)
+{
+	// Perhaps use this to track outbox changes?
+}
+
+bool manageInboxOutboxPanels(LLLayoutStack * stack,
+							 LLButton * pressedButton, LLLayoutPanel * pressedPanel,
+							 LLButton * otherButton, LLLayoutPanel * otherPanel)
+{
+	bool expand = pressedButton->getToggleState();
+	bool otherExpanded = otherButton->getToggleState();
+
+	//
+	// NOTE: Ideally we could have two panel sizes stored for a collapsed and expanded minimum size.
+	//       For now, leave this code disabled because it creates some bad artifacts when expanding
+	//       and collapsing the inbox/outbox.
+	//
+	//S32 smallMinSize = (expand ? pressedPanel->getMinDim() : otherPanel->getMinDim());
+	//S32 pressedMinSize = (expand ? 2 * smallMinSize : smallMinSize);
+	//otherPanel->setMinDim(smallMinSize);
+	//pressedPanel->setMinDim(pressedMinSize);
+
+	if (expand && otherExpanded)
+	{
+		// Reshape pressedPanel to the otherPanel's height so we preserve the marketplace panel size
+		pressedPanel->reshape(pressedPanel->getRect().getWidth(), otherPanel->getRect().getHeight());
+
+		stack->collapsePanel(otherPanel, true);
+		otherButton->setToggleState(false);
+	}
+
+	stack->collapsePanel(pressedPanel, !expand);
+
+	// Enable user_resize on main inventory panel only when a marketplace box is expanded
+	stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand);
+
+	return expand;
+}
+
+void LLSidepanelInventory::onToggleInboxBtn()
+{
+	LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+	LLButton* pressedButton = getChild<LLButton>(INBOX_BUTTON_NAME);
+	LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
+	LLButton* otherButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+	LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
+
+	bool inboxExpanded = manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel);
+
+	if (inboxExpanded)
+	{
+		// Save current time as a setting for future new-ness tests
+		gSavedSettings.setString(INBOX_EXPAND_TIME_SETTING, LLDate::now().asString());
+	}
+}
+
+void LLSidepanelInventory::onToggleOutboxBtn()
+{
+	LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+	LLButton* pressedButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+	LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
+	LLButton* otherButton = getChild<LLButton>(INBOX_BUTTON_NAME);
+	LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
+
+	manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel);
+}
+
 void LLSidepanelInventory::onOpen(const LLSD& key)
 {
 	LLFirstUse::newInventory(false);
 
+	// Expand the inbox if we have fresh items
+	LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+	if (inbox && (inbox->getFreshItemCount() > 0))
+	{
+		getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true);
+		onToggleInboxBtn();
+	}
+
 	if(key.size() == 0)
 		return;
 
@@ -171,26 +535,29 @@ void LLSidepanelInventory::onShopButtonClicked()
 
 void LLSidepanelInventory::performActionOnSelection(const std::string &action)
 {
-	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
 	LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
 	if (!current_item)
 	{
-		return;
+		LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+		if (inbox)
+		{
+			current_item = inbox->getRootFolder()->getCurSelectedItem();
+		}
+
+		if (!current_item)
+		{
+			return;
+		}
 	}
+
 	current_item->getListener()->performAction(panel_main_inventory->getActivePanel()->getModel(), action);
 }
 
 void LLSidepanelInventory::onWearButtonClicked()
 {
-	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
-	if (!panel_main_inventory)
-	{
-		llassert(panel_main_inventory != NULL);
-		return;
-	}
-
 	// Get selected items set.
-	const std::set<LLUUID> selected_uuids_set = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
+	const std::set<LLUUID> selected_uuids_set = LLAvatarActions::getInventorySelectedUUIDs();
 	if (selected_uuids_set.empty()) return; // nothing selected
 
 	// Convert the set to a vector.
@@ -329,31 +696,28 @@ bool LLSidepanelInventory::canShare()
 	LLPanelMainInventory* panel_main_inventory =
 		mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
 
-	if (!panel_main_inventory)
+	LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+
+	// Avoid flicker in the Recent tab while inventory is being loaded.
+	if ( (!inbox || inbox->getRootFolder()->getSelectionList().empty())
+		&& (panel_main_inventory && !panel_main_inventory->getActivePanel()->getRootFolder()->hasVisibleChildren()) )
 	{
-		llwarns << "Failed to get the main inventory panel" << llendl;
 		return false;
 	}
 
-	LLInventoryPanel* active_panel = panel_main_inventory->getActivePanel();
-	// Avoid flicker in the Recent tab while inventory is being loaded.
-	if (!active_panel->getRootFolder()->hasVisibleChildren()) return false;
-
-	return LLAvatarActions::canShareSelectedItems(active_panel);
+	return ( (panel_main_inventory ? LLAvatarActions::canShareSelectedItems(panel_main_inventory->getActivePanel()) : false)
+			|| (inbox ? LLAvatarActions::canShareSelectedItems(inbox) : false) );
 }
 
+
 bool LLSidepanelInventory::canWearSelected()
 {
-	LLPanelMainInventory* panel_main_inventory =
-		mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
 
-	if (!panel_main_inventory)
-	{
-		llassert(panel_main_inventory != NULL);
+	std::set<LLUUID> selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
+
+	if (selected_uuids.empty())
 		return false;
-	}
 
-	std::set<LLUUID> selected_uuids = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
 	for (std::set<LLUUID>::const_iterator it = selected_uuids.begin();
 		it != selected_uuids.end();
 		++it)
@@ -366,11 +730,20 @@ bool LLSidepanelInventory::canWearSelected()
 
 LLInventoryItem *LLSidepanelInventory::getSelectedItem()
 {
-	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
 	LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
 	if (!current_item)
 	{
-		return NULL;
+		LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+		if (inbox)
+		{
+			current_item = inbox->getRootFolder()->getCurSelectedItem();
+		}
+
+		if (!current_item)
+		{
+			return NULL;
+		}
 	}
 	const LLUUID &item_id = current_item->getListener()->getUUID();
 	LLInventoryItem *item = gInventory.getItem(item_id);
@@ -379,9 +752,20 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem()
 
 U32 LLSidepanelInventory::getSelectedCount()
 {
-	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+	int count = 0;
+
+	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
 	std::set<LLUUID> selection_list = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
-	return selection_list.size();
+	count += selection_list.size();
+
+	LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+	if (inbox)
+	{
+		selection_list = inbox->getRootFolder()->getSelectionList();
+		count += selection_list.size();
+	}
+
+	return count;
 }
 
 LLInventoryPanel *LLSidepanelInventory::getActivePanel()
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
index 32c98bc034b71b479b8c0fb3348d1d7bea06f16d..9117e3bf272528c0a1a9cf52f84cc5a6ed65efe6 100644
--- a/indra/newview/llsidepanelinventory.h
+++ b/indra/newview/llsidepanelinventory.h
@@ -30,6 +30,8 @@
 #include "llpanel.h"
 
 class LLFolderViewItem;
+class LLInboxOutboxAddedObserver;
+class LLInventoryCategoriesObserver;
 class LLInventoryItem;
 class LLInventoryPanel;
 class LLPanelMainInventory;
@@ -42,6 +44,14 @@ public:
 	LLSidepanelInventory();
 	virtual ~LLSidepanelInventory();
 
+private:
+	void handleLoginComplete();
+	
+public:
+	void observeInboxOutboxCreation();
+	void observeInboxModifications(const LLUUID& inboxID);
+	void observeOutboxModifications(const LLUUID& outboxID);
+
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onOpen(const LLSD& key);
 
@@ -56,6 +66,17 @@ public:
 	// checks can share selected item(s)
 	bool canShare();
 
+	void onToggleInboxBtn();
+	void onToggleOutboxBtn();
+
+	void enableInbox(bool enabled);
+	void enableOutbox(bool enabled);
+
+	bool isInboxEnabled() const { return mInboxEnabled; }
+	bool isOutboxEnabled() const { return mOutboxEnabled; }
+
+	void updateVerbs();
+
 protected:
 	// Tracks highlighted (selected) item in inventory panel.
 	LLInventoryItem *getSelectedItem();
@@ -63,10 +84,12 @@ protected:
 	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
 	// "wear", "teleport", etc.
 	void performActionOnSelection(const std::string &action);
-	void updateVerbs();
 
 	bool canWearSelected(); // check whether selected items can be worn
 
+	void onInboxChanged(const LLUUID& inbox_id);
+	void onOutboxChanged(const LLUUID& outbox_id);
+
 	//
 	// UI Elements
 	//
@@ -85,6 +108,7 @@ protected:
 	void 						onTeleportButtonClicked();
 	void 						onOverflowButtonClicked();
 	void 						onBackButtonClicked();
+
 private:
 	LLButton*					mInfoBtn;
 	LLButton*					mShareBtn;
@@ -94,6 +118,11 @@ private:
 	LLButton*					mOverflowBtn;
 	LLButton*					mShopBtn;
 
+	bool						mInboxEnabled;
+	bool						mOutboxEnabled;
+
+	LLInventoryCategoriesObserver* 			mCategoriesObserver;
+	LLInboxOutboxAddedObserver*				mInboxOutboxAddedObserver;
 };
 
 #endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp
index 37b10b592f1ca0420f3fac25d2953ee4e1cdb224..2918bb388a08f5be2da80571ba73c6d8aa76a097 100644
--- a/indra/newview/llsidepanelinventorysubpanel.cpp
+++ b/indra/newview/llsidepanelinventorysubpanel.cpp
@@ -46,8 +46,8 @@
 ///----------------------------------------------------------------------------
 
 // Default constructor
-LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel()
-  : LLPanel(),
+LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel(const LLPanel::Params& p)
+  : LLPanel(p),
 	mIsDirty(TRUE),
 	mIsEditing(FALSE),
 	mCancelBtn(NULL),
diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h
index b2de7d3b0b2fc3407e33146790a812672889f90a..b5cf3aaf17a175fa433c4e50d7c5bac33ac45744 100644
--- a/indra/newview/llsidepanelinventorysubpanel.h
+++ b/indra/newview/llsidepanelinventorysubpanel.h
@@ -40,7 +40,7 @@ class LLInventoryItem;
 class LLSidepanelInventorySubpanel : public LLPanel
 {
 public:
-	LLSidepanelInventorySubpanel();
+	LLSidepanelInventorySubpanel(const LLPanel::Params& p = getDefaultParams());
 	virtual ~LLSidepanelInventorySubpanel();
 
 	/*virtual*/ void setVisible(BOOL visible);
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index fbd2f7ca83184c47bd1fadac32b3dc3b2dc7244f..1ce05da8497f171b630d1c76585c26bd26fc3ae6 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -130,9 +130,10 @@ void LLObjectInventoryObserver::inventoryChanged(LLViewerObject* object,
 static LLRegisterPanelClassWrapper<LLSidepanelItemInfo> t_item_info("sidepanel_item_info");
 
 // Default constructor
-LLSidepanelItemInfo::LLSidepanelItemInfo()
-  : mItemID(LLUUID::null)
-  , mObjectInventoryObserver(NULL)
+LLSidepanelItemInfo::LLSidepanelItemInfo(const LLPanel::Params& p)
+	: LLSidepanelInventorySubpanel(p)
+	, mItemID(LLUUID::null)
+	, mObjectInventoryObserver(NULL)
 {
 	mPropertiesObserver = new LLItemPropertiesObserver(this);
 }
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 25be145f64dd1e8154519830d048a1a6f726a714..12aaca923ee082331a3e839989a780525ef5ae2f 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -44,7 +44,7 @@ class LLPermissions;
 class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
 {
 public:
-	LLSidepanelItemInfo();
+	LLSidepanelItemInfo(const LLPanel::Params& p = getDefaultParams());
 	virtual ~LLSidepanelItemInfo();
 	
 	/*virtual*/ BOOL postBuild();
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 631b244785cf67e48e96647ad6ee4eed7df9a8b5..651897a217161c7145932df0db0ae6eb2cdb9364 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -30,6 +30,7 @@
 
 #include "llagentcamera.h"
 #include "llappviewer.h"
+#include "llbadge.h"
 #include "llbottomtray.h"
 #include "llfloaterreg.h"
 #include "llfirstuse.h"
@@ -40,6 +41,7 @@
 #include "llfocusmgr.h"
 #include "llrootview.h"
 #include "llnavigationbar.h"
+#include "llpanelmarketplaceinbox.h"
 
 #include "llaccordionctrltab.h"
 
@@ -113,11 +115,14 @@ public:
 		Optional<std::string>		image_selected;
 		Optional<std::string>		tab_title;
 		Optional<std::string>		description;
+		Optional<LLBadge::Params>	badge;
+		
 		Params()
 		:	image("image"),
 			image_selected("image_selected"),
 			tab_title("tab_title","no title"),
-			description("description","no description")
+			description("description","no description"),
+			badge("badge")
 		{};
 	};
 protected:
@@ -140,7 +145,6 @@ public:
 	static LLSideTrayTab*  createInstance	();
 	
 	const std::string& getDescription () const { return mDescription;}
-	const std::string& getTabTitle() const { return mTabTitle;}
 	
 	void			onOpen		(const LLSD& key);
 	
@@ -150,7 +154,10 @@ public:
 
 	BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks);
 
-	LLPanel *getPanel();
+	LLPanel*		getPanel();
+
+	LLButton*		createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback);
+
 private:
 	std::string mTabTitle;
 	std::string mImage;
@@ -158,6 +165,9 @@ private:
 	std::string	mDescription;
 	
 	LLView*	mMainPanel;
+
+	bool			mHasBadge;
+	LLBadge::Params	mBadgeParams;
 };
 
 LLSideTrayTab::LLSideTrayTab(const Params& p)
@@ -166,8 +176,10 @@ LLSideTrayTab::LLSideTrayTab(const Params& p)
 	mImage(p.image),
 	mImageSelected(p.image_selected),
 	mDescription(p.description),
-	mMainPanel(NULL)
+	mMainPanel(NULL),
+	mBadgeParams(p.badge)
 {
+	mHasBadge = p.badge.isProvided();
 }
 
 LLSideTrayTab::~LLSideTrayTab()
@@ -182,8 +194,6 @@ bool LLSideTrayTab::addChild(LLView* view, S32 tab_group)
 	//return res;
 }
 
-
-
 //virtual 
 BOOL LLSideTrayTab::postBuild()
 {
@@ -196,7 +206,7 @@ BOOL LLSideTrayTab::postBuild()
 	getChild<LLButton>("undock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, false));
 	getChild<LLButton>("dock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, true));
 
-	return true;
+	return LLPanel::postBuild();
 }
 
 static const S32 splitter_margin = 1;
@@ -523,18 +533,36 @@ public:
 		return FALSE;
 	}
 
+	void setBadgeDriver(LLSideTrayTabBadgeDriver* driver)
+	{
+		mBadgeDriver = driver;
+	}
+
 protected:
 	LLSideTrayButton(const LLButton::Params& p)
-	: LLButton(p)
-	, mDragLastScreenX(0)
-	, mDragLastScreenY(0)
+		: LLButton(p)
+		, mDragLastScreenX(0)
+		, mDragLastScreenY(0)
+		, mBadgeDriver(NULL)
 	{}
 
 	friend class LLUICtrlFactory;
 
+	void draw()
+	{
+		if (mBadgeDriver)
+		{
+			setBadgeLabel(mBadgeDriver->getBadgeString());
+		}
+
+		LLButton::draw();
+	}
+
 private:
 	S32		mDragLastScreenX;
 	S32		mDragLastScreenY;
+
+	LLSideTrayTabBadgeDriver*	mBadgeDriver;
 };
 
 //////////////////////////////////////////////////////////////////////////////
@@ -615,11 +643,31 @@ BOOL LLSideTray::postBuild()
 	return true;
 }
 
+void LLSideTray::setTabButtonBadgeDriver(std::string tabName, LLSideTrayTabBadgeDriver* driver)
+{
+	mTabButtonBadgeDrivers[tabName] = driver;
+}
+
 void LLSideTray::handleLoginComplete()
 {
 	//reset tab to "home" tab if it was changesd during login process
 	selectTabByName("sidebar_home");
 
+	for (badge_map_t::iterator it = mTabButtonBadgeDrivers.begin(); it != mTabButtonBadgeDrivers.end(); ++it)
+	{
+		LLButton* button = mTabButtons[it->first];
+		LLSideTrayButton* side_button = dynamic_cast<LLSideTrayButton*>(button);
+
+		if (side_button)
+		{
+			side_button->setBadgeDriver(it->second);
+		}
+		else
+		{
+			llwarns << "Unable to find button " << it->first << " to set the badge driver. " << llendl;
+		}
+	}
+
 	detachTabs();
 }
 
@@ -766,51 +814,6 @@ bool LLSideTray::selectTabByName(const std::string& name, bool keep_prev_visible
 	return true;
 }
 
-LLButton* LLSideTray::createButton	(const std::string& name,const std::string& image,const std::string& tooltip,
-									 LLUICtrl::commit_callback_t callback)
-{
-	static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());	
-	
-	LLButton::Params bparams;
-
-	LLRect rect;
-	rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height); 
-
-	bparams.name(name);
-	bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP);
-	bparams.rect (rect);
-	bparams.tab_stop(false);
-	bparams.image_unselected(sidetray_params.tab_btn_image_normal);
-	bparams.image_selected(sidetray_params.tab_btn_image_selected);
-	bparams.image_disabled(sidetray_params.tab_btn_image_normal);
-	bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected);
-
-	LLButton* button;
-	if (name == "sidebar_openclose")
-	{
-		// "Open/Close" button shouldn't allow "tear off"
-		// hence it is created as LLButton instance.
-		button = LLUICtrlFactory::create<LLButton>(bparams);
-	}
-	else
-	{
-		button = LLUICtrlFactory::create<LLSideTrayButton>(bparams);
-	}
-
-	button->setClickedCallback(callback);
-
-	button->setToolTip(tooltip);
-	
-	if(image.length())
-	{
-		button->setImageOverlay(image);
-	}
-
-	mButtonsPanel->addChildInBack(button);
-
-	return button;
-}
-
 bool LLSideTray::addChild(LLView* view, S32 tab_group)
 {
 	LLSideTrayTab* tab_panel = dynamic_cast<LLSideTrayTab*>(view);
@@ -938,7 +941,56 @@ bool LLSideTray::addTab(LLSideTrayTab* tab)
 	return true;
 }
 
-void	LLSideTray::createButtons	()
+LLButton* LLSideTrayTab::createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback)
+{
+	static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());	
+
+	LLRect rect;
+	rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height); 
+
+	LLButton::Params bparams;
+
+	// Append "_button" to the side tray tab name
+	std::string button_name = getName() + "_button";
+	bparams.name(button_name);
+	bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP);
+	bparams.rect (rect);
+	bparams.tab_stop(false);
+	bparams.image_unselected(sidetray_params.tab_btn_image_normal);
+	bparams.image_selected(sidetray_params.tab_btn_image_selected);
+	bparams.image_disabled(sidetray_params.tab_btn_image_normal);
+	bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected);
+
+	if (mHasBadge)
+	{
+		bparams.badge = mBadgeParams;
+	}
+
+	LLButton* button;
+	if (allowTearOff)
+	{
+		button = LLUICtrlFactory::create<LLSideTrayButton>(bparams);
+	}
+	else
+	{
+		// "Open/Close" button shouldn't allow "tear off"
+		// hence it is created as LLButton instance.
+		button = LLUICtrlFactory::create<LLButton>(bparams);
+	}
+
+	button->setClickedCallback(callback);
+
+	button->setToolTip(mTabTitle);
+
+	if(mImage.length())
+	{
+		button->setImageOverlay(mImage);
+	}
+
+	return button;
+}
+
+void LLSideTray::createButtons()
 {
 	//create buttons for tabs
 	child_vector_const_iter_t child_it = mTabs.begin();
@@ -951,17 +1003,22 @@ void	LLSideTray::createButtons	()
 		// The "OpenClose" button will open/close the whole panel
 		if (name == "sidebar_openclose")
 		{
-			mCollapseButton = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(),
-				boost::bind(&LLSideTray::onToggleCollapse, this));
+			mCollapseButton = sidebar_tab->createButton(false, boost::bind(&LLSideTray::onToggleCollapse, this));
+
+			mButtonsPanel->addChildInBack(mCollapseButton);
+
 			LLHints::registerHintTarget("side_panel_btn", mCollapseButton->getHandle());
 		}
 		else
 		{
-			LLButton* button = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(),
-				boost::bind(&LLSideTray::onTabButtonClick, this, name));
+			LLButton* button = sidebar_tab->createButton(true, boost::bind(&LLSideTray::onTabButtonClick, this, name));
+
+			mButtonsPanel->addChildInBack(button);
+
 			mTabButtons[name] = button;
 		}
 	}
+
 	LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle());
 }
 
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 24882411f44e509506d22b72fb7156803fb8c9e0..17158329dcf9990454182528e036c0ff3e611c29 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -33,6 +33,13 @@
 class LLAccordionCtrl;
 class LLSideTrayTab;
 
+// Define an interface for side tab button badge values
+class LLSideTrayTabBadgeDriver
+{
+public:
+	virtual std::string getBadgeString() const = 0;
+};
+
 // Deal with LLSideTrayTab being opaque. Generic do-nothing cast...
 template <class T>
 T tab_cast(LLSideTrayTab* tab) { return tab; }
@@ -166,6 +173,8 @@ public:
 
 	bool		getCollapsed() { return mCollapsed; }
 
+	void		setTabButtonBadgeDriver(std::string tabName, LLSideTrayTabBadgeDriver* driver);
+
 public:
 	virtual ~LLSideTray(){};
 
@@ -204,8 +213,6 @@ protected:
 
 	void		createButtons	();
 
-	LLButton*	createButton	(const std::string& name,const std::string& image,const std::string& tooltip,
-									LLUICtrl::commit_callback_t callback);
 	void		arrange			();
 	void		detachTabs		();
 	void		reflectCollapseChange();
@@ -234,6 +241,8 @@ private:
 	LLPanel*						mButtonsPanel;
 	typedef std::map<std::string,LLButton*> button_map_t;
 	button_map_t					mTabButtons;
+	typedef std::map<std::string,LLSideTrayTabBadgeDriver*> badge_map_t;
+	badge_map_t						mTabButtonBadgeDrivers;
 	child_vector_t					mTabs;
 	child_vector_t					mDetachedTabs;
 	tab_order_vector_t				mOriginalTabOrder;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3c2ef37bb8e08a4b630a1de76071b0696ebad5b3..4dfcb85295977753aac509a0adef5391324065c6 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -76,6 +76,7 @@
 #include "lluserrelations.h"
 #include "llversioninfo.h"
 #include "llviewercontrol.h"
+#include "llviewerhelp.h"
 #include "llvfs.h"
 #include "llxorcipher.h"	// saved password, MAC address
 #include "llwindow.h"
@@ -1689,11 +1690,22 @@ bool idle_startup()
 				gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f);
 			}
 
+			if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin"))
+			{
+				gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
+			}
+
 			// Set the show start location to true, now that the user has logged
 			// on with this install.
 			gSavedSettings.setBOOL("ShowStartLocation", TRUE);
 		}
 
+		if (gSavedSettings.getBOOL("HelpFloaterOpen"))
+		{
+			// show default topic
+			LLViewerHelp::instance().showTopic("");
+		}
+
 		// We're successfully logged in.
 		gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
 
@@ -1950,7 +1962,8 @@ bool idle_startup()
 		gViewerWindow->getWindow()->resetBusyCount();
 		gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
 		LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL;
-		gViewerWindow->setShowProgress(FALSE);
+		gViewerWindow->revealIntroPanel();
+		//gViewerWindow->setShowProgress(FALSE);  // reveal intro video now handles this
 		gViewerWindow->setProgressCancelButtonVisible(FALSE);
 
 		// We're not away from keyboard, even though login might have taken
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 5b76537804a7b85e19c412cc09a4d2f1dd8f50fa..de22f2ae6b7f6fe3085363d7c6e8d76fa00bf782 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -420,7 +420,6 @@ BOOL LLFloaterTexturePicker::postBuild()
 		mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
 		mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
 		mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
-		mInventoryPanel->setAllowMultiSelect(FALSE);
 
 		// Disable auto selecting first filtered item because it takes away
 		// selection from the item set by LLTextureCtrl owning this floater.
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 42f780a8a3af5c687d367a13ef4e3031153f97ec..91012223930cf21e251179a94d5f9b393882f4d6 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -128,8 +128,10 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
 	addEntry(LLFolderType::FT_MY_OUTFITS, 			new ViewerFolderEntry("My Outfits",				"Inv_SysOpen",			"Inv_SysClosed",		TRUE));
 	addEntry(LLFolderType::FT_MESH, 				new ViewerFolderEntry("Meshes",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE));
 	
-
 	addEntry(LLFolderType::FT_INBOX, 				new ViewerFolderEntry("Inbox",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE));
+	addEntry(LLFolderType::FT_OUTBOX, 				new ViewerFolderEntry("Outbox",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE));
+
+	addEntry(LLFolderType::FT_BASIC_ROOT, 			new ViewerFolderEntry("Basic Root",				"Inv_SysOpen",			"Inv_SysClosed",		FALSE));
 		 
 	addEntry(LLFolderType::FT_NONE, 				new ViewerFolderEntry("New Folder",				"Inv_FolderOpen",		"Inv_FolderClosed",		FALSE, "default"));
 
diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp
index 9fe8c142b95f583019026ea86331bc0a965d7ad7..3a3d4f3881a696b0c8e9d0025f930a0be303ffed 100644
--- a/indra/newview/llviewerhelp.cpp
+++ b/indra/newview/llviewerhelp.cpp
@@ -101,8 +101,9 @@ void LLViewerHelp::showTopic(const std::string &topic)
 
 	// work out the URL for this topic and display it 
 	showHelp();
+	
 	std::string helpURL = LLViewerHelpUtil::buildHelpURL( help_topic );
-	setRawURL( helpURL );
+	setRawURL(helpURL);
 }
 
 std::string LLViewerHelp::defaultTopic()
@@ -148,18 +149,7 @@ std::string LLViewerHelp::getTopicFromFocus()
 // static 
 void LLViewerHelp::showHelp()
 {
-	LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser"));
-	if (helpbrowser)
-	{
-		BOOL visible = TRUE;
-		BOOL take_focus = TRUE;
-		helpbrowser->setVisible(visible);
-		helpbrowser->setFrontmost(take_focus);
-	}
-	else
-	{
-		llwarns << "Eep, help_browser floater not found" << llendl;
-	}
+	LLFloaterReg::showInstance("help_browser");
 }
 
 // static
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 9e58acdcd35308ee1b4011b0f138ca821fca8529..22666cec0d59b9893a13ff46aa06a05eb815e189 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1269,7 +1269,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons
 {
 	std::string type_name = userdata.asString();
 	
-	if (("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
+	if (("inbox" == type_name) || ("outbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
 	{
 		LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
 
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 1e53274cd6eabe283faecb0392aa019bff5a56ad..1be58eae450eb18caad52c77295490cfb4ed6ed7 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -64,8 +64,10 @@
 #include "llappviewer.h"
 #include "lllogininstance.h" 
 //#include "llfirstuse.h"
+#include "llviewernetwork.h"
 #include "llwindow.h"
 
+
 #include "llfloatermediabrowser.h"	// for handling window close requests and geometry change requests in media browser windows.
 #include "llfloaterwebcontent.h"	// for handling window close requests and geometry change requests in media browser windows.
 
@@ -1360,6 +1362,34 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
 }
 
 
+class LLInventoryUserStatusResponder : public LLHTTPClient::Responder
+{
+public:
+	LLInventoryUserStatusResponder()
+		: LLCurl::Responder()
+	{
+	}
+
+	void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status))
+		{
+			// Complete success
+			gSavedSettings.setBOOL("InventoryDisplayInbox", true);
+		}
+		else if (status == 401)
+		{
+			// API is available for use but OpenID authorization failed
+			gSavedSettings.setBOOL("InventoryDisplayInbox", true);
+		}
+		else
+		{
+			// API in unavailable
+			llinfos << "Marketplace API is unavailable -- Inbox may be disabled, status = " << status << ", reason = " << reason << llendl;
+		}
+	}
+};
+
 /////////////////////////////////////////////////////////////////////////////////////////
 // static
 void LLViewerMedia::setOpenIDCookie()
@@ -1406,6 +1436,25 @@ void LLViewerMedia::setOpenIDCookie()
 		LLHTTPClient::get(profile_url,  
 			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
 			headers);
+
+		std::string url = "https://marketplace.secondlife.com/";
+
+		if (!LLGridManager::getInstance()->isInProductionGrid())
+		{
+			std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
+			url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str());
+		}
+	
+		url += "api/1/users/";
+		url += gAgent.getID().getString();
+		url += "/user_status";
+
+		headers = LLSD::emptyMap();
+		headers["Accept"] = "*/*";
+		headers["Cookie"] = sOpenIDCookie;
+		headers["User-Agent"] = getCurrentUserAgent();
+
+		LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), headers);
 	}
 }
 
@@ -2349,15 +2398,13 @@ void LLViewerMediaImpl::updateJavascriptObject()
 	if ( mMediaSource )
 	{
 		// flag to expose this information to internal browser or not.
-		bool expose_javascript_object = gSavedSettings.getBOOL("BrowserEnableJSObject");
-		mMediaSource->jsExposeObjectEvent( expose_javascript_object );
+		bool enable = gSavedSettings.getBOOL("BrowserEnableJSObject");
+		mMediaSource->jsEnableObject( enable );
 
-		// indicate if the values we have are valid (currently do this blanket-fashion for
-		// everything depending on whether you are logged in or not - this may require a 
-		// more granular approach once variables are added that ARE valid before login
+		// these values are only menaingful after login so don't set them before
 		bool logged_in = LLLoginInstance::getInstance()->authSuccess();
-		mMediaSource->jsValuesValidEvent( logged_in );
-
+		if ( logged_in )
+		{
 		// current location within a region
 		LLVector3 agent_pos = gAgent.getPositionAgent();
 		double x = agent_pos.mV[ VX ];
@@ -2386,6 +2433,7 @@ void LLViewerMediaImpl::updateJavascriptObject()
 			region_name = region->getName();
 		};
 		mMediaSource->jsAgentRegionEvent( region_name );
+		}
 
 		// language code the viewer is set to
 		mMediaSource->jsAgentLanguageEvent( LLUI::getLanguage() );
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 55eea8fc69c561f78d8b9432369c8a5e680864e1..a37f8ad0d8c017e5be2482e0b57d2df8cb2c4aa1 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -108,6 +108,7 @@
 #include "lltrans.h"
 #include "lleconomy.h"
 #include "lltoolgrab.h"
+#include "llwindow.h"
 #include "boost/unordered_map.hpp"
 
 using namespace LLVOAvatarDefines;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 9f7559ad1591a5dac16704068e262fcf132ff602..44b3a85f253ea1752043230d6c7a04b705aa3401 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -37,6 +37,7 @@
 #include "lleconomy.h"
 #include "lleventtimer.h"
 #include "llfloaterreg.h"
+#include "llfolderview.h"
 #include "llfollowcamparams.h"
 #include "llinventorydefines.h"
 #include "lllslconstants.h"
@@ -87,6 +88,7 @@
 #include "lluri.h"
 #include "llviewergenericmessage.h"
 #include "llviewermenu.h"
+#include "llviewerinventory.h"
 #include "llviewerjoystick.h"
 #include "llviewerobjectlist.h"
 #include "llviewerparcelmgr.h"
@@ -694,7 +696,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
 	return false;
 }
 
-static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
+static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
 {
 	if (NULL == inventory_panel) return;
 
@@ -708,7 +710,7 @@ static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items,
 			continue;
 		}
 
-		LLInventoryItem* item = gInventory.getItem(item_id);
+		LLInventoryObject* item = gInventory.getObject(item_id);
 		llassert(item);
 		if (!item) {
 			continue;
@@ -787,7 +789,6 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO
 public:
 	LLViewerInventoryMoveFromWorldObserver()
 		: LLInventoryAddItemByAssetObserver()
-		, mActivePanel(NULL)
 	{
 
 	}
@@ -798,13 +799,16 @@ private:
 	/*virtual */void onAssetAdded(const LLUUID& asset_id)
 	{
 		// Store active Inventory panel.
-		mActivePanel = LLInventoryPanel::getActiveInventoryPanel();
+		if (LLInventoryPanel::getActiveInventoryPanel())
+		{
+			mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
+		}
 
 		// Store selected items (without destination folder)
 		mSelectedItems.clear();
-		if (mActivePanel)
+		if (LLInventoryPanel::getActiveInventoryPanel())
 		{
-			mSelectedItems = mActivePanel->getRootFolder()->getSelectionList();
+			mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList();
 		}
 		mSelectedItems.erase(mMoveIntoFolderID);
 	}
@@ -815,12 +819,14 @@ private:
 	 */
 	void done()
 	{
+		LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
+
 		// if selection is not changed since watch started lets hightlight new items.
-		if (mActivePanel && !isSelectionChanged())
+		if (active_panel && !isSelectionChanged())
 		{
 			LL_DEBUGS("Inventory_Move") << "Selecting new items..." << LL_ENDL;
-			mActivePanel->clearSelection();
-			highlight_inventory_items_in_panel(mAddedItems, mActivePanel);
+			active_panel->clearSelection();
+			highlight_inventory_objects_in_panel(mAddedItems, active_panel);
 		}
 	}
 
@@ -828,16 +834,16 @@ private:
 	 * Returns true if selected inventory items were changed since moved inventory items were started to watch.
 	 */
 	bool isSelectionChanged()
-	{
-		const LLInventoryPanel * const current_active_panel = LLInventoryPanel::getActiveInventoryPanel();
+	{	
+		LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
 
-		if (NULL == mActivePanel || current_active_panel != mActivePanel)
+		if (NULL == active_panel)
 		{
 			return true;
 		}
 
 		// get selected items (without destination folder)
-		selected_items_t selected_items = mActivePanel->getRootFolder()->getSelectionList();
+		selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList();
 		selected_items.erase(mMoveIntoFolderID);
 
 		// compare stored & current sets of selected items
@@ -851,7 +857,7 @@ private:
 		return different_items.size() > 0;
 	}
 
-	LLInventoryPanel *mActivePanel;
+	LLHandle<LLPanel> mActivePanel;
 	typedef std::set<LLUUID> selected_items_t;
 	selected_items_t mSelectedItems;
 
@@ -880,6 +886,75 @@ void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder
 	gInventoryMoveObserver->watchAsset(inv_item->getAssetUUID());
 }
 
+
+/**
+ * Class to observe moving of items and to select them in inventory.
+ *
+ * Used currently for dragging from inbox to regular inventory folders
+ */
+
+class LLViewerInventoryMoveObserver : public LLInventoryObserver
+{
+public:
+
+	LLViewerInventoryMoveObserver(const LLUUID& object_id)
+		: LLInventoryObserver()
+		, mObjectID(object_id)
+	{
+		if (LLInventoryPanel::getActiveInventoryPanel())
+		{
+			mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
+		}
+	}
+
+	virtual ~LLViewerInventoryMoveObserver() {}
+	virtual void changed(U32 mask);
+	
+private:
+	LLUUID mObjectID;
+	LLHandle<LLPanel> mActivePanel;
+
+};
+
+void LLViewerInventoryMoveObserver::changed(U32 mask)
+{
+	LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
+
+	if (NULL == active_panel)
+	{
+		gInventory.removeObserver(this);
+		return;
+	}
+
+	if((mask & (LLInventoryObserver::STRUCTURE)) != 0)
+	{
+		const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+		std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+		std::set<LLUUID>::const_iterator id_end = changed_items.end();
+		for (;id_it != id_end; ++id_it)
+		{
+			if ((*id_it) == mObjectID)
+			{
+				active_panel->clearSelection();			
+				std::vector<LLUUID> items;
+				items.push_back(mObjectID);
+				highlight_inventory_objects_in_panel(items, active_panel);
+				active_panel->getRootFolder()->scrollToShowSelection();
+				
+				gInventory.removeObserver(this);
+				break;
+			}
+		}
+	}
+}
+
+void set_dad_inbox_object(const LLUUID& object_id)
+{
+	LLViewerInventoryMoveObserver* move_observer = new LLViewerInventoryMoveObserver(object_id);
+	gInventory.addObserver(move_observer);
+}
+
 //unlike the FetchObserver for AgentOffer, we only make one 
 //instance of the AddedObserver for TaskOffers
 //and it never dies.  We do this because we don't know the UUID of 
@@ -936,7 +1011,6 @@ protected:
 
 //one global instance to bind them
 LLOpenTaskOffer* gNewInventoryObserver=NULL;
-
 class LLNewInventoryHintObserver : public LLInventoryAddedObserver
 {
 protected:
@@ -946,6 +1020,8 @@ protected:
 	}
 };
 
+LLNewInventoryHintObserver* gNewInventoryHintObserver=NULL;
+
 void start_new_inventory_observer()
 {
 	if (!gNewInventoryObserver) //task offer observer 
@@ -962,7 +1038,12 @@ void start_new_inventory_observer()
 		gInventory.addObserver(gInventoryMoveObserver);
 	}
 
-	gInventory.addObserver(new LLNewInventoryHintObserver());
+	if (!gNewInventoryHintObserver)
+	{
+		// Observer is deleted by gInventory
+		gNewInventoryHintObserver = new LLNewInventoryHintObserver();
+		gInventory.addObserver(gNewInventoryHintObserver);
+	}
 }
 
 class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver
@@ -4324,7 +4405,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
 	{
 		return;
 	}
-
+		
 	// Don't play sounds from gestures if they are not enabled.
 	if (object_id == owner_id && !gSavedSettings.getBOOL("EnableGestureSounds"))
 	{
@@ -6499,7 +6580,7 @@ void process_script_dialog(LLMessageSystem* msg, void**)
     LLUUID owner_id;
 	if (gMessageSystem->getNumberOfBlocks("OwnerData") > 0)
 	{
-		msg->getUUID("OwnerData", "OwnerID", owner_id);
+    msg->getUUID("OwnerData", "OwnerID", owner_id);
 	}
 
 	if (LLMuteList::getInstance()->isMuted(object_id) || LLMuteList::getInstance()->isMuted(owner_id))
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index b4a9b8e6773580897b478e8bc62c6c2b5d523cc3..9d09d9c01a8a204ed83ac4a689c8249a07fcbf33 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -203,6 +203,8 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name)
 bool highlight_offered_object(const LLUUID& obj_id);
 
 void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid);
+void set_dad_inbox_object(const LLUUID& object_id);
+
 
 class LLOfferInfo : public LLNotificationResponderInterface
 {
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index faa86d43ddce79135a13eace28a84916daf79131..252183b6d71ae450b3fbff8b497339db573bab81 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -33,6 +33,8 @@
 // in viewer.
 // It is used to precompile headers for improved build speed.
 
+#include <boost/coroutine/coroutine.hpp>
+
 #include "linden_common.h"
 
 // Work around stupid Microsoft STL warning
@@ -118,8 +120,8 @@
 
 // Library includes from llvfs
 #include "lldir.h"
-
-// Library includes from llmessage project
+
+// Library includes from llmessage project
 #include "llcachename.h"
 
 #endif
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index b1441cc2812341abf558e3d92395b53f0b3bfc52..cff166b825179d8d0e948b3803af919be6f43d95 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1979,7 +1979,10 @@ void LLViewerWindow::shutdownViews()
 	
 	// destroy the nav bar, not currently part of gViewerWindow
 	// *TODO: Make LLNavigationBar part of gViewerWindow
+	if (LLNavigationBar::instanceExists())
+	{
 	delete LLNavigationBar::getInstance();
+	}
 
 	// destroy menus after instantiating navbar above, as it needs
 	// access to gMenuHolder
@@ -4512,6 +4515,14 @@ void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
 	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
 }
 
+void LLViewerWindow::revealIntroPanel()
+{
+	if (mProgressView)
+	{
+		mProgressView->revealIntroPanel();
+	}
+}
+
 void LLViewerWindow::setShowProgress(const BOOL show)
 {
 	if (mProgressView)
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index df6928aa1d0ada833ff98edcdb71d111cf220e13..ff49ed1f62880e034a11f7c4d50f12e046c82620 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -271,6 +271,7 @@ public:
 	void			setProgressMessage(const std::string& msg);
 	void			setProgressCancelButtonVisible( BOOL b, const std::string& label = LLStringUtil::null );
 	LLProgressView *getProgressView() const;
+	void			revealIntroPanel();
 
 	void			updateObjectUnderCursor();
 
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index b0628dfe676c98f28a32a3009209a1d17ca9667b..76965ad14ba2de0589e4c4edcbd381fa940a62f7 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -132,6 +132,15 @@
     <color
      name="AvatarListItemIconVoiceLeftColor"
      reference="AvatarListItemIconOfflineColor" />
+    <color
+     name="BadgeImageColor"
+     value="0.44 0.69 0.56 1.0" />
+    <color
+     name="BadgeBorderColor"
+     value="0.9 0.9 0.9 1.0" />
+    <color
+     name="BadgeLabelColor"
+     reference="White" />
     <color
      name="ButtonBorderColor"
      reference="Unused?" />
@@ -760,7 +769,7 @@
     <color
      name="MenuBarProjectBgColor"
      reference="MdBlue" />
-
+  
     <color
       name="MeshImportTableNormalColor"
       value="1 1 1 1"/>
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gift.png b/indra/newview/skins/default/textures/icons/Inv_Gift.png
new file mode 100644
index 0000000000000000000000000000000000000000..5afe85d72d546f665d9b9611c74dbde83cf67d68
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_Gift.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png
new file mode 100644
index 0000000000000000000000000000000000000000..be58114aa12af04923bbcc7c0c6811e19d468a3f
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Off.png b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6b9480ab189705c9c04dcbb8ae60795dbb9f229
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On.png b/indra/newview/skins/default/textures/icons/OutboxPush_On.png
new file mode 100644
index 0000000000000000000000000000000000000000..ffda2e92d4d57cf3f53b3251e5268405cb5c1e5d
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_On.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b5911014f9392e0c3755b40dd0c4aba7b217506
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png
new file mode 100644
index 0000000000000000000000000000000000000000..0e60b417b064372897b6c4851de1384ac3a55e5c
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c26b92e73dbc6c14f0dc318e955b377b99fe299
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b5d462975871be3e739030cf108d3231ef6d733
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..f85be047b0da0c4fc4b12faed625451d1aaab65a
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd4e482216b8ef60ba0916b3a29ac455a712d58c
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..d212a871cec980cf117cc53f166d3fd72b2511a4
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5b6023e36dda0fa3a463e1df772a2e2e3b71eb8
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png
new file mode 100644
index 0000000000000000000000000000000000000000..e1911a092f63fffeb781f150948fa5af9c19f64a
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e59f7843abadec84696d1e226bf36f10d8ac88f
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png
new file mode 100644
index 0000000000000000000000000000000000000000..51e8bff6468df8dcea954664a0efd18d5fc973ee
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png
new file mode 100644
index 0000000000000000000000000000000000000000..300e2e69e16e5bb1cc99c402db23d7f06ba19719
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png
new file mode 100644
index 0000000000000000000000000000000000000000..32fb236381f5902ead576b01c0dedf3e24897845
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png
new file mode 100644
index 0000000000000000000000000000000000000000..827f343b1e13027c5eb33fd0bbf1d106f887a46a
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Disabled.png b/indra/newview/skins/default/textures/icons/Sync_Disabled.png
new file mode 100644
index 0000000000000000000000000000000000000000..ca2e8def971821a0c94c9c1cf52dc42825f69d3e
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Disabled.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Enabled.png b/indra/newview/skins/default/textures/icons/Sync_Enabled.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc236c8b98747d5311cfbb8c636113f7128bc0b5
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Enabled.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_1.png b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..624e5563765727879897d212f62655d7c6cc6336
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_2.png b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..5769803b3f60e68929467bbfb1d3f0da6f9228e3
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_3.png b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..92d4bfb020cecb80256f3ef98fd591d4ff6e1138
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_4.png b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png
new file mode 100644
index 0000000000000000000000000000000000000000..6d43eb3a9fb881566ad14ca1b8d15adb6f660afe
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_5.png b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png
new file mode 100644
index 0000000000000000000000000000000000000000..766d063c9918649f4a9e237c79a2720d331c6ec8
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_6.png b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png
new file mode 100644
index 0000000000000000000000000000000000000000..dfe7f68b723f10095bfab0ee71050ebb52e218ca
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index cc7cce99c991b6ed3d7695df18e1d2c0e8db1e39..c2757f2c94cb88b9554e8458dbc1b50c155895f5 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -72,8 +72,11 @@ with the same filename but different name
   <texture name="BackButton_Over" file_name="icons/back_arrow_over.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
   <texture name="BackButton_Press" file_name="icons/back_arrow_press.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
 
+  <texture name="Badge_Background" file_name="widgets/Badge_Background.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+  <texture name="Badge_Border" file_name="widgets/Badge_Border.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+
   <texture name="Blank" file_name="Blank.png" preload="false" />
-	
+
   <texture name="BreadCrumbBtn_Left_Disabled" file_name="widgets/BreadCrumbBtn_Left_Disabled.png" preload="false"/>
   <texture name="BreadCrumbBtn_Left_Off" file_name="widgets/BreadCrumbBtn_Left_Off.png" preload="false"/>
   <texture name="BreadCrumbBtn_Left_Over" file_name="widgets/BreadCrumbBtn_Left_Over.png" preload="false"/>
@@ -88,7 +91,6 @@ with the same filename but different name
   <texture name="BreadCrumbBtn_Right_Off" file_name="widgets/BreadCrumbBtn_Right_Off.png" preload="false"/>
   <texture name="BreadCrumbBtn_Right_Over" file_name="widgets/BreadCrumbBtn_Right_Over.png" preload="false"/>
   <texture name="BreadCrumbBtn_Right_Press" file_name="widgets/BreadCrumbBtn_Right_Press.png" preload="false"/>
- 
 
   <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="0" scale.top="1" scale.right="0" scale.bottom="0"  />
   <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0"  />
@@ -266,6 +268,8 @@ with the same filename but different name
 
   <texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" />
 
+  <texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
+  <texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
 
   <texture name="Microphone_On" file_name="icons/Microphone_On.png" preload="false" />
 
@@ -349,6 +353,23 @@ with the same filename but different name
   <texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />
   <texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" />
 
+  <texture name="OutboxPush_Disabled" file_name="icons/OutboxPush_Disabled.png" preload="true" />
+  <texture name="OutboxPush_Off" file_name="icons/OutboxPush_Off.png" preload="true" />
+  <texture name="OutboxPush_On" file_name="icons/OutboxPush_On.png" preload="true" />
+  <texture name="OutboxPush_On_Over" file_name="icons/OutboxPush_On_Over.png" preload="true" />
+  <texture name="OutboxPush_Over" file_name="icons/OutboxPush_Over.png" preload="true" />
+  <texture name="OutboxPush_Press" file_name="icons/OutboxPush_Press.png" preload="true" />
+  <texture name="OutboxPush_Progress_1" file_name="icons/OutboxPush_Progress_1.png" preload="true" />
+  <texture name="OutboxPush_Progress_2" file_name="icons/OutboxPush_Progress_2.png" preload="true" />
+  <texture name="OutboxPush_Progress_3" file_name="icons/OutboxPush_Progress_3.png" preload="true" />
+  <texture name="OutboxPush_Progress_4" file_name="icons/OutboxPush_Progress_4.png" preload="true" />
+  <texture name="OutboxPush_Progress_5" file_name="icons/OutboxPush_Progress_5.png" preload="true" />
+  <texture name="OutboxPush_Progress_6" file_name="icons/OutboxPush_Progress_6.png" preload="true" />
+  <texture name="OutboxPush_Selected" file_name="icons/OutboxPush_Selected.png" preload="true" />
+  <texture name="OutboxPush_Selected_Disabled" file_name="icons/OutboxPush_Selected_Disabled.png" preload="true" />
+  <texture name="OutboxPush_Selected_Over" file_name="icons/OutboxPush_Selected_Over.png" preload="true" />
+  <texture name="OutboxPush_Selected_Press" file_name="icons/OutboxPush_Selected_Press.png" preload="true" />
+
   <texture name="PanOrbit_Off" file_name="bottomtray/PanOrbit_Off.png" preload="false" />
 
   <texture name="Parcel_Exp_Color" file_name="icons/Parcel_Exp_Color.png" preload="false" />
@@ -496,6 +517,15 @@ with the same filename but different name
   <texture name="StopReload_Off" file_name="icons/StopReload_Off.png" preload="false" />
   <texture name="StopReload_Over" file_name="icons/StopReload_Over.png" preload="false" />
 
+  <texture name="Sync_Disabled" file_name="icons/Sync_Disabled.png" preload="true" />
+  <texture name="Sync_Enabled" file_name="icons/Sync_Enabled.png" preload="true" />
+  <texture name="Sync_Progress_1" file_name="icons/Sync_Progress_1.png" preload="true" />
+  <texture name="Sync_Progress_2" file_name="icons/Sync_Progress_2.png" preload="true" />
+  <texture name="Sync_Progress_3" file_name="icons/Sync_Progress_3.png" preload="true" />
+  <texture name="Sync_Progress_4" file_name="icons/Sync_Progress_4.png" preload="true" />
+  <texture name="Sync_Progress_5" file_name="icons/Sync_Progress_5.png" preload="true" />
+  <texture name="Sync_Progress_6" file_name="icons/Sync_Progress_6.png" preload="true" />
+
   <texture name="TabIcon_Appearance_Off" file_name="taskpanel/TabIcon_Appearance_Off.png" preload="false" />
   <texture name="TabIcon_Appearance_Selected" file_name="taskpanel/TabIcon_Appearance_Selected.png" preload="false" />
   <texture name="TabIcon_Close_Off" file_name="taskpanel/TabIcon_Close_Off.png" preload="false" />
@@ -649,6 +679,7 @@ with the same filename but different name
 
   <texture name="inv_folder_mesh.tga"/>
   <texture name="inv_item_mesh.tga"/>
+
   <texture name="lag_status_critical.tga" />
   <texture name="lag_status_good.tga" />
   <texture name="lag_status_warning.tga" />
diff --git a/indra/newview/skins/default/textures/widgets/Badge_Background.png b/indra/newview/skins/default/textures/widgets/Badge_Background.png
new file mode 100644
index 0000000000000000000000000000000000000000..5089c303129249824f4c05b828240f0dc90dbc06
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/Badge_Background.png differ
diff --git a/indra/newview/skins/default/textures/widgets/Badge_Border.png b/indra/newview/skins/default/textures/widgets/Badge_Border.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b086a63fb16efaab8fc2572cd4e46ddcecf7e15
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/Badge_Border.png differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
new file mode 100644
index 0000000000000000000000000000000000000000..e603c4438400d3091c47b941c9100086cdeb3eae
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
new file mode 100644
index 0000000000000000000000000000000000000000..fbc164123fbb14c0570d5d18c02126453e082870
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png differ
diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
index 02e50ee5844931593ad4894d0777b9f2ceff68c8..de6d586f7204b32d6249b7f2a51ea6474c4f92cf 100644
--- a/indra/newview/skins/default/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -2,6 +2,8 @@
 <floater
  legacy_header_height="18"
  can_resize="true"
+ left="10000"
+ bottom="10000"
  height="600"
  layout="topleft"
  min_height="150"
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
index 43729d7c9fd0da284a6a19b7e50fb6932f270cc9..5a1f920398b2817ee93cd475fb0889d3d0474b3b 100644
--- a/indra/newview/skins/default/xui/en/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -5,7 +5,7 @@
  height="440"
  layout="topleft"
  min_height="140"
- min_width="467"
+ min_width="0"
  name="floater_about"
  help_topic="floater_about"
  save_rect="true"
diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml
index e04a72cbc001c54aaf539e42eb7fb32af9957d48..69e60575562f7745852fd38f1c777d5911357813 100644
--- a/indra/newview/skins/default/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/default/xui/en/floater_web_content.xml
@@ -18,6 +18,7 @@
     follows="left|right|top|bottom"
     layout="topleft"
     left="5"
+    animate="false"
     name="stack1"
     orientation="vertical"
     top="20"
@@ -156,14 +157,20 @@
       name="external_controls"
       top_delta="0"
       user_resize="false"
+      auto_resize="true"
       width="585">
       <web_browser
-        bottom="-22"
+        bottom="-2"
         follows="all"
         layout="topleft"
         left="0"
         name="webbrowser"
         top="0"/>
+    </layout_panel>
+    <layout_panel name="status_bar" 
+                  height="23"
+                  auto_resize="false"
+                  user_resize="false">
       <text
         type="string"
         length="200"
@@ -174,7 +181,7 @@
         name="statusbartext"
         parse_urls="false"
         text_color="0.4 0.4 0.4 1"
-        top_pad="5"
+        top_pad="3"
         width="495"/>
       <progress_bar
         color_bar="0.3 1.0 0.3 1"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index b36b82ebd8d80aeb75b9a4067b9962838d9fad0c..e0ccb18c08bcd374fc70aac13709ddc2ca072087 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -42,7 +42,7 @@
                     <menu_item_call.on_enable
                      function="File.EnableUpload" />
                 </menu_item_call>
-		<menu_item_call
+                <menu_item_call
                  label="Model..."
                  layout="topleft"
                  name="Upload Model">
@@ -263,4 +263,4 @@
                      parameter="eyes" />
                 </menu_item_call>
             </menu>
-</menu>
+</menu>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d06190ec54853d0747b53746dd67c91b70bac2c9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inbox_inventory_panel
+    name="inventory_inbox"
+    start_folder="Received Items"
+    follows="all" layout="topleft"
+    top="0" left="0" height="165" width="308"
+	top_pad="0"
+    bg_opaque_color="DkGray2"
+    bg_alpha_color="DkGray2"
+    background_visible="true"
+    background_opaque="true"
+    border="false"
+    bevel_style="none"
+    show_item_link_overlays="true"
+    >
+    <scroll reserve_scroll_corner="false" />
+</inbox_inventory_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
new file mode 100644
index 0000000000000000000000000000000000000000..af32056428a3db41605ed8565e53b95c52da7ea6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inventory_panel
+    name="inventory_outbox"
+    start_folder="Outbox"
+    follows="all" layout="topleft"
+    top="0" left="0" height="165" width="308"
+	top_pad="0"
+    bg_opaque_color="DkGray2"
+    bg_alpha_color="DkGray2"
+    background_visible="true"
+    background_opaque="true"
+    border="false"
+    bevel_style="none"
+    show_item_link_overlays="true"
+    >
+    <scroll reserve_scroll_corner="false" />
+</inventory_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
index 2868d91cc7229ab0af485bca648574364199afb0..4535c563398a43117fff2dfa8736e3de9e933122 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -132,4 +132,12 @@
      name="cancel_btn"
      top="700"
      width="90" />
+  <web_browser
+   follows="all"
+   layout="topleft"
+   left="0"
+   name="login_media_panel"
+   width="1024"
+   height="768"
+   top="0"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
index 6ef93406ec11e63980357c5c0bd863ad598537ce..0f330a7b981b53e2622d95962f8c52a46c062eab 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -142,6 +142,7 @@
     mouse_opaque="false"
     background_visible="true"
   >
+      <badge location="top_left" location_percent_vcenter="50" location_percent_hcenter="95" />
       <panel
         class="sidepanel_inventory"
         name="sidepanel_inventory"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index 8997c1a6d75dd90768a1436be883c02bb3b5039a..79a0ec7c72ff108ed12c500fc7a26b481e293b77 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -9,7 +9,7 @@
 	  min_width="240"
 	  name="objects panel"
 	  width="333">
-	 <panel
+    <panel
 		 follows="all"
 		 layout="topleft"
 		 left="0"
@@ -19,24 +19,226 @@
 		 height="570"
 		 visible="true"
 		 width="330">
-		<panel
-			 class="panel_main_inventory"
-			 filename="panel_main_inventory.xml"
-			 follows="all"
-			 layout="topleft"
-			 left="0"
-			 name="panel_main_inventory"
-			 top="0"
-			 label=""
-			 height="545"
-			 width="330" />
+         <layout_stack
+              follows="left|right|top|bottom"
+              layout="topleft"
+              left="0"
+              top="0"
+              orientation="vertical"
+              name="inventory_layout_stack"
+              height="535"
+              width="330">
+             <layout_panel
+                 name="main_inventory_layout_panel"
+                 min_dim="150"
+                 width="330"
+                 follows="bottom|left|right"
+                 user_resize="false"
+                 height="480">
+                 <panel
+                      class="panel_main_inventory"
+                      filename="panel_main_inventory.xml"
+                      follows="all"
+                      layout="topleft"
+                      left="0"
+                      name="panel_main_inventory"
+                      top="0"
+                      label=""
+                      height="480"
+                      width="330" />
+             </layout_panel>
+             <layout_panel
+                 width="330"
+                 auto_resize="true"
+                 user_resize="false"
+                 follows="bottom|left|right"
+                 name="inbox_layout_panel"
+                 visible="false"
+                 min_dim="35"
+                 max_dim="200"
+                 expanded_min_dim="90"
+                 height="200">
+                 <panel
+                      follows="all"
+                      layout="topleft"
+                      left="0"
+                      name="marketplace_inbox"
+                      class="panel_marketplace_inbox"
+                      top="0"
+                      label=""
+                      height="200"
+                      width="330">
+                     <string name="InboxLabelWithArg">Received Items ([NUM])</string>
+                     <string name="InboxLabelNoArg">Received Items</string>
+                     <button
+                        label="Received Items"
+                        name="inbox_btn"
+                        height="35"
+                        width="308"
+                        image_unselected="MarketplaceBtn_Off"
+                        image_selected="MarketplaceBtn_Selected"
+                        halign="left"
+                        handle_right_mouse="false"
+                        follows="top|left|right"
+                        is_toggle="true"
+                        tab_stop="false"
+                        pad_left="35"
+                        top="0"
+                        left="10" />
+                     <text
+                        type="string"
+                        length="1"
+                        follows="right|top"
+                        layout="topleft"
+                        height="13"
+                        top="10"
+                        right="-20"
+                        name="inbox_fresh_new_count"
+                        font="SansSerifMedium"
+                        halign="right"
+                        text_color="EmphasisColor"
+                        top_pad="0"
+                        width="300">
+                        [NUM] New
+                     </text>
+                     <panel
+                        follows="all"
+                        left="10"
+                        bottom="200"
+                        width="308"
+                        top="35"
+                        bg_opaque_color="InventoryBackgroundColor"
+                        background_visible="true"
+                        background_opaque="true"
+                        tool_tip="Drag and drop items to your inventory to manage and use them"
+                        >
+                        <text
+							name="inbox_inventory_placeholder"
+							type="string"
+							follows="all"
+							layout="topleft"
+							top="0"
+							left="0"
+							width="308"
+							height="165"
+							wrap="true"
+							halign="center">
+							Purchases from the marketplace will be delivered here.
+						</text>
+                    </panel>
+                 </panel>
+             </layout_panel>
+             <layout_panel
+                width="330"
+                auto_resize="true"
+                user_resize="false"
+                follows="bottom|left|right"
+                name="outbox_layout_panel"
+                visible="false"
+                min_dim="35"
+                max_dim="200"
+                expanded_min_dim="90"
+                height="200">
+                 <panel
+                      follows="all"
+                      layout="topleft"
+                      left="10"
+                      name="marketplace_outbox"
+                      class="panel_marketplace_outbox"
+                      top="0"
+                      label=""
+                      height="200"
+                      width="310">
+                     <button
+                        label="Merchant Outbox"
+                        is_toggle="true"
+                        handle_right_mouse="false"
+                        name="outbox_btn"
+                        follows="top|left|right"
+                        image_unselected="MarketplaceBtn_Off"
+                        image_selected="MarketplaceBtn_Selected"
+                        height="35"
+                        tab_stop="false"
+                        width="308"
+                        halign="left"
+                        pad_left="35"
+                        top="0"
+                        left="0" />
+                     <button
+                         image_unselected="OutboxPush_Off"
+                         image_selected="OutboxPush_Selected"
+                         image_hover_selected="OutboxPush_Selected_Over"
+                         image_hover_unselected="OutboxPush_Over"
+                         image_disabled_selected="OutboxPush_Selected_Disabled"
+                         image_disabled="OutboxPush_Disabled"
+                         image_pressed="OutboxPush_Press"
+                         image_pressed_selected="OutboxPush_Selected_Press"
+                         label=""
+                         tool_tip="Push to my Marketplace Storefront"
+                         is_toggle="false"
+                         name="outbox_sync_btn"
+                         follows="top|right"
+                         tab_stop="false"
+                         halign="center"
+                         top="6"
+                         left="-50"
+                         height="23"
+                         width="32"
+                         enabled="false" />
+                     <loading_indicator
+                        follows="top|right"
+                        name="outbox_sync_indicator"
+                        top="6"
+                        left="-50"
+                        height="23"
+                        width="32"
+                        images_per_sec="1.15"
+                        tab_stop="false"
+                        visible="false">
+                         <images>
+                             <image name="OutboxPush_Progress_1"/>
+                             <image name="OutboxPush_Progress_2"/>
+                             <image name="OutboxPush_Progress_3"/>
+                             <image name="OutboxPush_Progress_4"/>
+                             <image name="OutboxPush_Progress_5"/>
+                             <image name="OutboxPush_Progress_6"/>
+                         </images>
+                     </loading_indicator>
+                     <panel
+                        follows="all"
+                        left="10"
+                        bottom="200"
+                        width="308"
+                        top="35"
+                        bg_opaque_color="InventoryBackgroundColor"
+                        background_visible="true"
+                        background_opaque="true"
+                        tool_tip="Drag and drop items here to prepare them for sale on your storefront"
+                        >
+                        <text
+							name="outbox_inventory_placeholder"
+							type="string"
+							follows="all"
+							layout="topleft"
+							top="0"
+							left="0"
+							width="308"
+							height="165"
+							wrap="true"
+							halign="center">
+							Set up your merchant account to use this feature.
+						</text>
+                    </panel>
+                 </panel>
+             </layout_panel>
+         </layout_stack>
 		<panel
 		     follows="bottom|left|right"
-			 height="25"
+			 height="30"
 			 layout="topleft"
 			 name="button_panel"
 			 left="9"
-			 top_pad="-2"
+             top_pad="7"
 			 width="308">
 			<layout_stack
      	         follows="bottom|left|right"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 09bff0a46cb0f2510844523b0e268bd578c693b0..def4079ba966b0e7c98007024f6f1070f08f59e3 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2021,6 +2021,8 @@ Returns a string with the requested data about the region
 	<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
 	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
 	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
+	<string name="InventoryInboxNoItems">Items purchased through the marketplace will be delivered here.</string>
+	<string name="InventoryOutboxNoItems">Drag items here in preparation for listing on your marketplace storefront.</string>
     <!-- use value="" because they have preceding spaces -->
 	<string name="no_transfer" value=" (no transfer)" />
 	<string name="no_modify"   value=" (no modify)" />
diff --git a/indra/newview/skins/default/xui/en/widgets/badge.xml b/indra/newview/skins/default/xui/en/widgets/badge.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f77c4b71787f75830591a37bc533086d1bc1b12b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/badge.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Additional attributes:
+   -->
+<badge border_image="Badge_Border"
+       border_color="BadgeBorderColor"
+       font="SansSerifSmall"
+       image="Badge_Background"
+       image_color="BadgeImageColor"
+       label_color="BadgeLabelColor"
+       location="top_left"
+       location_percent_hcenter="85"
+       location_percent_vcenter="85"
+       padding_horiz="7"
+       padding_vert="4"
+       requests_front="true"
+       >
+</badge>
diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml
index 16241ed84ec5a8f9e9fbb5966cb14cc686014b5d..302014eb24b8db5f20ec2afb9bb8ba19d44d1077 100644
--- a/indra/newview/skins/default/xui/en/widgets/button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/button.xml
@@ -25,5 +25,6 @@
         pad_bottom="3" 
         height="23"
         scale_image="true"
+        handle_right_mouse="true"
         use_draw_context_alpha="true">
 </button>
diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2c987b158da78360e574612eb16052d9b40ce32a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inbox_folder_view_folder
+  folder_arrow_image="Folder_Arrow"
+  folder_indentation="8"
+  item_height="20" 
+  item_top_pad="4"
+  selection_image="Rounded_Square"
+  >
+	<new_badge label="New" location="right" location_percent_hcenter="70" />
+</inbox_folder_view_folder>
diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml
new file mode 100644
index 0000000000000000000000000000000000000000..830c27bdac83f47af3727942ac17d96a60c3e87f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inbox_inventory_panel show_load_status="false" />
diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
index 93875d66e622778abed0996c4bcc3592d90fe5cb..00f4c43915517e15ab65089f422c1e9783acec40 100644
--- a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
+++ b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
@@ -3,4 +3,12 @@
   bg_opaque_color="InventoryBackgroundColor"
   background_visible="true"
   background_opaque="true"
-  />
+  show_load_status="true"
+  >
+    <scroll
+		name="Inventory Scroller"
+        follows="all"
+		reserve_scroll_corner="true"
+        tab_stop="true"
+        />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml
index 9bf99fa363eb623052cee62325bb0291c5f9d085..47a210d9b70d989b6d086798196c06372728ea88 100644
--- a/indra/newview/skins/default/xui/en/widgets/panel.xml
+++ b/indra/newview/skins/default/xui/en/widgets/panel.xml
@@ -10,4 +10,5 @@
        bg_alpha_image_overlay="White"
        background_visible="false"
        background_opaque="false"
-       chrome="false"/>
\ No newline at end of file
+       chrome="false"
+       accepts_badge="true"/>
\ No newline at end of file
diff --git a/indra/newview/skins/minimal/xui/en/floater_help_browser.xml b/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
index cc551f7d58448b75f4a0ce56a6d5604a9c273628..477f2103526953382e7207df5bb520e9a77a482f 100644
--- a/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
@@ -3,14 +3,13 @@
  legacy_header_height="18"
  can_resize="true"
  can_minimize="false" 
- height="360"
+ height="460"
  layout="topleft"
  min_height="360"
- left="645"
+ left="10000"
  top="10" 
- min_width="345"
+ min_width="335"
  name="floater_help_browser"
- save_rect="true"
  single_instance="true"
  title="HOW TO"
  width="335">
@@ -22,7 +21,7 @@
      name="done_text">
     </floater.string>
     <layout_stack
-     bottom="360"
+     bottom="460"
      follows="left|right|top|bottom"
      layout="topleft"
      left="5"
@@ -38,7 +37,7 @@
          user_resize="false"
          width="325">
             <web_browser
-              trusted_content="true" 
+              trusted_content="true"  
              bottom="-5"
              follows="left|right|top|bottom"
              layout="topleft"
diff --git a/indra/newview/skins/minimal/xui/en/floater_web_content.xml b/indra/newview/skins/minimal/xui/en/floater_web_content.xml
index 50cb5b14ce7c0c4f1d8ac60962e2cefdb7379059..1d9a967d5a9db16050d90178713e9d96238fc1a7 100644
--- a/indra/newview/skins/minimal/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/minimal/xui/en/floater_web_content.xml
@@ -17,6 +17,7 @@
     follows="left|right|top|bottom"
     layout="topleft"
     left="5"
+    animate="false"
     name="stack1"
     orientation="vertical"
     top="20"
@@ -155,14 +156,20 @@
       name="external_controls"
       top_delta="0"
       user_resize="false"
+      auto_resize="true"
       width="585">
       <web_browser
-        bottom="-22"
+        bottom="-2"
         follows="all"
         layout="topleft"
         left="0"
         name="webbrowser"
         top="0"/>
+      </layout_panel>
+    <layout_panel name="status_bar" 
+                  height="23"
+                  auto_resize="false"
+                  user_resize="false">
       <text
         type="string"
         length="200"
@@ -173,7 +180,7 @@
         name="statusbartext"
         parse_urls="false"
         text_color="0.4 0.4 0.4 1"
-        top_pad="5"
+        top_pad="3"
         width="495"/>
       <progress_bar
         color_bar="0.3 1.0 0.3 1"
diff --git a/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
index be13bc1bb7c672f9954d63a075bc55db0fa10531..2cb77bcdf3e9c1f4c027f66098fec47943b19efa 100644
--- a/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
@@ -23,102 +23,172 @@
      orientation="vertical"
      top_pad="5"
      width="145">
-      <layout_panel
-       auto_resize="false"
-       follows="top|left|right"
-       height="20"
-       layout="topleft"
-       left="2"
-       min_height="20"
-       width="140"
-       name="view_profile_btn_panel"
-       top="0"
-       user_resize="false">
-        <button
-         follows="left|top|right"
-         height="23"
-         label="Profile"
-         name="view_profile_btn"
+        <layout_panel
+         auto_resize="false"
+         follows="top|left|right"
+         height="20"
+         layout="topleft"
+         left="2"
+         min_height="20"
+         width="140"
+         name="view_profile_btn_panel"
          top="0"
-         width="140" />
-      </layout_panel>
-      <layout_panel
-       auto_resize="false"
-       follows="top|left|right"
-       height="25"
-       layout="topleft"
-       min_height="25"
-       width="140"
-       name="add_friend_btn_panel"
-       user_resize="false">
-        <button
-         follows="left|top|right"
-         height="23"
-         label="Add Friend"
-         name="add_friend_btn"
-         top="5"
-         width="140" />
-      </layout_panel>
-      <layout_panel
-       auto_resize="false"
-       follows="top|left|right"
-       height="25"
-       layout="topleft"
-       min_height="25"
-       width="140"
-       name="teleport_btn_panel"
-       user_resize="false">
-        <button
-             auto_resize="false"
+         user_resize="false">
+            <button
+             follows="left|top|right"
+             height="23"
+             label="Profile"
+             name="view_profile_btn"
+             top="0"
+             width="140" />
+        </layout_panel>
+        <layout_panel
+         auto_resize="false"
+         follows="top|left|right"
+         height="25"
+         layout="topleft"
+         min_height="25"
+         width="140"
+         name="add_friend_btn_panel"
+         user_resize="false">
+            <button
              follows="left|top|right"
              height="23"
-             label="Teleport"
-             name="teleport_btn"
-             tool_tip = "Offer to teleport this person"
+             label="Add Friend"
+             name="add_friend_btn"
+             top="5"
              width="140" />
-      </layout_panel>
-      <layout_panel
+        </layout_panel>
+        <layout_panel
          auto_resize="false"
          follows="top|left|right"
          height="25"
          layout="topleft"
          min_height="25"
          width="140"
-         name="call_btn_panel"
+         name="teleport_btn_panel"
          user_resize="false">
-        <button
-         follows="left|top|right"
-         height="23"
-         label="Call"
-         name="call_btn"
-         width="140" />
-      </layout_panel>
-      <layout_panel
-       auto_resize="false"
-       follows="top|left|right"
-       height="25"
-       layout="topleft"
-       min_height="25"
-       width="140"
-       name="end_call_btn_panel"
-       user_resize="false"
-       visible="false">
-        <button
-         follows="left|top|right"
-         height="23"
-         label="End Call"
-         name="end_call_btn"
-         width="140" />
-      </layout_panel>
-      <layout_panel
-       mouse_opaque="false"
-       auto_resize="true"
-       follows="top|left"
-       height="0"
-       layout="topleft"
-       min_height="0"
-       width="140"
-       name="spacer"
-       user_resize="false" />
+            <button
+                 auto_resize="false"
+                 follows="left|top|right"
+                 height="23"
+                 label="Teleport"
+                 name="teleport_btn"
+                 tool_tip = "Offer to teleport this person"
+                 width="140" />
+        </layout_panel>
+        <layout_panel
+           auto_resize="false"
+           follows="top|left|right"
+           height="25"
+           layout="topleft"
+           min_height="25"
+           width="140"
+           name="call_btn_panel"
+           user_resize="false">
+            <button
+             follows="left|top|right"
+             height="23"
+             label="Call"
+             name="call_btn"
+             width="140" />
+        </layout_panel>
+        <layout_panel
+         auto_resize="false"
+         follows="top|left|right"
+         height="25"
+         layout="topleft"
+         min_height="25"
+         width="140"
+         name="end_call_btn_panel"
+         user_resize="false"
+         visible="false">
+            <button
+             follows="left|top|right"
+             height="23"
+             label="End Call"
+             name="end_call_btn"
+             width="140" />
+        </layout_panel>
+        <layout_panel
+         auto_resize="false"
+         follows="top|left|right"
+         height="25"
+         layout="topleft"
+         min_height="25"
+         width="140"
+         name="block_btn_panel"
+         user_resize="false">
+            <button
+             follows="left|top|right"
+             height="23"
+             label="Block"
+             name="block_btn"
+             width="140" />
+        </layout_panel>
+        <layout_panel
+         auto_resize="false"
+         follows="top|left|right"
+         height="25"
+         layout="topleft"
+         min_height="25"
+         width="140"
+         name="unblock_btn_panel"
+         user_resize="false"
+         visible="false">
+            <button
+             follows="left|top|right"
+             height="23"
+             label="Unblock"
+             name="unblock_btn"
+             width="140" />
+        </layout_panel>
+        <layout_panel
+         auto_resize="false"
+         follows="top|left|right"
+         height="25"
+         layout="topleft"
+         min_height="54"
+         width="140"
+         name="volume_ctrl_panel"
+         visible="false" 
+         user_resize="false">
+            <slider
+             follows="top|left"
+             height="23"
+             increment="0.01"
+             left="0"
+             max_val="0.95"
+             min_val="0.05"
+             name="volume_slider"
+             show_text="false"
+             tool_tip="Call Volume"
+             top_pad="32"
+             value="0.5"
+             width="125" />
+            <button
+             follows="top|left"
+             height="16"
+             image_disabled="Audio_Off"
+             image_disabled_selected="AudioMute_Off"
+             image_hover_selected="AudioMute_Over"
+             image_selected="AudioMute_Off"
+             image_unselected="Audio_Off"
+             is_toggle="true"
+             left_pad="0"
+             top_delta="4"
+             name="mute_btn"
+             width="16" />
+        </layout_panel>
+        <layout_panel
+         mouse_opaque="false"
+         auto_resize="true"
+         follows="top|left"
+         height="0"
+         layout="topleft"
+         min_height="0"
+         width="140"
+         name="spacer"
+         user_resize="false" />
     </layout_stack>
 </panel>