diff --git a/autobuild.xml b/autobuild.xml
index 9d4fe8382b2b52c0102fd53ac4f58d94b4eb2599..ba0eb75f16663fe0c033ab36160cc7daa1d98324 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -2101,7 +2101,6 @@
                   <string>-G</string>
                   <string>"Visual Studio 10"</string>
                   <string>-DUNATTENDED:BOOL=ON</string>
-                  <string>-DUSE_PRECOMPILED_HEADERS=ON</string>
                   <string>-DINSTALL_PROPRIETARY=TRUE</string>
                   <string>-DUSE_KDU=FALSE</string>
                   <string>-DFMOD=FALSE</string>
@@ -2179,7 +2178,6 @@
                   <string>-G</string>
                   <string>"Visual Studio 10"</string>
                   <string>-DUNATTENDED:BOOL=ON</string>
-                  <string>-DUSE_PRECOMPILED_HEADERS=ON</string>
                   <string>-DINSTALL_PROPRIETARY=TRUE</string>
                   <string>-DUSE_KDU=FALSE</string>
                   <string>-DFMOD=FALSE</string>
@@ -2256,7 +2254,6 @@
                   <string>-G</string>
                   <string>"Visual Studio 10"</string>
                   <string>-DUNATTENDED:BOOL=ON</string>
-                  <string>-DUSE_PRECOMPILED_HEADERS=ON</string>
                   <string>-DINSTALL_PROPRIETARY=TRUE</string>
                   <string>-DUSE_KDU=FALSE</string>
                   <string>-DFMOD=FALSE</string>
diff --git a/build.sh b/build.sh
index 3d3f0d561647d9818a0468ec3614db728ee5e60d..d46da2c66d9308a39a3a95118b32d00045d17a52 100755
--- a/build.sh
+++ b/build.sh
@@ -58,7 +58,6 @@ pre_build()
     "$AUTOBUILD" configure -c $variant -- \
      -DPACKAGE:BOOL=ON \
      -DRELEASE_CRASH_REPORTING:BOOL=ON \
-     -DUSE_PRECOMPILED_HEADERS=FALSE \
      -DVIEWER_CHANNEL:STRING="\"$viewer_channel\"" \
      -DVIEWER_LOGIN_CHANNEL:STRING="\"$viewer_login_channel\"" \
      -DGRID:STRING="\"$viewer_grid\"" \
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 310e6cbdd42a7b16c70b5fe227d95b674e0d811a..d1042d6e8693ff4692a105d24885081e6a4a233d 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -35,8 +35,10 @@ endif (NOT CMAKE_BUILD_TYPE)
 
 # For the library installation process;
 # see cmake/Prebuild.cmake for the counterpart code.
-file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp)
-file(WRITE ${CMAKE_BINARY_DIR}/temp/sentinel_installed "0")
+if ("${CMAKE_SOURCE_DIR}/../autobuild.xml" IS_NEWER_THAN "${CMAKE_BINARY_DIR}/temp/sentinel_installed")
+  file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp)
+  file(WRITE ${CMAKE_BINARY_DIR}/temp/sentinel_installed "0")
+endif ("${CMAKE_SOURCE_DIR}/../autobuild.xml" IS_NEWER_THAN "${CMAKE_BINARY_DIR}/temp/sentinel_installed")
 add_subdirectory(cmake)
 
 add_subdirectory(${LIBS_OPEN_PREFIX}llaudio)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 15b827b217d9f96abac1085d4a640aaf819fa8d8..faffdc8ccdb524e6401b786b95205e1645a2774c 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -36,6 +36,13 @@ if (WINDOWS)
   # Don't build DLLs.
   set(BUILD_SHARED_LIBS OFF)
 
+  # for "backwards compatibility", cmake sneaks in the Zm1000 option which royally
+  # screws incredibuild. this hack disables it.
+  # for details see: http://connect.microsoft.com/VisualStudio/feedback/details/368107/clxx-fatal-error-c1027-inconsistent-values-for-ym-between-creation-and-use-of-precompiled-headers
+  # http://www.ogre3d.org/forums/viewtopic.php?f=2&t=60015
+  # http://www.cmake.org/pipermail/cmake/2009-September/032143.html
+  string(REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+
   set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP -D_SCL_SECURE_NO_WARNINGS=1"
       CACHE STRING "C++ compiler debug options" FORCE)
   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO 
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 3f259f6382e078b92dff9fe223058e501df6f51a..08feab6e36998c559cadb4ce01006787759c4537 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -95,7 +95,7 @@ INCLUDE(GoogleMock)
     IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
       SET(${name}_test_additional_INCLUDE_DIRS "")
     ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
-    INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
+    INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${${name}_test_additional_INCLUDE_DIRS} )
     IF(LL_TEST_VERBOSE)
       MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
     ENDIF(LL_TEST_VERBOSE)
diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake
index 1b60d176f11d141269c664a50b71a189a2e1448a..dbb4dfc46c7f034c792224ac52a33269be1e8028 100644
--- a/indra/cmake/Prebuilt.cmake
+++ b/indra/cmake/Prebuilt.cmake
@@ -1,35 +1,49 @@
 # -*- cmake -*-
 
 include(FindAutobuild)
+if(INSTALL_PROPRIETARY)
+  include(FindSCP)
+endif(INSTALL_PROPRIETARY)
 
+# The use_prebuilt_binary macro handles automated installation of package
+# dependencies using autobuild.  The goal is that 'autobuild install' should
+# only be run when we know we need to install a new package.  This should be
+# the case in a clean checkout, or if autobuild.xml has been updated since the
+# last run (encapsulated by the file ${CMAKE_BINARY_DIR}/temp/sentinel_installed),
+# or if a previous attempt to install the package has failed (the exit status
+# of previous attempts is serialized in the file
+# ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
 macro (use_prebuilt_binary _binary)
   if (NOT DEFINED STANDALONE_${_binary})
     set(STANDALONE_${_binary} ${STANDALONE})
   endif (NOT DEFINED STANDALONE_${_binary})
 
   if (NOT STANDALONE_${_binary})
-    if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
-      if(INSTALL_PROPRIETARY)
-        include(FindSCP)
-      endif(INSTALL_PROPRIETARY)
-	  if(DEBUG_PREBUILT)
-		message("cd ${CMAKE_SOURCE_DIR} && ${AUTOBUILD_EXECUTABLE} install
-		--install-dir=${AUTOBUILD_INSTALL_DIR}
-		--skip-license-check
-		${_binary} ")
-	  endif(DEBUG_PREBUILT)
-	  execute_process(COMMAND "${AUTOBUILD_EXECUTABLE}"
-		install
-		--install-dir=${AUTOBUILD_INSTALL_DIR}
-		--skip-license-check
-		${_binary}
-		WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
-		RESULT_VARIABLE ${_binary}_installed
-		)
+    if("${${_binary}_installed}" STREQUAL "" AND EXISTS "${CMAKE_BINARY_DIR}/temp/${_binary}_installed")
+      file(READ ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${_binary}_installed")
+      if(DEBUG_PREBUILT)
+        message(STATUS "${_binary}_installed: \"${${_binary}_installed}\"")
+      endif(DEBUG_PREBUILT)
+    endif("${${_binary}_installed}" STREQUAL "" AND EXISTS "${CMAKE_BINARY_DIR}/temp/${_binary}_installed")
+
+    if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed OR NOT ${${_binary}_installed} EQUAL 0)
+      if(DEBUG_PREBUILT)
+        message("cd ${CMAKE_SOURCE_DIR} && ${AUTOBUILD_EXECUTABLE} install
+        --install-dir=${AUTOBUILD_INSTALL_DIR}
+        --skip-license-check
+        ${_binary} ")
+      endif(DEBUG_PREBUILT)
+      execute_process(COMMAND "${AUTOBUILD_EXECUTABLE}"
+        install
+        --install-dir=${AUTOBUILD_INSTALL_DIR}
+        --skip-license-check
+        ${_binary}
+        WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+        RESULT_VARIABLE ${_binary}_installed
+        )
       file(WRITE ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${${_binary}_installed}")
-    else(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
-      set(${_binary}_installed 0)
-    endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
+    endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed OR NOT ${${_binary}_installed} EQUAL 0)
+
     if(NOT ${_binary}_installed EQUAL 0)
       message(FATAL_ERROR
               "Failed to download or unpack prebuilt '${_binary}'."
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 03428691cfcd815744b055a28925eecc68a1acf2..2f23e7c307c6385953460269bef39dd3b512414b 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -151,7 +151,7 @@ For more information, please see JIRA DEV-14943 - Cmake Linux cannot build both
 endif (LINUX AND SERVER AND VIEWER)
 
 
-set(USE_PRECOMPILED_HEADERS OFF CACHE BOOL "Enable use of precompiled header directives where supported.")
+set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.")
 
 source_group("CMake Rules" FILES CMakeLists.txt)
 
diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp
index c34115ee8064a6d8a63b3ad03ad85e7d44b5dfed..217e26c3ca527380c91fd8bbc1e1d42d3debc83b 100644
--- a/indra/integration_tests/llui_libtest/llui_libtest.cpp
+++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp
@@ -33,6 +33,7 @@
 // linden library includes
 #include "llcontrol.h"		// LLControlGroup
 #include "lldir.h"
+#include "lldiriterator.h"
 #include "llerrorcontrol.h"
 #include "llfloater.h"
 #include "llfontfreetype.h"
@@ -174,7 +175,9 @@ void export_test_floaters()
 	std::string delim = gDirUtilp->getDirDelimiter();
 	std::string xui_dir = get_xui_dir() + "en" + delim;
 	std::string filename;
-	while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename))
+
+	LLDirIterator iter(xui_dir, "floater_test_*.xml");
+	while (iter.next(filename))
 	{
 		if (filename.find("_new.xml") != std::string::npos)
 		{
diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp
index a81de0223c8f432b3740894fbc6dce824f5b3089..eed00ac06ec2606b3204869b6679e47f3ea97180 100644
--- a/indra/linux_updater/linux_updater.cpp
+++ b/indra/linux_updater/linux_updater.cpp
@@ -33,6 +33,7 @@
 #include "llerrorcontrol.h"
 #include "llfile.h"
 #include "lldir.h"
+#include "lldiriterator.h"
 #include "llxmlnode.h"
 #include "lltrans.h"
 
@@ -55,6 +56,8 @@ typedef struct _updater_app_state {
 	std::string strings_dirs;
 	std::string strings_file;
 
+	LLDirIterator *image_dir_iter;
+
 	GtkWidget *window;
 	GtkWidget *progress_bar;
 	GtkWidget *image;
@@ -115,7 +118,7 @@ bool translate_init(std::string comma_delim_path_list,
 void updater_app_ui_init(void);
 void updater_app_quit(UpdaterAppState *app_state);
 void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state);
-std::string next_image_filename(std::string& image_path);
+std::string next_image_filename(std::string& image_path, LLDirIterator& iter);
 void display_error(GtkWidget *parent, std::string title, std::string message);
 BOOL install_package(std::string package_file, std::string destination);
 BOOL spawn_viewer(UpdaterAppState *app_state);
@@ -181,7 +184,7 @@ void updater_app_ui_init(UpdaterAppState *app_state)
 
 		// load the first image
 		app_state->image = gtk_image_new_from_file
-			(next_image_filename(app_state->image_dir).c_str());
+			(next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str());
 		gtk_widget_set_size_request(app_state->image, 340, 310);
 		gtk_container_add(GTK_CONTAINER(frame), app_state->image);
 
@@ -212,7 +215,7 @@ gboolean rotate_image_cb(gpointer data)
 	llassert(data != NULL);
 	app_state = (UpdaterAppState *) data;
 
-	filename = next_image_filename(app_state->image_dir);
+	filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter);
 
 	gdk_threads_enter();
 	gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str());
@@ -221,10 +224,10 @@ gboolean rotate_image_cb(gpointer data)
 	return TRUE;
 }
 
-std::string next_image_filename(std::string& image_path)
+std::string next_image_filename(std::string& image_path, LLDirIterator& iter)
 {
 	std::string image_filename;
-	gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename);
+	iter.next(image_filename);
 	return image_path + "/" + image_filename;
 }
 
@@ -748,6 +751,7 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
 		else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc))
 		{
 			app_state->image_dir = argv[i];
+			app_state->image_dir_iter = new LLDirIterator(argv[i], "/*.jpg");
 		}
 		else if ((!strcmp(argv[i], "--dest")) && (++i < argc))
 		{
@@ -832,6 +836,7 @@ int main(int argc, char **argv)
 	}
 
 	bool success = !app_state->failure;
+	delete app_state->image_dir_iter;
 	delete app_state;
 	return success ? 0 : 1;
 }
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 39daefd1ad63ce8b29827972473dadfab53d3c5c..ed192a9975125106a8ffafb4d1f72b84d59f0917 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -24,6 +24,10 @@
  * $/LicenseInfo$
  */
 
+#include "linden_common.h"
+
+#include "llapp.h"
+
 #include <cstdlib>
 
 #ifdef LL_DARWIN
@@ -32,9 +36,6 @@
 #include <sys/sysctl.h>
 #endif
 
-#include "linden_common.h"
-#include "llapp.h"
-
 #include "llcommon.h"
 #include "llapr.h"
 #include "llerrorcontrol.h"
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 16aa49b65342f77e4df25e615c10eb58e13f0c96..0cfc393e05053f56a72ecec85d6fcc14adebe779 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -27,7 +27,6 @@
 #ifndef LL_LLBUTTON_H
 #define LL_LLBUTTON_H
 
-#include "lluuid.h"
 #include "llcontrol.h"
 #include "lluictrl.h"
 #include "v4color.h"
@@ -53,6 +52,8 @@ S32 round_up(S32 grid, S32 value);
 
 
 class LLUICtrlFactory;
+class LLUIImage;
+class LLUUID;
 
 //
 // Classes
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index 94387fb41a5b18e2b065eaf36eddc04c9b0b4a2d..8414b92113d9646864e4715dbc37c70213ea91fa 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -27,14 +27,9 @@
 #define LLFLOATERREG_H
 
 /// llcommon
-#include "llboost.h"
 #include "llrect.h"
-#include "llstl.h"
 #include "llsd.h"
 
-/// llui
-#include "lluictrl.h"
-
 #include <boost/function.hpp>
 
 //*******************************************************
@@ -43,6 +38,7 @@
 //
 
 class LLFloater;
+class LLUICtrl;
 
 typedef boost::function<LLFloater* (const LLSD& key)> LLFloaterBuildFunc;
 
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 43e5f6b051d4f344c7e65f91a2fabc6bc67ab4dc..724d190307dcb841f96d6ebf7f30219d098eb9b8 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -113,6 +113,16 @@ boost::signals2::connection	LLFocusableElement::setTopLostCallback(const focus_s
 
 
 
+typedef std::list<LLHandle<LLView> > view_handle_list_t;
+typedef std::map<LLHandle<LLView>, LLHandle<LLView> > focus_history_map_t;
+struct LLFocusMgr::Impl
+{
+	// caching list of keyboard focus ancestors for calling onFocusReceived and onFocusLost
+	view_handle_list_t mCachedKeyboardFocusList;
+
+	focus_history_map_t mFocusHistory;
+};
+
 LLFocusMgr gFocusMgr;
 
 LLFocusMgr::LLFocusMgr()
@@ -123,10 +133,17 @@ LLFocusMgr::LLFocusMgr()
 	mDefaultKeyboardFocus( NULL ),
 	mKeystrokesOnly(FALSE),
 	mTopCtrl( NULL ),
-	mAppHasFocus(TRUE)   // Macs don't seem to notify us that we've gotten focus, so default to true
+	mAppHasFocus(TRUE),   // Macs don't seem to notify us that we've gotten focus, so default to true
+	mImpl(new LLFocusMgr::Impl)
 {
 }
 
+LLFocusMgr::~LLFocusMgr()
+{
+	mImpl->mFocusHistory.clear();
+	delete mImpl;
+	mImpl = NULL;
+}
 
 void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
 {
@@ -179,7 +196,7 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL
 		mKeyboardFocus = new_focus;
 
 		// list of the focus and it's ancestors
-		view_handle_list_t old_focus_list = mCachedKeyboardFocusList;
+		view_handle_list_t old_focus_list = mImpl->mCachedKeyboardFocusList;
 		view_handle_list_t new_focus_list;
 
 		// walk up the tree to root and add all views to the new_focus_list
@@ -206,7 +223,7 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL
 			LLView* old_focus_view = old_focus_iter->get();
 			if (old_focus_view)
 			{
-				mCachedKeyboardFocusList.pop_front();
+				mImpl->mCachedKeyboardFocusList.pop_front();
 				old_focus_view->onFocusLost();
 			}
 		}
@@ -219,7 +236,7 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL
 			LLView* new_focus_view = new_focus_riter->get();
 			if (new_focus_view)
 			{
-                mCachedKeyboardFocusList.push_front(new_focus_view->getHandle());
+                mImpl->mCachedKeyboardFocusList.push_front(new_focus_view->getHandle());
 				new_focus_view->onFocusReceived();
 			}
 		}
@@ -254,7 +271,7 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL
 		if (focus_subtree)
 		{
 			LLView* focused_view = dynamic_cast<LLView*>(mKeyboardFocus);
-			mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle<LLView>(); 
+			mImpl->mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle<LLView>(); 
 		}
 	}
 	
@@ -456,8 +473,8 @@ LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const
 {
 	if (subtree_root)
 	{
-		focus_history_map_t::const_iterator found_it = mFocusHistory.find(subtree_root->getHandle());
-		if (found_it != mFocusHistory.end())
+		focus_history_map_t::const_iterator found_it = mImpl->mFocusHistory.find(subtree_root->getHandle());
+		if (found_it != mImpl->mFocusHistory.end())
 		{
 			// found last focus for this subtree
 			return static_cast<LLUICtrl*>(found_it->second.get());
@@ -470,6 +487,6 @@ void LLFocusMgr::clearLastFocusForGroup(LLView* subtree_root)
 {
 	if (subtree_root)
 	{
-		mFocusHistory.erase(subtree_root->getHandle());
+		mImpl->mFocusHistory.erase(subtree_root->getHandle());
 	}
 }
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index 22c1895075e70b8a5e1f5ee9d94841c79b507064..25ae1d2579d272126fa7690a476a87742c5b5785 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -74,7 +74,7 @@ class LLFocusMgr
 {
 public:
 	LLFocusMgr();
-	~LLFocusMgr() { mFocusHistory.clear(); }
+	~LLFocusMgr();
 
 	// Mouse Captor
 	void			setMouseCapture(LLMouseHandler* new_captor);	// new_captor = NULL to release the mouse.
@@ -120,6 +120,8 @@ class LLFocusMgr
 
 	bool			keyboardFocusHasAccelerators() const;
 
+	struct Impl;
+
 private:
 	LLUICtrl*			mLockedView;
 
@@ -132,10 +134,6 @@ class LLFocusMgr
 	LLFocusableElement*	mDefaultKeyboardFocus;
 	BOOL				mKeystrokesOnly;
 	
-	// caching list of keyboard focus ancestors for calling onFocusReceived and onFocusLost
-	typedef std::list<LLHandle<LLView> > view_handle_list_t;
-	view_handle_list_t mCachedKeyboardFocusList;
-
 	// Top View
 	LLUICtrl*			mTopCtrl;
 
@@ -143,8 +141,7 @@ class LLFocusMgr
 
 	BOOL				mAppHasFocus;
 
-	typedef std::map<LLHandle<LLView>, LLHandle<LLView> > focus_history_map_t;
-	focus_history_map_t mFocusHistory;
+	Impl * mImpl;
 };
 
 extern LLFocusMgr gFocusMgr;
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index 669e126266adced8157b393ee4dd28dca1c905c0..efa0925a4a9364b493d44ab096ae723f100962a1 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -30,6 +30,7 @@
 #include "lluuid.h"
 #include "v4color.h"
 #include "lluictrl.h"
+#include "lluiimage.h"
 #include "stdenums.h"
 
 class LLTextBox;
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 7b5fa218f23ca775e306f395d22edfd533a67e86..fe191e59714aad3a261878628799d50b7ff0670f 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -41,6 +41,7 @@
 
 #include "lleditmenuhandler.h"
 #include "lluictrl.h"
+#include "lluiimage.h"
 #include "lluistring.h"
 #include "llviewborder.h"
 
diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h
index c0cb1cc74a9df96fc06566a07648e17c6e6cad24..4c47cc267cc96df4da59b263d4e6d51cd63f7d7c 100644
--- a/indra/llui/llloadingindicator.h
+++ b/indra/llui/llloadingindicator.h
@@ -28,6 +28,7 @@
 #define LL_LLLOADINGINDICATOR_H
 
 #include "lluictrl.h"
+#include "lluiimage.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // class LLLoadingIndicator
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index d4e6091ee037eb409fdacd391a61ef0a7913b4f8..f744e9db415dcb78f969f6c2e6ae62cb24b22bfd 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -35,6 +35,7 @@
 #include "llkeyboard.h"			// for the MASK constants
 #include "llcontrol.h"
 #include "lluictrlfactory.h"
+#include "lluiimage.h"
 
 #include <sstream>
 
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index c1a1a06f39c02ed8ef36e6d3d4e4c108d0b04944..7bbbeaf709cacfa8f93c5cff9623ebd53d3f1bac 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -32,6 +32,7 @@
 #include "llcallbackmap.h"
 #include "lluictrl.h"
 #include "llviewborder.h"
+#include "lluiimage.h"
 #include "lluistring.h"
 #include "v4color.h"
 #include <list>
diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp
index ead22686bc405d21191d5aa342350a93d1bc75fe..84a890edfa59268076cb46a410038a9374685b44 100644
--- a/indra/llui/llprogressbar.cpp
+++ b/indra/llui/llprogressbar.cpp
@@ -38,6 +38,7 @@
 
 #include "llfocusmgr.h"
 #include "lluictrlfactory.h"
+#include "lluiimage.h"
 
 static LLDefaultChildRegistry::Register<LLProgressBar> r("progress_bar");
 
diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h
index 3f308e749683feb09e748f9ef522d936ecc83e1a..a8ec83ea00434c169a0cd77bc955daf4a9a0e7e1 100644
--- a/indra/llui/llprogressbar.h
+++ b/indra/llui/llprogressbar.h
@@ -27,8 +27,9 @@
 #ifndef LL_LLPROGRESSBAR_H
 #define LL_LLPROGRESSBAR_H
 
-#include "lluictrl.h"
 #include "llframetimer.h"
+#include "lluictrl.h"
+#include "lluiimage.h"
 
 class LLProgressBar
 	: public LLUICtrl
diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h
index 68823ed68e46b7619ec7c74250b1031734015997..700c17ea3e9c06ab34636eb732e5c3b7373de51a 100644
--- a/indra/llui/llslider.h
+++ b/indra/llui/llslider.h
@@ -29,6 +29,7 @@
 
 #include "llf32uictrl.h"
 #include "v4color.h"
+#include "lluiimage.h"
 
 class LLSlider : public LLF32UICtrl
 {
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index 28a064e6b60c4e4ea8c8653ecd028c44cdc1e3fb..bb731f4f7e222a01ac3c339f36b7b552f26d9d85 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -88,7 +88,7 @@ void LLStyle::setVisible(BOOL is_visible)
 	mVisible = is_visible;
 }
 
-LLUIImagePtr LLStyle::getImage() const
+LLPointer<LLUIImage> LLStyle::getImage() const
 {
 	return mImagep;
 }
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 322edc343ce9ba1f94ac9cc73e23092e6e679ebc..9f1eba79d8c30ca56a1c9dac4fb984fda68eb95d 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -30,6 +30,7 @@
 #include "v4color.h"
 #include "llui.h"
 #include "llinitparam.h"
+#include "lluiimage.h"
 
 class LLFontGL;
 
@@ -72,7 +73,7 @@ class LLStyle : public LLRefCount
 	void setLinkHREF(const std::string& href);
 	BOOL isLink() const;
 
-	LLUIImagePtr getImage() const;
+	LLPointer<LLUIImage> getImage() const;
 	void setImage(const LLUUID& src);
 	void setImage(const std::string& name);
 
@@ -108,7 +109,7 @@ class LLStyle : public LLRefCount
 	const LLFontGL*		mFont;
 	std::string			mLink;
 	bool				mIsLink;
-	LLUIImagePtr		mImagep;
+	LLPointer<LLUIImage> mImagep;
 };
 
 typedef LLPointer<LLStyle> LLStyleSP;
diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp
index 9d0ff9d5cb17ecccee1f37da8a3b51207707f514..58fa8a0828245a856e4f5730f317a192824acd65 100644
--- a/indra/llui/lltransutil.cpp
+++ b/indra/llui/lltransutil.cpp
@@ -26,10 +26,11 @@
 
 #include "linden_common.h"
 
+#include "lltransutil.h"
+
 #include "lltrans.h"
 #include "lluictrlfactory.h"
-
-#include "lltransutil.h"
+#include "llxmlnode.h"
 
 
 bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<std::string>& default_args)
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 6a43477693b0f54b488ec8e0b1c0af75f4308faa..c583d58d5a5076645fc797bf4bc556eb36879deb 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -33,15 +33,12 @@
 #include "llrect.h"
 #include "llcontrol.h"
 #include "llcoord.h"
-#include "lluiimage.h"		// *TODO: break this dependency, need to add #include "lluiimage.h" to all widgets that hold an Optional<LLUIImage*> in their paramblocks
 #include "llinitparam.h"
 #include "llregistry.h"
 #include "lluicolor.h"
 #include "lluicolortable.h"
 #include <boost/signals2.hpp>
 #include "lllazyvalue.h"
-#include "llhandle.h"		// *TODO: remove this dependency, added as a 
-							// convenience when LLHandle moved to llhandle.h
 #include "llframetimer.h"
 
 // LLUIFactory
@@ -265,8 +262,6 @@ class LLUI
 
 // Moved LLLocalClipRect to lllocalcliprect.h
 
-// Moved all LLHandle-related code to llhandle.h
-
 //RN: maybe this needs to moved elsewhere?
 class LLImageProviderInterface
 {
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 61dc4b80305eae6d223ea8220a0b90d550efe018..8f167959b9ee370e94d68cb96ab420324c9c8dca 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -34,6 +34,7 @@
 #include "stdtypes.h"
 #include "llcoord.h"
 #include "llfontgl.h"
+#include "llhandle.h"
 #include "llmortician.h"
 #include "llmousehandler.h"
 #include "llstring.h"
diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp
index 89cd34c37c1c231650e3aaec7b0edecd4c947683..32d7ea7c25ae46fbb47c356f6858be8d8424d4ee 100644
--- a/indra/llui/llviewborder.cpp
+++ b/indra/llui/llviewborder.cpp
@@ -28,6 +28,7 @@
 #include "llrender.h"
 #include "llfocusmgr.h"
 #include "lluictrlfactory.h"
+#include "lluiimage.h"
 
 static LLDefaultChildRegistry::Register<LLViewBorder> r("view_border");
 
diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h
index 00471959296dd0429d0f500f5911e6d9b28756ff..09ffc2cd54ba26fe487480c8244d726fd0ff0974 100644
--- a/indra/llui/llwindowshade.h
+++ b/indra/llui/llwindowshade.h
@@ -29,6 +29,7 @@
 
 #include "lluictrl.h"
 #include "llnotifications.h"
+#include "lluiimage.h"
 
 class LLWindowShade : public LLUICtrl
 {
diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index 722f4e2bfdef9c6212c9edf06f2abee5f55ff996..a3782d824b4cbbcf0abe31ecb5d754238cf3c8a5 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -12,6 +12,7 @@ include_directories(
 
 set(llvfs_SOURCE_FILES
     lldir.cpp
+    lldiriterator.cpp
     lllfsthread.cpp
     llpidlock.cpp
     llvfile.cpp
@@ -24,6 +25,7 @@ set(llvfs_HEADER_FILES
 
     lldir.h
     lldirguard.h
+    lldiriterator.h
     lllfsthread.h
     llpidlock.h
     llvfile.h
@@ -60,6 +62,11 @@ list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES})
 
 add_library (llvfs ${llvfs_SOURCE_FILES})
 
+target_link_libraries(llvfs
+    ${BOOST_FILESYSTEM_LIBRARY}
+    ${BOOST_SYSTEM_LIBRARY}
+    )
+
 if (DARWIN)
   include(CMakeFindFrameworks)
   find_library(CARBON_LIBRARY Carbon)
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 341c96f6ea7b9a4d9cd790cb6c71128dffbe2a7b..f3ac17d612b130fbb65e95162b0b22d169377353 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -40,6 +40,8 @@
 #include "lltimer.h"	// ms_sleep()
 #include "lluuid.h"
 
+#include "lldiriterator.h"
+
 #if LL_WINDOWS
 #include "lldir_win32.h"
 LLDir_Win32 gDirUtil;
@@ -83,7 +85,9 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
 	std::string filename; 
 	std::string fullpath;
 	S32 result;
-	while (getNextFileInDir(dirname, mask, filename))
+
+	LLDirIterator iter(dirname, mask);
+	while (iter.next(filename))
 	{
 		fullpath = dirname;
 		fullpath += getDirDelimiter();
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 42996fd051b9f5cc8ed949645fa7fda5c4c58f74..5ee8bdb542da2ebc4ee3d10ce114a7df3c1e20b6 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -75,31 +75,6 @@ class LLDir
 // pure virtual functions
 	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
 
-    /// Walk the files in a directory, with file pattern matching
-	virtual BOOL getNextFileInDir(const std::string& dirname, ///< directory path - must end in trailing slash!
-                                  const std::string& mask,    ///< file pattern string (use "*" for all)
-                                  std::string& fname          ///< output: found file name
-                                  ) = 0;
-    /**<
-     * @returns true if a file was found, false if the entire directory has been scanned.
-     *
-     * @note that this function is NOT thread safe
-     *
-     * This function may not be used to scan part of a directory, then start a new search of a different
-     * directory, and then restart the first search where it left off; the entire search must run to
-     * completion or be abandoned - there is no restart.
-     *
-     * @bug: See http://jira.secondlife.com/browse/VWR-23697
-     *       and/or the tests in test/lldir_test.cpp
-     *       This is known to fail with patterns that have both:
-     *       a wildcard left of a . and more than one sequential ? right of a .
-     *       the pattern foo.??x appears to work
-     *       but *.??x or foo?.??x do not
-     *
-     * @todo this really should be rewritten as an iterator object, and the
-     *       filtering should be done in a platform-independent way.
-     */
-
 	virtual std::string getCurPath() = 0;
 	virtual BOOL fileExists(const std::string &filename) const = 0;
 
diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index 72b54f538083c5937012865572526c1b8afca0b6..407f3b93fbe95ca3c03dbc3ae2dc793ff84398bf 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -242,68 +242,6 @@ U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &
 	return (file_count);
 }
 
-// get the next file in the directory
-BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
-	glob_t g;
-	BOOL result = FALSE;
-	fname = "";
-	
-	if(!(dirname == mCurrentDir))
-	{
-		// different dir specified, close old search
-		mCurrentDirIndex = -1;
-		mCurrentDirCount = -1;
-		mCurrentDir = dirname;
-	}
-	
-	std::string tmp_str;
-	tmp_str = dirname;
-	tmp_str += mask;
-
-	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
-	{
-		if(g.gl_pathc > 0)
-		{
-			if((int)g.gl_pathc != mCurrentDirCount)
-			{
-				// Number of matches has changed since the last search, meaning a file has been added or deleted.
-				// Reset the index.
-				mCurrentDirIndex = -1;
-				mCurrentDirCount = g.gl_pathc;
-			}
-	
-			mCurrentDirIndex++;
-	
-			if(mCurrentDirIndex < (int)g.gl_pathc)
-			{
-//				llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
-
-				// The API wants just the filename, not the full path.
-				//fname = g.gl_pathv[mCurrentDirIndex];
-
-				char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
-				
-				if(s == NULL)
-					s = g.gl_pathv[mCurrentDirIndex];
-				else if(s[0] == '/')
-					s++;
-					
-				fname = s;
-				
-				result = TRUE;
-			}
-		}
-		
-		globfree(&g);
-	}
-	
-	return(result);
-}
-
-
-
-
 std::string LLDir_Linux::getCurPath()
 {
 	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */ 
diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h
index a34de1241d625afcb13aae9673c88f3c8831532c..76032398675ae3cdb8545be805b8bc89c7c88e82 100644
--- a/indra/llvfs/lldir_linux.h
+++ b/indra/llvfs/lldir_linux.h
@@ -47,7 +47,6 @@ class LLDir_Linux : public LLDir
 
 	virtual std::string getCurPath();
 	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
-	virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
 	/*virtual*/ BOOL fileExists(const std::string &filename) const;
 
 	/*virtual*/ std::string getLLPluginLauncher();
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index f9369b043eb47e4583dd88af6c737871f9bf9bea..8f48f92e2a057bcde53eb437d5901fc8ec6de74c 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -258,67 +258,6 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma
 	return (file_count);
 }
 
-// get the next file in the directory
-BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
-	glob_t g;
-	BOOL result = FALSE;
-	fname = "";
-	
-	if(!(dirname == mCurrentDir))
-	{
-		// different dir specified, close old search
-		mCurrentDirIndex = -1;
-		mCurrentDirCount = -1;
-		mCurrentDir = dirname;
-	}
-	
-	std::string tmp_str;
-	tmp_str = dirname;
-	tmp_str += mask;
-
-	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
-	{
-		if(g.gl_pathc > 0)
-		{
-			if(g.gl_pathc != mCurrentDirCount)
-			{
-				// Number of matches has changed since the last search, meaning a file has been added or deleted.
-				// Reset the index.
-				mCurrentDirIndex = -1;
-				mCurrentDirCount = g.gl_pathc;
-			}
-	
-			mCurrentDirIndex++;
-	
-			if(mCurrentDirIndex < g.gl_pathc)
-			{
-//				llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
-
-				// The API wants just the filename, not the full path.
-				//fname = g.gl_pathv[mCurrentDirIndex];
-
-				char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
-				
-				if(s == NULL)
-					s = g.gl_pathv[mCurrentDirIndex];
-				else if(s[0] == '/')
-					s++;
-					
-				fname = s;
-				
-				result = TRUE;
-			}
-		}
-		
-		globfree(&g);
-	}
-	
-	return(result);
-}
-
-
-
 S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)
 {
 	glob_t g;
diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h
index b456d3afca989ef93f0cdc2b5c39f723e78763bb..bc3f0fac0012578dd58be36a7c42b6834e4df206 100644
--- a/indra/llvfs/lldir_mac.h
+++ b/indra/llvfs/lldir_mac.h
@@ -47,7 +47,6 @@ class LLDir_Mac : public LLDir
 	virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
 	virtual std::string getCurPath();
 	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
-	virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
 	virtual BOOL fileExists(const std::string &filename) const;
 
 	/*virtual*/ std::string getLLPluginLauncher();
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
index 515fd66b6e9a9f4d2aef1647ad78134a15419f0c..21f8c3acdbeefa56272bac597cf5b1d1858ba46c 100644
--- a/indra/llvfs/lldir_solaris.cpp
+++ b/indra/llvfs/lldir_solaris.cpp
@@ -260,68 +260,6 @@ U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string
 	return (file_count);
 }
 
-// get the next file in the directory
-BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
-	glob_t g;
-	BOOL result = FALSE;
-	fname = "";
-	
-	if(!(dirname == mCurrentDir))
-	{
-		// different dir specified, close old search
-		mCurrentDirIndex = -1;
-		mCurrentDirCount = -1;
-		mCurrentDir = dirname;
-	}
-	
-	std::string tmp_str;
-	tmp_str = dirname;
-	tmp_str += mask;
-
-	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
-	{
-		if(g.gl_pathc > 0)
-		{
-			if((int)g.gl_pathc != mCurrentDirCount)
-			{
-				// Number of matches has changed since the last search, meaning a file has been added or deleted.
-				// Reset the index.
-				mCurrentDirIndex = -1;
-				mCurrentDirCount = g.gl_pathc;
-			}
-	
-			mCurrentDirIndex++;
-	
-			if(mCurrentDirIndex < (int)g.gl_pathc)
-			{
-//				llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
-
-				// The API wants just the filename, not the full path.
-				//fname = g.gl_pathv[mCurrentDirIndex];
-
-				char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
-				
-				if(s == NULL)
-					s = g.gl_pathv[mCurrentDirIndex];
-				else if(s[0] == '/')
-					s++;
-					
-				fname = s;
-				
-				result = TRUE;
-			}
-		}
-		
-		globfree(&g);
-	}
-	
-	return(result);
-}
-
-
-
-
 std::string LLDir_Solaris::getCurPath()
 {
 	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */ 
diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h
index 70fac6f8185941adef6aeba13d9f73b7181b8ceb..0b58a45b15e07582128d190b160c85788b7d0c05 100644
--- a/indra/llvfs/lldir_solaris.h
+++ b/indra/llvfs/lldir_solaris.h
@@ -47,7 +47,6 @@ class LLDir_Solaris : public LLDir
 
 	virtual std::string getCurPath();
 	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
-	virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
 	/*virtual*/ BOOL fileExists(const std::string &filename) const;
 
 private:
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 4e2a55f4b30789f9ce8ce8eb6dc8fe0c721caca3..7709945123637d75b7f773b0437c59459f157198 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -240,67 +240,6 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &
 	return (file_count);
 }
 
-
-// get the next file in the directory
-BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
-    BOOL fileFound = FALSE;
-	fname = "";
-
-	WIN32_FIND_DATAW FileData;
-    llutf16string pathname = utf8str_to_utf16str(dirname) + utf8str_to_utf16str(mask);
-
-	if (pathname != mCurrentDir)
-	{
-		// different dir specified, close old search
-		if (!mCurrentDir.empty())
-		{
-			FindClose(mDirSearch_h);
-		}
-		mCurrentDir = pathname;
-
-		// and open new one
-		// Check error opening Directory structure
-		if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)   
-		{
-           fileFound = TRUE;
-		}
-	}
-
-    // Loop to skip over the current (.) and parent (..) directory entries
-    // (apparently returned in Win7 but not XP)
-    do
-    {
-       if (   fileFound
-           && (  (lstrcmp(FileData.cFileName, (LPCTSTR)TEXT(".")) == 0)
-               ||(lstrcmp(FileData.cFileName, (LPCTSTR)TEXT("..")) == 0)
-               )
-           )
-       {
-          fileFound = FALSE;
-       }
-    } while (   mDirSearch_h != INVALID_HANDLE_VALUE
-             && !fileFound
-             && (fileFound = FindNextFile(mDirSearch_h, &FileData)
-                 )
-             );
-
-    if (!fileFound && GetLastError() == ERROR_NO_MORE_FILES)
-    {
-       // No more files, so reset to beginning of directory
-       FindClose(mDirSearch_h);
-       mCurrentDir[0] = '\000';
-    }
-
-    if (fileFound)
-    {
-        // convert from TCHAR to char
-        fname = utf16str_to_utf8str(FileData.cFileName);
-	}
-    
-	return fileFound;
-}
-
 std::string LLDir_Win32::getCurPath()
 {
 	WCHAR w_str[MAX_PATH];
diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h
index b170ebbcd7da551cb3f0182bd51bd7ad419e40a6..62fb4713abe53ef6257d910525da1bd0efc83798 100644
--- a/indra/llvfs/lldir_win32.h
+++ b/indra/llvfs/lldir_win32.h
@@ -44,15 +44,12 @@ class LLDir_Win32 : public LLDir
 
 	/*virtual*/ std::string getCurPath();
 	/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask);
-	/*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
 	/*virtual*/ BOOL fileExists(const std::string &filename) const;
 
 	/*virtual*/ std::string getLLPluginLauncher();
 	/*virtual*/ std::string getLLPluginFilename(std::string base_name);
 
 private:
-	BOOL getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname);
-
 	void* mDirSearch_h;
 	llutf16string mCurrentDir;
 };
diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp
index 8788bd63e87d2b8030324ffcd0e0434057844151..ea321c5ae958829d739137eae3548f5cbf07c540 100644
--- a/indra/llvfs/tests/lldir_test.cpp
+++ b/indra/llvfs/tests/lldir_test.cpp
@@ -28,6 +28,7 @@
 #include "linden_common.h"
 
 #include "../lldir.h"
+#include "../lldiriterator.h"
 
 #include "../test/lltut.h"
 
@@ -259,13 +260,12 @@ namespace tut
 
    std::string makeTestFile( const std::string& dir, const std::string& file )
    {
-      std::string delim = gDirUtilp->getDirDelimiter();
-      std::string path = dir + delim + file;
+      std::string path = dir + file;
       LLFILE* handle = LLFile::fopen( path, "w" );
       ensure("failed to open test file '"+path+"'", handle != NULL );
       // Harbison & Steele, 4th ed., p. 366: "If an error occurs, fputs
       // returns EOF; otherwise, it returns some other, nonnegative value."
-      ensure("failed to write to test file '"+path+"'", fputs("test file", handle) >= 0);
+      ensure("failed to write to test file '"+path+"'", EOF != fputs("test file", handle) );
       fclose(handle);
       return path;
    }
@@ -290,7 +290,7 @@ namespace tut
    }
 
    static const char* DirScanFilename[5] = { "file1.abc", "file2.abc", "file1.xyz", "file2.xyz", "file1.mno" };
-   
+
    void scanTest(const std::string& directory, const std::string& pattern, bool correctResult[5])
    {
 
@@ -300,7 +300,8 @@ namespace tut
       bool  filesFound[5] = { false, false, false, false, false };
       //std::cerr << "searching '"+directory+"' for '"+pattern+"'\n";
 
-      while ( found <= 5 && gDirUtilp->getNextFileInDir(directory, pattern, scanResult) )
+      LLDirIterator iter(directory, pattern);
+      while ( found <= 5 && iter.next(scanResult) )
       {
          found++;
          //std::cerr << "  found '"+scanResult+"'\n";
@@ -334,15 +335,15 @@ namespace tut
    
    template<> template<>
    void LLDirTest_object_t::test<5>()
-      // getNextFileInDir
+      // LLDirIterator::next
    {
       std::string delim = gDirUtilp->getDirDelimiter();
       std::string dirTemp = LLFile::tmpdir();
 
       // Create the same 5 file names of the two directories
 
-      std::string dir1 = makeTestDir(dirTemp + "getNextFileInDir");
-      std::string dir2 = makeTestDir(dirTemp + "getNextFileInDir");
+      std::string dir1 = makeTestDir(dirTemp + "LLDirIterator");
+      std::string dir2 = makeTestDir(dirTemp + "LLDirIterator");
       std::string dir1files[5];
       std::string dir2files[5];
       for (int i=0; i<5; i++)
@@ -380,19 +381,17 @@ namespace tut
       scanTest(dir2, "file?.x?z", expected7);
 
       // Scan dir2 and see if any file?.??c files are found
-      // THESE FAIL ON Mac and Windows, SO ARE COMMENTED OUT FOR NOW
-      //      bool  expected8[5] = { true, true, false, false, false };
-      //      scanTest(dir2, "file?.??c", expected8);
-      //      scanTest(dir2, "*.??c", expected8);
+      bool  expected8[5] = { true, true, false, false, false };
+      scanTest(dir2, "file?.??c", expected8);
+      scanTest(dir2, "*.??c", expected8);
 
       // Scan dir1 and see if any *.?n? files are found
       bool  expected9[5] = { false, false, false, false, true };
       scanTest(dir1, "*.?n?", expected9);
 
       // Scan dir1 and see if any *.???? files are found
-      // THIS ONE FAILS ON WINDOWS (returns three charater suffixes) SO IS COMMENTED OUT FOR NOW
-      // bool  expected10[5] = { false, false, false, false, false };
-      // scanTest(dir1, "*.????", expected10);
+      bool  expected10[5] = { false, false, false, false, false };
+      scanTest(dir1, "*.????", expected10);
 
       // Scan dir1 and see if any ?????.* files are found
       bool  expected11[5] = { true, true, true, true, true };
@@ -402,6 +401,15 @@ namespace tut
       bool  expected12[5] = { false, false, true, true, false };
       scanTest(dir1, "??l??.xyz", expected12);
 
+      bool expected13[5] = { true, false, true, false, false };
+      scanTest(dir1, "file1.{abc,xyz}", expected13);
+
+      bool expected14[5] = { true, true, false, false, false };
+      scanTest(dir1, "file[0-9].abc", expected14);
+
+      bool expected15[5] = { true, true, false, false, false };
+      scanTest(dir1, "file[!a-z].abc", expected15);
+
       // clean up all test files and directories
       for (int i=0; i<5; i++)
       {
diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp
index e13d73c6401e48364932f838f6799eff8cf87a44..b403b86048ad81e48d76f7a47e987ce3fa0d6d82 100644
--- a/indra/llxuixml/lltrans.cpp
+++ b/indra/llxuixml/lltrans.cpp
@@ -30,6 +30,7 @@
 
 #include "llfasttimer.h"	// for call count statistics
 #include "llxuiparser.h"
+#include "llxmlnode.h"
 
 #include <map>
 
diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h
index 5b127b53cff94472f2f388448d7bcf430ee64dd8..b7091f77e8f6c7ab9eb0c6b25cfbfd972668086f 100644
--- a/indra/llxuixml/lltrans.h
+++ b/indra/llxuixml/lltrans.h
@@ -29,8 +29,10 @@
 
 #include <map>
 
+#include "llpointer.h"
 #include "llstring.h"
-#include "llxmlnode.h"
+
+class LLXMLNode;
 
 /**
  * @brief String template loaded from strings.xml
@@ -61,9 +63,9 @@ class LLTrans
 	 * @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE"
 	 * @returns true if the file was parsed successfully, true if something went wrong
 	 */
-	static bool parseStrings(LLXMLNodePtr& root, const std::set<std::string>& default_args);
+	static bool parseStrings(LLPointer<LLXMLNode> & root, const std::set<std::string>& default_args);
 
-	static bool parseLanguageStrings(LLXMLNodePtr &root);
+	static bool parseLanguageStrings(LLPointer<LLXMLNode> & root);
 
 	/**
 	 * @brief Returns a translated string
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
index 7a748d8aea770562f7312b2686fbe74de0fb10b8..0c38c4da936b2feb28e4e58172f4db6c2c0f6b34 100644
--- a/indra/llxuixml/llxuiparser.h
+++ b/indra/llxuixml/llxuiparser.h
@@ -28,7 +28,6 @@
 #define LLXUIPARSER_H
 
 #include "llinitparam.h"
-#include "llfasttimer.h"
 #include "llregistry.h"
 #include "llpointer.h"
 
@@ -95,6 +94,7 @@ class LLXUIXSDWriter : public LLXSDWriter
 };
 
 
+class LLXUIParserImpl;
 
 class LLXUIParser : public LLInitParam::Parser
 {
@@ -176,6 +176,7 @@ LOG_CLASS(LLXUIParser);
 // ordering of child elements from base file to localized diff file.  Then we can use a pair
 // of coroutines to perform matching of xml nodes during parsing.  Not sure if the overhead
 // of coroutines would offset the gain from SAX parsing
+class LLSimpleXUIParserImpl;
 
 class LLSimpleXUIParser : public LLInitParam::Parser
 {
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 7319c0d902cd87c0b78ce867ff384e888928935a..8f5efcf941768d4f7755b5ef70a40cd031ea5599 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -25,10 +25,12 @@
  */
 
 #include "llviewerprecompiledheaders.h"
+
 #include "llagent.h" 
 
 #include "pipeline.h"
 
+#include "llagentaccess.h"
 #include "llagentcamera.h"
 #include "llagentlistener.h"
 #include "llagentwearables.h"
@@ -36,6 +38,7 @@
 #include "llanimationstates.h"
 #include "llbottomtray.h"
 #include "llcallingcard.h"
+#include "llcapabilitylistener.h"
 #include "llchannelmanager.h"
 #include "llconsole.h"
 #include "llfirstuse.h"
@@ -55,8 +58,10 @@
 #include "llpaneltopinfobar.h"
 #include "llparcel.h"
 #include "llrendersphere.h"
+#include "llsdmessage.h"
 #include "llsdutil.h"
 #include "llsky.h"
+#include "llslurl.h"
 #include "llsmoothstep.h"
 #include "llstartup.h"
 #include "llstatusbar.h"
@@ -74,6 +79,7 @@
 #include "llviewerobjectlist.h"
 #include "llviewerparcelmgr.h"
 #include "llviewerstats.h"
+#include "llviewerwindow.h"
 #include "llvoavatarself.h"
 #include "llwindow.h"
 #include "llworld.h"
@@ -172,7 +178,8 @@ LLAgent::LLAgent() :
 	mbRunning(false),
 	mbTeleportKeepsLookAt(false),
 
-	mAgentAccess(gSavedSettings),
+	mAgentAccess(new LLAgentAccess(gSavedSettings)),
+	mTeleportSourceSLURL(new LLSLURL),
 	mTeleportState( TELEPORT_NONE ),
 	mRegionp(NULL),
 
@@ -209,7 +216,7 @@ LLAgent::LLAgent() :
 	mAutoPilotFinishedCallback(NULL),
 	mAutoPilotCallbackData(NULL),
 	
-	mEffectColor(LLColor4(0.f, 1.f, 1.f, 1.f)),
+	mEffectColor(new LLUIColor(LLColor4(0.f, 1.f, 1.f, 1.f))),
 
 	mHaveHomePosition(FALSE),
 	mHomeRegionHandle( 0 ),
@@ -251,7 +258,7 @@ void LLAgent::init()
 
 	setFlying( gSavedSettings.getBOOL("FlyingAtExit") );
 
-	mEffectColor = LLUIColorTable::instance().getColor("EffectColor");
+	*mEffectColor = LLUIColorTable::instance().getColor("EffectColor");
 
 	gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2));
 	gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2));
@@ -275,9 +282,16 @@ LLAgent::~LLAgent()
 	cleanup();
 
 	delete mMouselookModeInSignal;
+	mMouselookModeInSignal = NULL;
 	delete mMouselookModeOutSignal;
+	mMouselookModeOutSignal = NULL;
 
-	// *Note: this is where LLViewerCamera::getInstance() used to be deleted.
+	delete mAgentAccess;
+	mAgentAccess = NULL;
+	delete mEffectColor;
+	mEffectColor = NULL;
+	delete mTeleportSourceSLURL;
+	mTeleportSourceSLURL = NULL;
 }
 
 // Handle any actions that need to be performed when the main app gains focus
@@ -2142,32 +2156,32 @@ void LLAgent::onAnimStop(const LLUUID& id)
 
 bool LLAgent::isGodlike() const
 {
-	return mAgentAccess.isGodlike();
+	return mAgentAccess->isGodlike();
 }
 
 bool LLAgent::isGodlikeWithoutAdminMenuFakery() const
 {
-	return mAgentAccess.isGodlikeWithoutAdminMenuFakery();
+	return mAgentAccess->isGodlikeWithoutAdminMenuFakery();
 }
 
 U8 LLAgent::getGodLevel() const
 {
-	return mAgentAccess.getGodLevel();
+	return mAgentAccess->getGodLevel();
 }
 
 bool LLAgent::wantsPGOnly() const
 {
-	return mAgentAccess.wantsPGOnly();
+	return mAgentAccess->wantsPGOnly();
 }
 
 bool LLAgent::canAccessMature() const
 {
-	return mAgentAccess.canAccessMature();
+	return mAgentAccess->canAccessMature();
 }
 
 bool LLAgent::canAccessAdult() const
 {
-	return mAgentAccess.canAccessAdult();
+	return mAgentAccess->canAccessAdult();
 }
 
 bool LLAgent::canAccessMaturityInRegion( U64 region_handle ) const
@@ -2202,37 +2216,37 @@ bool LLAgent::canAccessMaturityAtGlobal( LLVector3d pos_global ) const
 
 bool LLAgent::prefersPG() const
 {
-	return mAgentAccess.prefersPG();
+	return mAgentAccess->prefersPG();
 }
 
 bool LLAgent::prefersMature() const
 {
-	return mAgentAccess.prefersMature();
+	return mAgentAccess->prefersMature();
 }
 	
 bool LLAgent::prefersAdult() const
 {
-	return mAgentAccess.prefersAdult();
+	return mAgentAccess->prefersAdult();
 }
 
 bool LLAgent::isTeen() const
 {
-	return mAgentAccess.isTeen();
+	return mAgentAccess->isTeen();
 }
 
 bool LLAgent::isMature() const
 {
-	return mAgentAccess.isMature();
+	return mAgentAccess->isMature();
 }
 
 bool LLAgent::isAdult() const
 {
-	return mAgentAccess.isAdult();
+	return mAgentAccess->isAdult();
 }
 
 void LLAgent::setTeen(bool teen)
 {
-	mAgentAccess.setTeen(teen);
+	mAgentAccess->setTeen(teen);
 }
 
 //static 
@@ -2277,37 +2291,37 @@ bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity)
 
 BOOL LLAgent::getAdminOverride() const	
 { 
-	return mAgentAccess.getAdminOverride(); 
+	return mAgentAccess->getAdminOverride(); 
 }
 
 void LLAgent::setMaturity(char text)
 {
-	mAgentAccess.setMaturity(text);
+	mAgentAccess->setMaturity(text);
 }
 
 void LLAgent::setAdminOverride(BOOL b)	
 { 
-	mAgentAccess.setAdminOverride(b);
+	mAgentAccess->setAdminOverride(b);
 }
 
 void LLAgent::setGodLevel(U8 god_level)	
 { 
-	mAgentAccess.setGodLevel(god_level);
+	mAgentAccess->setGodLevel(god_level);
 }
 
 void LLAgent::setAOTransition()
 {
-	mAgentAccess.setTransition();
+	mAgentAccess->setTransition();
 }
 
 const LLAgentAccess& LLAgent::getAgentAccess()
 {
-	return mAgentAccess;
+	return *mAgentAccess;
 }
 
 bool LLAgent::validateMaturity(const LLSD& newvalue)
 {
-	return mAgentAccess.canSetMaturity(newvalue.asInteger());
+	return mAgentAccess->canSetMaturity(newvalue.asInteger());
 }
 
 void LLAgent::handleMaturity(const LLSD& newvalue)
@@ -2639,12 +2653,12 @@ BOOL LLAgent::allowOperation(PermissionBit op,
 
 const LLColor4 &LLAgent::getEffectColor()
 {
-	return mEffectColor;
+	return *mEffectColor;
 }
 
 void LLAgent::setEffectColor(const LLColor4 &color)
 {
-	mEffectColor = color;
+	*mEffectColor = color;
 }
 
 void LLAgent::initOriginGlobal(const LLVector3d &origin_global)
@@ -3472,7 +3486,7 @@ void LLAgent::setTeleportState(ETeleportState state)
 
 		case TELEPORT_MOVING:
 		// We're outa here. Save "back" slurl.
-		LLAgentUI::buildSLURL(mTeleportSourceSLURL);
+		LLAgentUI::buildSLURL(*mTeleportSourceSLURL);
 			break;
 
 		case TELEPORT_ARRIVING:
@@ -3805,6 +3819,11 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename)
 	}//end for (all message sets in xml file)
 }
 
+const void LLAgent::getTeleportSourceSLURL(LLSLURL& slurl) const
+{
+	slurl = *mTeleportSourceSLURL;
+}
+
 void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility )
 {
 	gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo);
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 896408c0dd6a9cc0417ece00063cf1664dcd64a0..54c5649f97f3a35eea2f3487b35dc42f63a46d59 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -29,15 +29,11 @@
 
 #include "indra_constants.h"
 #include "llevent.h" 				// LLObservable base class
-#include "llagentaccess.h"
 #include "llagentconstants.h"
 #include "llagentdata.h" 			// gAgentID, gAgentSessionID
-#include "llcharacter.h" 			// LLAnimPauseRequest
+#include "llcharacter.h"
 #include "llcoordframe.h"			// for mFrameAgent
-#include "llpointer.h"
-#include "lluicolor.h"
 #include "llvoavatardefines.h"
-#include "llslurl.h"
 
 #include <boost/signals2.hpp>
 
@@ -56,6 +52,10 @@ class LLFriendObserver;
 class LLPickInfo;
 class LLViewerObject;
 class LLAgentDropGroupViewerNode;
+class LLAgentAccess;
+class LLSLURL;
+class LLPauseRequestHandle;
+class LLUIColor;
 
 //--------------------------------------------------------------------
 // Types
@@ -80,6 +80,8 @@ struct LLGroupData
 
 class LLAgentListener;
 
+class LLAgentImpl;
+
 //------------------------------------------------------------------------
 // LLAgent
 //------------------------------------------------------------------------
@@ -420,7 +422,7 @@ class LLAgent : public LLOldEvents::LLObservable
 	camera_signal_t* mMouselookModeInSignal;
 	camera_signal_t* mMouselookModeOutSignal;
 	BOOL            mCustomAnim; 		// Current animation is ANIM_AGENT_CUSTOMIZE ?
-	LLAnimPauseRequest mPauseRequest;
+	LLPointer<LLPauseRequestHandle> mPauseRequest;
 	BOOL			mViewsPushed; 		// Keep track of whether or not we have pushed views
 	
 /**                    Animation
@@ -515,13 +517,13 @@ class LLAgent : public LLOldEvents::LLObservable
 
 public:
 	static void 	parseTeleportMessages(const std::string& xml_filename);
-	const void getTeleportSourceSLURL(LLSLURL& slurl) const { slurl = mTeleportSourceSLURL; }
+	const void getTeleportSourceSLURL(LLSLURL& slurl) const;
 public:
 	// ! TODO ! Define ERROR and PROGRESS enums here instead of exposing the mappings.
 	static std::map<std::string, std::string> sTeleportErrorMessages;
 	static std::map<std::string, std::string> sTeleportProgressMessages;
 private:
-	LLSLURL	mTeleportSourceSLURL; 			// SLURL where last TP began
+	LLSLURL * mTeleportSourceSLURL; 			// SLURL where last TP began
 
 	//--------------------------------------------------------------------
 	// Teleport Actions
@@ -580,7 +582,7 @@ class LLAgent : public LLOldEvents::LLObservable
 	// ! BACKWARDS COMPATIBILITY ! This function can go away after the AO transition (see llstartup.cpp).
 	void 			setAOTransition();
 private:
-	LLAgentAccess 	mAgentAccess;
+	LLAgentAccess * mAgentAccess;
 	
 	//--------------------------------------------------------------------
 	// God
@@ -660,7 +662,7 @@ class LLAgent : public LLOldEvents::LLObservable
 	const LLColor4	&getEffectColor();
 	void			setEffectColor(const LLColor4 &color);
 private:
-	LLUIColor 		mEffectColor;
+	LLUIColor * mEffectColor;
 
 /**                    Rendering
  **                                                                            **
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 9de2941c4a5db2ffbafbfe98fb09300e941a2d6f..3a7e8dff64875d987716a0fb735e4ad5c86fa72e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -82,13 +82,14 @@
 #include "lltextutil.h"
 #include "lllogininstance.h"
 #include "llprogressview.h"
-
+#include "llvocache.h"
 #include "llweb.h"
 #include "llsecondlifeurls.h"
 #include "llupdaterservice.h"
 
 // Linden library includes
 #include "llavatarnamecache.h"
+#include "lldiriterator.h"
 #include "llimagej2c.h"
 #include "llmemory.h"
 #include "llprimitive.h"
@@ -132,7 +133,6 @@
 #include "lltoolmgr.h"
 #include "llassetstorage.h"
 #include "llpolymesh.h"
-#include "llcachename.h"
 #include "llaudioengine.h"
 #include "llstreamingaudio.h"
 #include "llviewermenu.h"
@@ -3432,7 +3432,9 @@ void LLAppViewer::migrateCacheDirectory()
 			S32 file_count = 0;
 			std::string file_name;
 			std::string mask = delimiter + "*.*";
-			while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name))
+
+			LLDirIterator iter(old_cache_dir, mask);
+			while (iter.next(file_name))
 			{
 				if (file_name == "." || file_name == "..") continue;
 				std::string source_path = old_cache_dir + delimiter + file_name;
@@ -3653,7 +3655,8 @@ bool LLAppViewer::initCache()
 		dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
 
 		std::string found_file;
-		if (gDirUtilp->getNextFileInDir(dir, mask, found_file))
+		LLDirIterator iter(dir, mask);
+		if (iter.next(found_file))
 		{
 			old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file;
 
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 523c2e3adf8113425f6926c9434100d52a8688ef..714e0e6163b8a939ac3f9603cafc80a17e0f5d8f 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -30,6 +30,7 @@
 
 #include "llcommandlineparser.h"
 
+#include "lldiriterator.h"
 #include "llmemtype.h"
 #include "llurldispatcher.h"		// SLURL from other app instance
 #include "llviewernetwork.h"
@@ -504,7 +505,9 @@ std::string LLAppViewerLinux::generateSerialNumber()
 
 	// trawl /dev/disk/by-uuid looking for a good-looking UUID to grab
 	std::string this_name;
-	while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name))
+
+	LLDirIterator iter(uuiddir, "*");
+	while (iter.next(this_name))
 	{
 		if (this_name.length() > best.length() ||
 		    (this_name.length() == best.length() &&
diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h
index 697a70876201dd7232485aff80414557bbdaa0b1..3fee46c2f67a39832979db6cd74116b4bddcfb19 100644
--- a/indra/newview/lleventnotifier.h
+++ b/indra/newview/lleventnotifier.h
@@ -31,6 +31,7 @@
 #include "v3dmath.h"
 
 class LLEventNotification;
+class LLMessageSystem;
 
 
 class LLEventNotifier
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 7be4ebc6908406a5904c2c1c4392ba18fcc69874..0d0c1f594dca2c7f1fbf450f5bf8186245ce3e10 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -38,6 +38,7 @@
 #include "message.h"
 
 #include "llagent.h"
+#include "llagentaccess.h"
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index a096fb64cdb2b39ebc890f16bc9bfcb98f58edb8..8a70fa24d87d2c319e07c7751478749642f8729b 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -43,11 +43,12 @@ class LLButton;
 class LLCheckBoxCtrl;
 class LLRadioGroup;
 class LLComboBox;
-class LLNameListCtrl;
-class LLSpinCtrl;
 class LLLineEditor;
+class LLMessageSystem;
+class LLNameListCtrl;
 class LLRadioGroup;
 class LLParcelSelectionObserver;
+class LLSpinCtrl;
 class LLTabContainer;
 class LLTextBox;
 class LLTextEditor;
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index add591895bceb2cab6cc7443a667973c5990cbe1..00dc7b1627500a411bb3421ec5d2bbf2b500dac5 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -53,6 +53,7 @@
 #include "llfloaterpostcard.h"
 #include "llcheckboxctrl.h"
 #include "llradiogroup.h"
+#include "llslurl.h"
 #include "lltoolfocus.h"
 #include "lltoolmgr.h"
 #include "llwebsharing.h"
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 0d8601410a1413677a645d24a3143315722f41d0..4c9c4cb154af0c9b515c6d9daac139888cd7750f 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -35,6 +35,7 @@
 #include "llfloateruipreview.h"			// Own header
 
 // Internal utility
+#include "lldiriterator.h"
 #include "lleventtimer.h"
 #include "llexternaleditor.h"
 #include "llrender.h"
@@ -481,9 +482,11 @@ BOOL LLFloaterUIPreview::postBuild()
 	std::string language_directory;
 	std::string xui_dir = get_xui_dir();	// directory containing localizations -- don't forget trailing delim
 	mLanguageSelection->removeall();																				// clear out anything temporarily in list from XML
+
+	LLDirIterator iter(xui_dir, "*");
 	while(found)																									// for every directory
 	{
-		if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory)))							// get next directory
+		if((found = iter.next(language_directory)))							// get next directory
 		{
 			std::string full_path = xui_dir + language_directory;
 			if(LLFile::isfile(full_path.c_str()))																	// if it's not a directory, skip it
@@ -635,42 +638,51 @@ void LLFloaterUIPreview::refreshList()
 	mFileList->clearRows();		// empty list
 	std::string name;
 	BOOL found = TRUE;
+
+	LLDirIterator floater_iter(getLocalizedDirectory(), "floater_*.xml");
 	while(found)				// for every floater file that matches the pattern
 	{
-		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name)))	// get next file matching pattern
+		if((found = floater_iter.next(name)))	// get next file matching pattern
 		{
 			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)
 		}
 	}
 	found = TRUE;
+
+	LLDirIterator inspect_iter(getLocalizedDirectory(), "inspect_*.xml");
 	while(found)				// for every inspector file that matches the pattern
 	{
-		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name)))	// get next file matching pattern
+		if((found = inspect_iter.next(name)))	// get next file matching pattern
 		{
 			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)
 		}
 	}
 	found = TRUE;
+
+	LLDirIterator menu_iter(getLocalizedDirectory(), "menu_*.xml");
 	while(found)				// for every menu file that matches the pattern
 	{
-		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name)))	// get next file matching pattern
+		if((found = menu_iter.next(name)))	// get next file matching pattern
 		{
 			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)
 		}
 	}
 	found = TRUE;
+
+	LLDirIterator panel_iter(getLocalizedDirectory(), "panel_*.xml");
 	while(found)				// for every panel file that matches the pattern
 	{
-		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name)))	// get next file matching pattern
+		if((found = panel_iter.next(name)))	// get next file matching pattern
 		{
 			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)
 		}
 	}
-
 	found = TRUE;
+
+	LLDirIterator sidepanel_iter(getLocalizedDirectory(), "sidepanel_*.xml");
 	while(found)				// for every sidepanel file that matches the pattern
 	{
-		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name)))	// get next file matching pattern
+		if((found = sidepanel_iter.next(name)))	// get next file matching pattern
 		{
 			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)
 		}
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 2006e094a822241648c2a5be69709065f58f4b45..fc941510ab2395382a72a7d6cb1a16eb8422507f 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -28,6 +28,7 @@
 
 #include "llview.h"
 #include "lldarray.h"  // *TODO: Eliminate, forward declare
+#include "lluiimage.h"
 
 class LLFontGL;
 class LLFolderView;
diff --git a/indra/newview/lllocationhistory.h b/indra/newview/lllocationhistory.h
index 188fbf1f9badbebb43d7e733f424709c949a42d3..9fef42c5df11996246dd882ba1c4718f11533cb5 100644
--- a/indra/newview/lllocationhistory.h
+++ b/indra/newview/lllocationhistory.h
@@ -33,6 +33,7 @@
 #include <string>
 #include <map>
 #include <boost/function.hpp>
+#include <boost/signals2.hpp>
 
 class LLSD;
 /**
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 2df683861a92582c65628e6436456d92ba5ed0ae..efc4e2383881d2fb5aa57828a7707b7d6d3b4d35 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -32,6 +32,7 @@
 #include "lltrans.h"
 #include "llviewercontrol.h"
 
+#include "lldiriterator.h"
 #include "llinstantmessage.h"
 #include "llsingleton.h" // for LLSingleton
 
@@ -602,7 +603,8 @@ std::string LLLogChat::oldLogFileName(std::string filename)
 	//LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
 	std::vector<std::string> allfiles;
 
-    while (gDirUtilp->getNextFileInDir(directory, pattern, scanResult))
+	LLDirIterator iter(directory, pattern);
+	while (iter.next(scanResult))
     {
 		//LL_INFOS("") << "Found   :" << scanResult << LL_ENDL;
         allfiles.push_back(scanResult);
diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h
index 026803584d8b663a457af66879d6b36f47ceea0f..2d23753d46edb1aba27085cb4f5d8c290c8fc322 100644
--- a/indra/newview/lloutputmonitorctrl.h
+++ b/indra/newview/lloutputmonitorctrl.h
@@ -31,6 +31,7 @@
 #include "llview.h"
 #include "llmutelist.h"
 #include "llspeakingindicatormanager.h"
+#include "lluiimage.h"
 
 class LLTextBox;
 class LLUICtrlFactory;
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 73c4722b828f15d512a36a3fc7b1251aa1cd7be6..d58a1cb66399f1e8b7c896082b139877784451f4 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -36,6 +36,7 @@
 #include "llimview.h"
 #include "llmenubutton.h"
 #include "llnotificationsutil.h"
+#include "llslurl.h"
 #include "lltexteditor.h"
 #include "lltexturectrl.h"
 #include "lltoggleablemenu.h"
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index ec340dc258dff5964524d41dfad2889e1588f6b7..1576ccccdf3e5249bed0b605e2988e17066dc220 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -44,6 +44,7 @@
 #include "llnotificationsutil.h"
 #include "llscrolllistitem.h"
 #include "llspinctrl.h"
+#include "llslurl.h"
 #include "lltextbox.h"
 #include "lltexteditor.h"
 #include "lltexturectrl.h"
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 3dbc637318a7eab48a77cc668a45ee554eaa7d88..fbe331c7ab925edef1c90a3faf5bd2e10cf21d76 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -42,6 +42,7 @@
 #include "llscrolllistctrl.h"
 #include "llscrolllistitem.h"
 #include "llscrolllistcell.h"
+#include "llslurl.h"
 #include "lltabcontainer.h"
 #include "lltextbox.h"
 #include "lltexteditor.h"
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 8e5beb33cef116dcd53e275a9a05a8a6ea966098..9f5c55bad124c673d14131a4cc262a23b198e822 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -34,6 +34,7 @@
 #include "llassetuploadresponders.h"
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
+#include "lldatapacker.h"
 #include "lldelayedgestureerror.h"
 #include "llfloaterreg.h"
 #include "llgesturemgr.h"
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index c8c6858b81d2f829a4a996fa8b1f4b19a3174350..fbd2f7ca83184c47bd1fadac32b3dc3b2dc7244f 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -39,6 +39,7 @@
 #include "llinventoryobserver.h"
 #include "lllineeditor.h"
 #include "llradiogroup.h"
+#include "llslurl.h"
 #include "llviewercontrol.h"
 #include "llviewerinventory.h"
 #include "llviewerobjectlist.h"
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index ba243f258a62d0fecc536089cfe45dd335e38a8c..671a3346008e090751b1dd07b3341939a5b31a4d 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -35,7 +35,6 @@
 #include "llagentwearables.h"
 #include "llappearancemgr.h"
 #include "lldictionary.h"
-//#include "llfirstuse.h"
 #include "llfloaterreg.h"
 #include "llfloatertools.h"
 #include "llgesturemgr.h"
diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp
index e7a0d17c3a42ed3e1e385437e51bd4595bfa9db8..e06fe7bda02b6466e473f2dbf651870d56fba80a 100644
--- a/indra/newview/llviewerchat.cpp
+++ b/indra/newview/llviewerchat.cpp
@@ -29,6 +29,8 @@
 
 // newview includes
 #include "llagent.h" 	// gAgent		
+#include "llslurl.h"
+#include "lluicolor.h"
 #include "lluicolortable.h"
 #include "llviewercontrol.h" // gSavedSettings
 #include "llviewerregion.h"
diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h
index 925244e89bcc28295799df7f18b81ed064a1234c..ca73212ed1262f60737f545be5d333b5da02754d 100644
--- a/indra/newview/llviewerkeyboard.h
+++ b/indra/newview/llviewerkeyboard.h
@@ -28,6 +28,7 @@
 #define LL_LLVIEWERKEYBOARD_H
 
 #include "llkeyboard.h" // For EKeystate
+#include "llinitparam.h"
 
 const S32 MAX_NAMED_FUNCTIONS = 100;
 const S32 MAX_KEY_BINDINGS = 128; // was 60
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 62ae7ac6e2e0f5f1a338ca5f5c0c1d2b9458a8f5..2b9f32f6f547259c0a0aefd9df406f7cb5044dd5 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1,3742 +1,3744 @@
-/**
- * @file llviewermedia.cpp
- * @brief Client interface to the media engine
- *
- * $LicenseInfo:firstyear=2007&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 "llagent.h"
-#include "llagentcamera.h"
-#include "llviewermedia.h"
-#include "llviewermediafocus.h"
-#include "llmimetypes.h"
-#include "llmediaentry.h"
-#include "llversioninfo.h"
-#include "llviewercontrol.h"
-#include "llviewertexture.h"
-#include "llviewerparcelmedia.h"
-#include "llviewerparcelmgr.h"
-#include "llviewertexturelist.h"
-#include "llvovolume.h"
-#include "llpluginclassmedia.h"
-#include "llplugincookiestore.h"
-#include "llviewerwindow.h"
-#include "llfocusmgr.h"
-#include "llcallbacklist.h"
-#include "llparcel.h"
-#include "llaudioengine.h"  // for gAudiop
-#include "llurldispatcher.h"
-#include "llvoavatar.h"
-#include "llvoavatarself.h"
-#include "llviewerregion.h"
-#include "llwebsharing.h"	// For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
-#include "llfilepicker.h"
-#include "llnotifications.h"
-#include "lldir.h"
-#include "llevent.h"		// LLSimpleListener
-#include "llnotificationsutil.h"
-#include "lluuid.h"
-#include "llkeyboard.h"
-#include "llmutelist.h"
-#include "llpanelprofile.h"
-#include "llappviewer.h"
-#include "lllogininstance.h" 
-//#include "llfirstuse.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.
-
-#include <boost/bind.hpp>	// for SkinFolder listener
-#include <boost/signals2.hpp>
-
-/*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable";
-/*static*/ const char* LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING = "MediaShowOnOthers";
-/*static*/ const char* LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING = "MediaShowWithinParcel";
-/*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel";
-
-
-// Move this to its own file.
-
-LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter()
-{
-	observerListType::iterator iter = mObservers.begin();
-
-	while( iter != mObservers.end() )
-	{
-		LLViewerMediaObserver *self = *iter;
-		iter++;
-		remObserver(self);
-	}
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer )
-{
-	if ( ! observer )
-		return false;
-
-	if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() )
-		return false;
-
-	mObservers.push_back( observer );
-	observer->mEmitters.push_back( this );
-
-	return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer )
-{
-	if ( ! observer )
-		return false;
-
-	mObservers.remove( observer );
-	observer->mEmitters.remove(this);
-
-	return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLViewerMediaObserver::EMediaEvent event )
-{
-	// Broadcast the event to any observers.
-	observerListType::iterator iter = mObservers.begin();
-	while( iter != mObservers.end() )
-	{
-		LLViewerMediaObserver *self = *iter;
-		++iter;
-		self->handleMediaEvent( media, event );
-	}
-}
-
-// Move this to its own file.
-LLViewerMediaObserver::~LLViewerMediaObserver()
-{
-	std::list<LLViewerMediaEventEmitter *>::iterator iter = mEmitters.begin();
-
-	while( iter != mEmitters.end() )
-	{
-		LLViewerMediaEventEmitter *self = *iter;
-		iter++;
-		self->remObserver( this );
-	}
-}
-
-
-// Move this to its own file.
-// helper class that tries to download a URL from a web site and calls a method
-// on the Panel Land Media and to discover the MIME type
-class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
-{
-LOG_CLASS(LLMimeDiscoveryResponder);
-public:
-	LLMimeDiscoveryResponder( viewer_media_t media_impl)
-		: mMediaImpl(media_impl),
-		  mInitialized(false)
-	{
-		if(mMediaImpl->mMimeTypeProbe != NULL)
-		{
-			llerrs << "impl already has an outstanding responder" << llendl;
-		}
-		
-		mMediaImpl->mMimeTypeProbe = this;
-	}
-
-	~LLMimeDiscoveryResponder()
-	{
-		disconnectOwner();
-	}
-
-	virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		std::string media_type = content["content-type"].asString();
-		std::string::size_type idx1 = media_type.find_first_of(";");
-		std::string mime_type = media_type.substr(0, idx1);
-
-		lldebugs << "status is " << status << ", media type \"" << media_type << "\"" << llendl;
-		
-		// 2xx status codes indicate success.
-		// Most 4xx status codes are successful enough for our purposes.
-		// 499 is the error code for host not found, timeout, etc.
-		// 500 means "Internal Server error" but we decided it's okay to 
-		//     accept this and go past it in the MIME type probe
-		// 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com
-		// 499 is a code specifc to join.secondlife.com (????) apparently safe to ignore
-//		if(	((status >= 200) && (status < 300))	||
-//			((status >= 400) && (status < 499))	|| 
-//			(status == 500) ||
-//			(status == 302) ||
-//			(status == 499) 
-//			)
-		// We now no longer check the error code returned from the probe.
-		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
-		if(1)
-		{
-			// The probe was successful.
-			if(mime_type.empty())
-			{
-				// Some sites don't return any content-type header at all.
-				// Treat an empty mime type as text/html.
-				mime_type = "text/html";
-			}
-			
-			completeAny(status, mime_type);
-		}
-		else
-		{
-			llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
-		
-			if(mMediaImpl)
-			{
-				mMediaImpl->mMediaSourceFailed = true;
-			}
-		}
-
-	}
-
-	void completeAny(U32 status, const std::string& mime_type)
-	{
-		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
-		// Make a local copy so we can call loadURI() afterwards.
-		LLViewerMediaImpl *impl = mMediaImpl;
-		
-		if(impl && !mInitialized && ! mime_type.empty())
-		{
-			if(impl->initializeMedia(mime_type))
-			{
-				mInitialized = true;
-				impl->loadURI();
-				disconnectOwner();
-			}
-		}
-	}
-	
-	void cancelRequest()
-	{
-		disconnectOwner();
-	}
-	
-private:
-	void disconnectOwner()
-	{
-		if(mMediaImpl)
-		{
-			if(mMediaImpl->mMimeTypeProbe != this)
-			{
-				llerrs << "internal error: mMediaImpl->mMimeTypeProbe != this" << llendl;
-			}
-
-			mMediaImpl->mMimeTypeProbe = NULL;
-		}
-		mMediaImpl = NULL;
-	}
-	
-	
-public:
-		LLViewerMediaImpl *mMediaImpl;
-		bool mInitialized;
-};
-
-class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
-{
-LOG_CLASS(LLViewerMediaOpenIDResponder);
-public:
-	LLViewerMediaOpenIDResponder( )
-	{
-	}
-
-	~LLViewerMediaOpenIDResponder()
-	{
-	}
-
-	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
-		LL_DEBUGS("MediaAuth") << content << LL_ENDL;
-		std::string cookie = content["set-cookie"].asString();
-		
-		LLViewerMedia::openIDCookieResponse(cookie);
-	}
-
-	/* virtual */ void completedRaw(
-		U32 status,
-		const std::string& reason,
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// This is just here to disable the default behavior (attempting to parse the response as llsd).
-		// We don't care about the content of the response, only the set-cookie header.
-	}
-
-};
-
-class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder
-{
-LOG_CLASS(LLViewerMediaWebProfileResponder);
-public:
-	LLViewerMediaWebProfileResponder(std::string host)
-	{
-		mHost = host;
-	}
-
-	~LLViewerMediaWebProfileResponder()
-	{
-	}
-
-	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
-		LL_WARNS("MediaAuth") << content << LL_ENDL;
-
-		std::string cookie = content["set-cookie"].asString();
-
-		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
-	}
-
-	 void completedRaw(
-		U32 status,
-		const std::string& reason,
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// This is just here to disable the default behavior (attempting to parse the response as llsd).
-		// We don't care about the content of the response, only the set-cookie header.
-	}
-
-	std::string mHost;
-};
-
-
-LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
-LLURL LLViewerMedia::sOpenIDURL;
-std::string LLViewerMedia::sOpenIDCookie;
-LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL;
-static LLViewerMedia::impl_list sViewerMediaImplList;
-static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
-static LLTimer sMediaCreateTimer;
-static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
-static F32 sGlobalVolume = 1.0f;
-static F64 sLowestLoadableImplInterest = 0.0f;
-static bool sAnyMediaShowing = false;
-static boost::signals2::connection sTeleportFinishConnection;
-static std::string sUpdatedCookies;
-static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt";
-
-//////////////////////////////////////////////////////////////////////////////////////////
-static void add_media_impl(LLViewerMediaImpl* media)
-{
-	sViewerMediaImplList.push_back(media);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-static void remove_media_impl(LLViewerMediaImpl* media)
-{
-	LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
-	LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
-	
-	for(; iter != end; iter++)
-	{
-		if(media == *iter)
-		{
-			sViewerMediaImplList.erase(iter);
-			return;
-		}
-	}
-}
-
-class LLViewerMediaMuteListObserver : public LLMuteListObserver
-{
-	/* virtual */ void onChange()  { LLViewerMedia::muteListChanged();}
-};
-
-static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
-static bool sViewerMediaMuteListObserverInitialized = false;
-static bool sInWorldMediaDisabled = false;
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// LLViewerMedia
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-viewer_media_t LLViewerMedia::newMediaImpl(
-											 const LLUUID& texture_id,
-											 S32 media_width, 
-											 S32 media_height, 
-											 U8 media_auto_scale,
-											 U8 media_loop)
-{
-	LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id);
-	if(media_impl == NULL || texture_id.isNull())
-	{
-		// Create the media impl
-		media_impl = new LLViewerMediaImpl(texture_id, media_width, media_height, media_auto_scale, media_loop);
-	}
-	else
-	{
-		media_impl->unload();
-		media_impl->setTextureID(texture_id);
-		media_impl->mMediaWidth = media_width;
-		media_impl->mMediaHeight = media_height;
-		media_impl->mMediaAutoScale = media_auto_scale;
-		media_impl->mMediaLoop = media_loop;
-	}
-
-	return media_impl;
-}
-
-viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self)
-{	
-	// Try to find media with the same media ID
-	viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
-	
-	lldebugs << "called, current URL is \"" << media_entry->getCurrentURL() 
-			<< "\", previous URL is \"" << previous_url 
-			<< "\", update_from_self is " << (update_from_self?"true":"false")
-			<< llendl;
-			
-	bool was_loaded = false;
-	bool needs_navigate = false;
-	
-	if(media_impl)
-	{	
-		was_loaded = media_impl->hasMedia();
-		
-		media_impl->setHomeURL(media_entry->getHomeURL());
-		
-		media_impl->mMediaAutoScale = media_entry->getAutoScale();
-		media_impl->mMediaLoop = media_entry->getAutoLoop();
-		media_impl->mMediaWidth = media_entry->getWidthPixels();
-		media_impl->mMediaHeight = media_entry->getHeightPixels();
-		media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
-		media_impl->mMediaEntryURL = media_entry->getCurrentURL();
-		if (media_impl->mMediaSource)
-		{
-			media_impl->mMediaSource->setAutoScale(media_impl->mMediaAutoScale);
-			media_impl->mMediaSource->setLoop(media_impl->mMediaLoop);
-			media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
-		}
-		
-		bool url_changed = (media_impl->mMediaEntryURL != previous_url);
-		if(media_impl->mMediaEntryURL.empty())
-		{
-			if(url_changed)
-			{
-				// The current media URL is now empty.  Unload the media source.
-				media_impl->unload();
-			
-				lldebugs << "Unloading media instance (new current URL is empty)." << llendl;
-			}
-		}
-		else
-		{
-			// The current media URL is not empty.
-			// If (the media was already loaded OR the media was set to autoplay) AND this update didn't come from this agent,
-			// do a navigate.
-			bool auto_play = media_impl->isAutoPlayable();			
-			if((was_loaded || auto_play) && !update_from_self)
-			{
-				needs_navigate = url_changed;
-			}
-			
-			lldebugs << "was_loaded is " << (was_loaded?"true":"false") 
-					<< ", auto_play is " << (auto_play?"true":"false") 
-					<< ", needs_navigate is " << (needs_navigate?"true":"false") << llendl;
-		}
-	}
-	else
-	{
-		media_impl = newMediaImpl(
-			media_entry->getMediaID(), 
-			media_entry->getWidthPixels(),
-			media_entry->getHeightPixels(), 
-			media_entry->getAutoScale(), 
-			media_entry->getAutoLoop());
-		
-		media_impl->setHomeURL(media_entry->getHomeURL());
-		media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
-		media_impl->mMediaEntryURL = media_entry->getCurrentURL();
-		if(media_impl->isAutoPlayable())
-		{
-			needs_navigate = true;
-		}
-	}
-	
-	if(media_impl)
-	{
-		if(needs_navigate)
-		{
-			media_impl->navigateTo(media_impl->mMediaEntryURL, "", true, true);
-			lldebugs << "navigating to URL " << media_impl->mMediaEntryURL << llendl;
-		}
-		else if(!media_impl->mMediaURL.empty() && (media_impl->mMediaURL != media_impl->mMediaEntryURL))
-		{
-			// If we already have a non-empty media URL set and we aren't doing a navigate, update the media URL to match the media entry.
-			media_impl->mMediaURL = media_impl->mMediaEntryURL;
-
-			// If this causes a navigate at some point (such as after a reload), it should be considered server-driven so it isn't broadcast.
-			media_impl->mNavigateServerRequest = true;
-
-			lldebugs << "updating URL in the media impl to " << media_impl->mMediaEntryURL << llendl;
-		}
-	}
-	
-	return media_impl;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)
-{
-	LLViewerMediaImpl* result = NULL;
-	
-	// Look up the texture ID in the texture id->impl map.
-	impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id);
-	if(iter != sViewerMediaTextureIDMap.end())
-	{
-		result = iter->second;
-	}
-
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-std::string LLViewerMedia::getCurrentUserAgent()
-{
-	// Don't use user-visible string to avoid 
-	// punctuation and strange characters.
-	std::string skin_name = gSavedSettings.getString("SkinCurrent");
-
-	// Just in case we need to check browser differences in A/B test
-	// builds.
-	std::string channel = LLVersionInfo::getChannel();
-
-	// append our magic version number string to the browser user agent id
-	// See the HTTP 1.0 and 1.1 specifications for allowed formats:
-	// http://www.ietf.org/rfc/rfc1945.txt section 10.15
-	// http://www.ietf.org/rfc/rfc2068.txt section 3.8
-	// This was also helpful:
-	// http://www.mozilla.org/build/revised-user-agent-strings.html
-	std::ostringstream codec;
-	codec << "SecondLife/";
-	codec << LLVersionInfo::getVersion();
-	codec << " (" << channel << "; " << skin_name << " skin)";
-	llinfos << codec.str() << llendl;
-	
-	return codec.str();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::updateBrowserUserAgent()
-{
-	std::string user_agent = getCurrentUserAgent();
-	
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-
-	for(; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser())
-		{
-			pimpl->mMediaSource->setBrowserUserAgent(user_agent);
-		}
-	}
-
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::handleSkinCurrentChanged(const LLSD& /*newvalue*/)
-{
-	// gSavedSettings is already updated when this function is called.
-	updateBrowserUserAgent();
-	return true;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id)
-{
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-
-	for(; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if(pimpl->getMediaTextureID() == texture_id)
-		{
-			return true;
-		}
-	}
-	return false;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::setVolume(F32 volume)
-{
-	if(volume != sGlobalVolume)
-	{
-		sGlobalVolume = volume;
-		impl_list::iterator iter = sViewerMediaImplList.begin();
-		impl_list::iterator end = sViewerMediaImplList.end();
-
-		for(; iter != end; iter++)
-		{
-			LLViewerMediaImpl* pimpl = *iter;
-			pimpl->updateVolume();
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-F32 LLViewerMedia::getVolume()
-{
-	return sGlobalVolume;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::muteListChanged()
-{
-	// When the mute list changes, we need to check mute status on all impls.
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-
-	for(; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		pimpl->mNeedsMuteCheck = true;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
-{
-	sInWorldMediaDisabled = disabled;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::getInWorldMediaDisabled()
-{
-	return sInWorldMediaDisabled;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)
-{
-	bool result = false;
-	
-	if (NULL == object)
-	{
-		result = false;
-	}
-	// Focused?  Then it is interesting!
-	else if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == object->getID())
-	{
-		result = true;
-	}
-	// Selected?  Then it is interesting!
-	// XXX Sadly, 'contains()' doesn't take a const :(
-	else if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(object)))
-	{
-		result = true;
-	}
-	else 
-	{
-		lldebugs << "object interest = " << object_interest << ", lowest loadable = " << sLowestLoadableImplInterest << llendl;
-		if(object_interest >= sLowestLoadableImplInterest)
-			result = true;
-	}
-	
-	return result;
-}
-
-LLViewerMedia::impl_list &LLViewerMedia::getPriorityList()
-{
-	return sViewerMediaImplList;
-}
-
-// This is the predicate function used to sort sViewerMediaImplList by priority.
-bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
-{
-	if(i1->isForcedUnloaded() && !i2->isForcedUnloaded())
-	{
-		// Muted or failed items always go to the end of the list, period.
-		return false;
-	}
-	else if(i2->isForcedUnloaded() && !i1->isForcedUnloaded())
-	{
-		// Muted or failed items always go to the end of the list, period.
-		return true;
-	}
-	else if(i1->hasFocus())
-	{
-		// The item with user focus always comes to the front of the list, period.
-		return true;
-	}
-	else if(i2->hasFocus())
-	{
-		// The item with user focus always comes to the front of the list, period.
-		return false;
-	}
-	else if(i1->isParcelMedia())
-	{
-		// The parcel media impl sorts above all other inworld media, unless one has focus.
-		return true;
-	}
-	else if(i2->isParcelMedia())
-	{
-		// The parcel media impl sorts above all other inworld media, unless one has focus.
-		return false;
-	}
-	else if(i1->getUsedInUI() && !i2->getUsedInUI())
-	{
-		// i1 is a UI element, i2 is not.  This makes i1 "less than" i2, so it sorts earlier in our list.
-		return true;
-	}
-	else if(i2->getUsedInUI() && !i1->getUsedInUI())
-	{
-		// i2 is a UI element, i1 is not.  This makes i2 "less than" i1, so it sorts earlier in our list.
-		return false;
-	}
-	else if(i1->isPlayable() && !i2->isPlayable())
-	{
-		// Playable items sort above ones that wouldn't play even if they got high enough priority
-		return true;
-	}
-	else if(!i1->isPlayable() && i2->isPlayable())
-	{
-		// Playable items sort above ones that wouldn't play even if they got high enough priority
-		return false;
-	}
-	else if(i1->getInterest() == i2->getInterest())
-	{
-		// Generally this will mean both objects have zero interest.  In this case, sort on distance.
-		return (i1->getProximityDistance() < i2->getProximityDistance());
-	}
-	else
-	{
-		// The object with the larger interest value should be earlier in the list, so we reverse the sense of the comparison here.
-		return (i1->getInterest() > i2->getInterest());
-	}
-}
-
-static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
-{
-	if(i1->getProximityDistance() < i2->getProximityDistance())
-	{
-		return true;
-	}
-	else if(i1->getProximityDistance() > i2->getProximityDistance())
-	{
-		return false;
-	}
-	else
-	{
-		// Both objects have the same distance.  This most likely means they're two faces of the same object.
-		// They may also be faces on different objects with exactly the same distance (like HUD objects).
-		// We don't actually care what the sort order is for this case, as long as it's stable and doesn't change when you enable/disable media.
-		// Comparing the impl pointers gives a completely arbitrary ordering, but it will be stable.
-		return (i1 < i2);
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE("Update Media");
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::updateMedia(void *dummy_arg)
-{
-	LLFastTimer t1(FTM_MEDIA_UPDATE);
-	
-	// Enable/disable the plugin read thread
-	LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
-	
-	// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
-	createSpareBrowserMediaSource();
-	
-	sAnyMediaShowing = false;
-	sUpdatedCookies = getCookieStore()->getChangedCookies();
-	if(!sUpdatedCookies.empty())
-	{
-		lldebugs << "updated cookies will be sent to all loaded plugins: " << llendl;
-		lldebugs << sUpdatedCookies << llendl;
-	}
-	
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-
-	for(; iter != end;)
-	{
-		LLViewerMediaImpl* pimpl = *iter++;
-		pimpl->update();
-		pimpl->calculateInterest();
-	}
-	
-	// Let the spare media source actually launch
-	if(sSpareBrowserMediaSource)
-	{
-		sSpareBrowserMediaSource->idle();
-	}
-		
-	// Sort the static instance list using our interest criteria
-	sViewerMediaImplList.sort(priorityComparitor);
-
-	// Go through the list again and adjust according to priority.
-	iter = sViewerMediaImplList.begin();
-	end = sViewerMediaImplList.end();
-	
-	F64 total_cpu = 0.0f;
-	int impl_count_total = 0;
-	int impl_count_interest_low = 0;
-	int impl_count_interest_normal = 0;
-	
-	std::vector<LLViewerMediaImpl*> proximity_order;
-	
-	bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia");
-	bool inworld_audio_enabled = gSavedSettings.getBOOL("AudioStreamingMusic");
-	U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal");
-	U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal");
-	U32 max_low = gSavedSettings.getU32("PluginInstancesLow");
-	F32 max_cpu = gSavedSettings.getF32("PluginInstancesCPULimit");
-	// Setting max_cpu to 0.0 disables CPU usage checking.
-	bool check_cpu_usage = (max_cpu != 0.0f);
-	
-	LLViewerMediaImpl* lowest_interest_loadable = NULL;
-	
-	// Notes on tweakable params:
-	// max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded.
-	// If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow.
-	
-	for(; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		
-		LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
-
-		if(pimpl->isForcedUnloaded() || (impl_count_total >= (int)max_instances))
-		{
-			// Never load muted or failed impls.
-			// Hard limit on the number of instances that will be loaded at one time
-			new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
-		}
-		else if(!pimpl->getVisible())
-		{
-			new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
-		}
-		else if(pimpl->hasFocus())
-		{
-			new_priority = LLPluginClassMedia::PRIORITY_HIGH;
-			impl_count_interest_normal++;	// count this against the count of "normal" instances for priority purposes
-		}
-		else if(pimpl->getUsedInUI())
-		{
-			new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
-			impl_count_interest_normal++;
-		}
-		else if(pimpl->isParcelMedia())
-		{
-			new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
-			impl_count_interest_normal++;
-		}
-		else
-		{
-			// Look at interest and CPU usage for instances that aren't in any of the above states.
-			
-			// Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture,
-			// turn it down to low instead of normal.  This may downsample for plugins that support it.
-			bool media_is_small = false;
-			F64 approximate_interest = pimpl->getApproximateTextureInterest();
-			if(approximate_interest == 0.0f)
-			{
-				// this media has no current size, which probably means it's not loaded.
-				media_is_small = true;
-			}
-			else if(pimpl->getInterest() < (approximate_interest / 4))
-			{
-				media_is_small = true;
-			}
-			
-			if(pimpl->getInterest() == 0.0f)
-			{
-				// This media is completely invisible, due to being outside the view frustrum or out of range.
-				new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
-			}
-			else if(check_cpu_usage && (total_cpu > max_cpu))
-			{
-				// Higher priority plugins have already used up the CPU budget.  Set remaining ones to slideshow priority.
-				new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
-			}
-			else if((impl_count_interest_normal < (int)max_normal) && !media_is_small)
-			{
-				// Up to max_normal inworld get normal priority
-				new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
-				impl_count_interest_normal++;
-			}
-			else if (impl_count_interest_low + impl_count_interest_normal < (int)max_low + (int)max_normal)
-			{
-				// The next max_low inworld get turned down
-				new_priority = LLPluginClassMedia::PRIORITY_LOW;
-				impl_count_interest_low++;
-				
-				// Set the low priority size for downsampling to approximately the size the texture is displayed at.
-				{
-					F32 approximate_interest_dimension = fsqrtf(pimpl->getInterest());
-					
-					pimpl->setLowPrioritySizeLimit(llround(approximate_interest_dimension));
-				}
-			}
-			else
-			{
-				// Any additional impls (up to max_instances) get very infrequent time
-				new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
-			}
-		}
-		
-		if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED))
-		{
-			// This is a loadable inworld impl -- the last one in the list in this class defines the lowest loadable interest.
-			lowest_interest_loadable = pimpl;
-			
-			impl_count_total++;
-		}
-
-		// Overrides if the window is minimized or we lost focus (taking care
-		// not to accidentally "raise" the priority either)
-		if (!gViewerWindow->getActive() /* viewer window minimized? */ 
-			&& new_priority > LLPluginClassMedia::PRIORITY_HIDDEN)
-		{
-			new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
-		}
-		else if (!gFocusMgr.getAppHasFocus() /* viewer window lost focus? */
-				 && new_priority > LLPluginClassMedia::PRIORITY_LOW)
-		{
-			new_priority = LLPluginClassMedia::PRIORITY_LOW;
-		}
-		
-		if(!inworld_media_enabled)
-		{
-			// If inworld media is locked out, force all inworld media to stay unloaded.
-			if(!pimpl->getUsedInUI())
-			{
-				new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
-			}
-		}
-		// update the audio stream here as well
-		if( !inworld_audio_enabled)
-		{
-			if(LLViewerMedia::isParcelAudioPlaying() && gAudiop && LLViewerMedia::hasParcelAudio())
-			{
-				gAudiop->stopInternetStream();
-			}
-		}
-		pimpl->setPriority(new_priority);
-		
-		if(pimpl->getUsedInUI())
-		{
-			// Any impls used in the UI should not be in the proximity list.
-			pimpl->mProximity = -1;
-		}
-		else
-		{
-			proximity_order.push_back(pimpl);
-		}
-
-		total_cpu += pimpl->getCPUUsage();
-		
-		if (!pimpl->getUsedInUI() && pimpl->hasMedia())
-		{
-			sAnyMediaShowing = true;
-		}
-
-	}
-
-	// Re-calculate this every time.
-	sLowestLoadableImplInterest	= 0.0f;
-
-	// Only do this calculation if we've hit the impl count limit -- up until that point we always need to load media data.
-	if(lowest_interest_loadable && (impl_count_total >= (int)max_instances))
-	{
-		// Get the interest value of this impl's object for use by isInterestingEnough
-		LLVOVolume *object = lowest_interest_loadable->getSomeObject();
-		if(object)
-		{
-			// NOTE: Don't use getMediaInterest() here.  We want the pixel area, not the total media interest,
-			// 		so that we match up with the calculation done in LLMediaDataClient.
-			sLowestLoadableImplInterest = object->getPixelArea();
-		}
-	}
-	
-	if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug"))
-	{
-		// Give impls the same ordering as the priority list
-		// they're already in the right order for this.
-	}
-	else
-	{
-		// Use a distance-based sort for proximity values.  
-		std::stable_sort(proximity_order.begin(), proximity_order.end(), proximity_comparitor);
-	}
-
-	// Transfer the proximity order to the proximity fields in the objects.
-	for(int i = 0; i < (int)proximity_order.size(); i++)
-	{
-		proximity_order[i]->mProximity = i;
-	}
-	
-	LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
-
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::isAnyMediaShowing()
-{
-	return sAnyMediaShowing;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::setAllMediaEnabled(bool val)
-{
-	// Set "tentative" autoplay first.  We need to do this here or else
-	// re-enabling won't start up the media below.
-	gSavedSettings.setBOOL("MediaTentativeAutoPlay", val);
-	
-	// Then 
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-	
-	for(; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if (!pimpl->getUsedInUI())
-		{
-			pimpl->setDisabled(!val);
-		}
-	}
-	
-	// Also do Parcel Media and Parcel Audio
-	if (val)
-	{
-		if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
-		{	
-			LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
-		}
-		
-		if (gSavedSettings.getBOOL("AudioStreamingMusic") &&
-			!LLViewerMedia::isParcelAudioPlaying() &&
-			gAudiop && 
-			LLViewerMedia::hasParcelAudio())
-		{
-			gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
-		}
-	}
-	else {
-		// This actually unloads the impl, as opposed to "stop"ping the media
-		LLViewerParcelMedia::stop();
-		if (gAudiop) gAudiop->stopInternetStream();
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::isParcelMediaPlaying()
-{
-	return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia());
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::isParcelAudioPlaying()
-{
-	return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());
-}
-
-void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response)
-{
-	LLViewerMediaImpl *impl = LLViewerMedia::getMediaImplFromTextureID(notification["payload"]["media_id"]);
-	if(impl)
-	{
-		LLPluginClassMedia* media = impl->getMediaPlugin();
-		if(media)
-		{
-			if (response["ok"])
-			{
-				media->sendAuthResponse(true, response["username"], response["password"]);
-			}
-			else
-			{
-				media->sendAuthResponse(false, "", "");
-			}
-		}
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::clearAllCookies()
-{
-	// Clear all cookies for all plugins
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-	for (; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if(pimpl->mMediaSource)
-		{
-			pimpl->mMediaSource->clear_cookies();
-		}
-	}
-	
-	// Clear all cookies from the cookie store
-	getCookieStore()->setAllCookies("");
-
-	// FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly.
-	// It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded.
-	// Until such time as we can centralize cookie storage, the following hack should cover these cases:
-	
-	// HACK: Look for cookie files in all possible places and delete them.
-	// NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file)
-	
-	// Places that cookie files can be:
-	// <getOSUserAppDir>/browser_profile/cookies
-	// <getOSUserAppDir>/first_last/browser_profile/cookies  (note that there may be any number of these!)
-	// <getOSUserAppDir>/first_last/plugin_cookies.txt  (note that there may be any number of these!)
-	
-	std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter();
-	std::string target;
-	std::string filename;
-	
-	lldebugs << "base dir = " << base_dir << llendl;
-
-	// The non-logged-in version is easy
-	target = base_dir;
-	target += "browser_profile";
-	target += gDirUtilp->getDirDelimiter();
-	target += "cookies";
-	lldebugs << "target = " << target << llendl;
-	if(LLFile::isfile(target))
-	{
-		LLFile::remove(target);
-	}
-	
-	// the hard part: iterate over all user directories and delete the cookie file from each one
-	while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename))
-	{
-		target = base_dir;
-		target += filename;
-		target += gDirUtilp->getDirDelimiter();
-		target += "browser_profile";
-		target += gDirUtilp->getDirDelimiter();
-		target += "cookies";
-		lldebugs << "target = " << target << llendl;
-		if(LLFile::isfile(target))
-		{	
-			LLFile::remove(target);
-		}
-		
-		// Other accounts may have new-style cookie files too -- delete them as well
-		target = base_dir;
-		target += filename;
-		target += gDirUtilp->getDirDelimiter();
-		target += PLUGIN_COOKIE_FILE_NAME;
-		lldebugs << "target = " << target << llendl;
-		if(LLFile::isfile(target))
-		{	
-			LLFile::remove(target);
-		}
-	}
-	
-	// If we have an OpenID cookie, re-add it to the cookie store.
-	setOpenIDCookie();
-}
-	
-/////////////////////////////////////////////////////////////////////////////////////////
-// static 
-void LLViewerMedia::clearAllCaches()
-{
-	// Clear all plugins' caches
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-	for (; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		pimpl->clearCache();
-	}
-}
-	
-/////////////////////////////////////////////////////////////////////////////////////////
-// static 
-void LLViewerMedia::setCookiesEnabled(bool enabled)
-{
-	// Set the "cookies enabled" flag for all loaded plugins
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-	for (; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if(pimpl->mMediaSource)
-		{
-			pimpl->mMediaSource->enable_cookies(enabled);
-		}
-	}
-}
-	
-/////////////////////////////////////////////////////////////////////////////////////////
-// static 
-void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int port)
-{
-	// Set the proxy config for all loaded plugins
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-	for (; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if(pimpl->mMediaSource)
-		{
-			pimpl->mMediaSource->proxy_setup(enable, host, port);
-		}
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static 
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-LLPluginCookieStore *LLViewerMedia::getCookieStore()
-{
-	if(sCookieStore == NULL)
-	{
-		sCookieStore = new LLPluginCookieStore;
-	}
-	
-	return sCookieStore;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::loadCookieFile()
-{
-	// build filename for each user
-	std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
-
-	if (resolved_filename.empty())
-	{
-		llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
-		return;
-	}
-	
-	// open the file for reading
-	llifstream file(resolved_filename);
-	if (!file.is_open())
-	{
-		llwarns << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << llendl;
-		return;
-	}
-	
-	getCookieStore()->readAllCookies(file, true);
-
-	file.close();
-	
-	// send the clear_cookies message to all loaded plugins
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-	for (; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if(pimpl->mMediaSource)
-		{
-			pimpl->mMediaSource->clear_cookies();
-		}
-	}
-	
-	// If we have an OpenID cookie, re-add it to the cookie store.
-	setOpenIDCookie();
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::saveCookieFile()
-{
-	// build filename for each user
-	std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
-
-	if (resolved_filename.empty())
-	{
-		llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
-		return;
-	}
-
-	// open a file for writing
-	llofstream file (resolved_filename);
-	if (!file.is_open())
-	{
-		llwarns << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << llendl;
-		return;
-	}
-
-	getCookieStore()->writePersistentCookies(file);
-
-	file.close();
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure)
-{
-	std::stringstream cookie;
-	
-	cookie << name << "=" << LLPluginCookieStore::quoteString(value);
-	
-	if(expires.notNull())
-	{
-		cookie << "; expires=" << expires.asRFC1123();
-	}
-	
-	cookie << "; domain=" << domain;
-
-	cookie << "; path=" << path;
-	
-	if(secure)
-	{
-		cookie << "; secure";
-	}
-	
-	getCookieStore()->setCookies(cookie.str());
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure)
-{
-	// A session cookie just has a NULL date.
-	addCookie(name, value, domain, LLDate(), path, secure);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path )
-{
-	// To remove a cookie, add one with the same name, domain, and path that expires in the past.
-	
-	addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::setOpenIDCookie()
-{
-	if(!sOpenIDCookie.empty())
-	{
-		// The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port]
-		// We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.
-		// We therefore do it here.
-		std::string authority = sOpenIDURL.mAuthority;
-		std::string::size_type host_start = authority.find('@'); 
-		if(host_start == std::string::npos)
-		{
-			// no username/password
-			host_start = 0;
-		}
-		else
-		{
-			// Hostname starts after the @. 
-			// (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.)
-			++host_start;
-		}
-		std::string::size_type host_end = authority.rfind(':'); 
-		if((host_end == std::string::npos) || (host_end < host_start))
-		{
-			// no port
-			host_end = authority.size();
-		}
-		
-		getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start));
-
-		// *HACK: Doing this here is nasty, find a better way.
-		LLWebSharing::instance().setOpenIDCookie(sOpenIDCookie);
-
-		// Do a web profile get so we can store the cookie 
-		LLSD headers = LLSD::emptyMap();
-		headers["Accept"] = "*/*";
-		headers["Cookie"] = sOpenIDCookie;
-		headers["User-Agent"] = getCurrentUserAgent();
-
-		std::string profile_url = getProfileURL("");
-		LLURL raw_profile_url( profile_url.c_str() );
-
-		LLHTTPClient::get(profile_url,  
-			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
-			headers);
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token)
-{
-	LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL;
-
-	// post the token to the url 
-	// the responder will need to extract the cookie(s).
-
-	// Save the OpenID URL for later -- we may need the host when adding the cookie.
-	sOpenIDURL.init(openid_url.c_str());
-	
-	// We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
-	sOpenIDCookie.clear();
-
-	LLSD headers = LLSD::emptyMap();
-	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
-	headers["Accept"] = "*/*";
-	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
-	headers["Content-Type"] = "application/x-www-form-urlencoded";
-
-	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
-	size_t size = openid_token.size();
-	U8 *data = new U8[size];
-	memcpy(data, openid_token.data(), size);
-
-	LLHTTPClient::postRaw( 
-		openid_url, 
-		data, 
-		size, 
-		new LLViewerMediaOpenIDResponder(),
-		headers);
-			
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::openIDCookieResponse(const std::string &cookie)
-{
-	LL_DEBUGS("MediaAuth") << "Cookie received: \"" << cookie << "\"" << LL_ENDL;
-	
-	sOpenIDCookie += cookie;
-
-	setOpenIDCookie();
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
-{
-	if(uuid.empty())
-		return;
-		
-	for (impl_list::iterator iter = sViewerMediaImplList.begin(); iter != sViewerMediaImplList.end(); iter++)
-	{
-		if((*iter)->mMediaSource && (*iter)->mMediaSource->pluginSupportsMediaBrowser())
-		{
-			(*iter)->mMediaSource->proxyWindowOpened(target, uuid);
-		}
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::proxyWindowClosed(const std::string &uuid)
-{
-	if(uuid.empty())
-		return;
-
-	for (impl_list::iterator iter = sViewerMediaImplList.begin(); iter != sViewerMediaImplList.end(); iter++)
-	{
-		if((*iter)->mMediaSource && (*iter)->mMediaSource->pluginSupportsMediaBrowser())
-		{
-			(*iter)->mMediaSource->proxyWindowClosed(uuid);
-		}
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::createSpareBrowserMediaSource()
-{
-	// If we don't have a spare browser media source, create one.
-	// However, if PluginAttachDebuggerToPlugins is set then don't spawn a spare
-	// SLPlugin process in order to not be confused by an unrelated gdb terminal
-	// popping up at the moment we start a media plugin.
-	if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
-	{
-		// The null owner will keep the browser plugin from fully initializing 
-		// (specifically, it keeps LLPluginClassMedia from negotiating a size change, 
-		// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
-		sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// static
-LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() 
-{
-	LLPluginClassMedia* result = sSpareBrowserMediaSource;
-	sSpareBrowserMediaSource = NULL;
-	return result; 
-};
-
-bool LLViewerMedia::hasInWorldMedia()
-{
-	if (sInWorldMediaDisabled) return false;
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-	// This should be quick, because there should be very few non-in-world-media impls
-	for (; iter != end; iter++)
-	{
-		LLViewerMediaImpl* pimpl = *iter;
-		if (!pimpl->getUsedInUI() && !pimpl->isParcelMedia())
-		{
-			// Found an in-world media impl
-			return true;
-		}
-	}
-	return false;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::hasParcelMedia()
-{
-	return !LLViewerParcelMedia::getURL().empty();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::hasParcelAudio()
-{
-	return !LLViewerMedia::getParcelAudioURL().empty();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-std::string LLViewerMedia::getParcelAudioURL()
-{
-	return LLViewerParcelMgr::getInstance()->getAgentParcel()->getMusicURL();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::initClass()
-{
-	gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);	
-	sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
-		setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished));
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::cleanupClass()
-{
-	gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
-	sTeleportFinishConnection.disconnect();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::onTeleportFinished()
-{
-	// On teleport, clear this setting (i.e. set it to true)
-	gSavedSettings.setBOOL("MediaTentativeAutoPlay", true);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// LLViewerMediaImpl
-//////////////////////////////////////////////////////////////////////////////////////////
-LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id, 
-										  S32 media_width, 
-										  S32 media_height, 
-										  U8 media_auto_scale, 
-										  U8 media_loop)
-:	
-	mMediaSource( NULL ),
-	mMovieImageHasMips(false),
-	mMediaWidth(media_width),
-	mMediaHeight(media_height),
-	mMediaAutoScale(media_auto_scale),
-	mMediaLoop(media_loop),
-	mNeedsNewTexture(true),
-	mTextureUsedWidth(0),
-	mTextureUsedHeight(0),
-	mSuspendUpdates(false),
-	mVisible(true),
-	mLastSetCursor( UI_CURSOR_ARROW ),
-	mMediaNavState( MEDIANAVSTATE_NONE ),
-	mInterest(0.0f),
-	mUsedInUI(false),
-	mHasFocus(false),
-	mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
-	mNavigateRediscoverType(false),
-	mNavigateServerRequest(false),
-	mMediaSourceFailed(false),
-	mRequestedVolume(1.0f),
-	mIsMuted(false),
-	mNeedsMuteCheck(false),
-	mPreviousMediaState(MEDIA_NONE),
-	mPreviousMediaTime(0.0f),
-	mIsDisabled(false),
-	mIsParcelMedia(false),
-	mProximity(-1),
-	mProximityDistance(0.0f),
-	mMimeTypeProbe(NULL),
-	mMediaAutoPlay(false),
-	mInNearbyMediaList(false),
-	mClearCache(false),
-	mBackgroundColor(LLColor4::white),
-	mNavigateSuspended(false),
-	mNavigateSuspendedDeferred(false),
-	mIsUpdated(false),
-	mTrustedBrowser(false)
-{ 
-
-	// Set up the mute list observer if it hasn't been set up already.
-	if(!sViewerMediaMuteListObserverInitialized)
-	{
-		LLMuteList::getInstance()->addObserver(&sViewerMediaMuteListObserver);
-		sViewerMediaMuteListObserverInitialized = true;
-	}
-	
-	add_media_impl(this);
-
-	setTextureID(texture_id);
-	
-	// connect this media_impl to the media texture, creating it if it doesn't exist.0
-	// This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded.
-	LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId);
-	if(media_tex)
-	{
-		media_tex->setMediaImpl();
-	}
-
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-LLViewerMediaImpl::~LLViewerMediaImpl()
-{
-	destroyMediaSource();
-	
-	LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;
-
-	setTextureID();
-	remove_media_impl(this);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
-{
-	// Broadcast to observers using the superclass version
-	LLViewerMediaEventEmitter::emitEvent(plugin, event);
-	
-	// If this media is on one or more LLVOVolume objects, tell them about the event as well.
-	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
-	while(iter != mObjectList.end())
-	{
-		LLVOVolume *self = *iter;
-		++iter;
-		self->mediaEvent(this, plugin, event);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
-{
-	bool mimeTypeChanged = (mMimeType != mime_type);
-	bool pluginChanged = (LLMIMETypes::implType(mCurrentMimeType) != LLMIMETypes::implType(mime_type));
-	
-	if(!mMediaSource || pluginChanged)
-	{
-		// We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type.
-		(void)initializePlugin(mime_type);
-	}
-	else if(mimeTypeChanged)
-	{
-		// The same plugin should be able to handle the new media -- just update the stored mime type.
-		mMimeType = mime_type;
-	}
-
-	return (mMediaSource != NULL);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::createMediaSource()
-{
-	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
-	{
-		// This media shouldn't be created yet.
-		return;
-	}
-	
-	if(! mMediaURL.empty())
-	{
-		navigateInternal();
-	}
-	else if(! mMimeType.empty())
-	{
-		if (!initializeMedia(mMimeType))
-		{
-			LL_WARNS("Media") << "Failed to initialize media for mime type " << mMimeType << LL_ENDL;
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::destroyMediaSource()
-{
-	mNeedsNewTexture = true;
-
-	// Tell the viewer media texture it's no longer active
-	LLViewerMediaTexture* oldImage = LLViewerTextureManager::findMediaTexture( mTextureId );
-	if (oldImage)
-	{
-		oldImage->setPlaying(FALSE) ;
-	}
-	
-	cancelMimeTypeProbe();
-	
-	if(mMediaSource)
-	{
-		mMediaSource->setDeleteOK(true) ;
-		delete mMediaSource;
-		mMediaSource = NULL;
-	}	
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::setMediaType(const std::string& media_type)
-{
-	mMimeType = media_type;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-/*static*/
-LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target)
-{
-	std::string plugin_basename = LLMIMETypes::implType(media_type);
-	LLPluginClassMedia* media_source = NULL;
-	
-	// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
-	// If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
-	if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
-	{
-		media_source = LLViewerMedia::getSpareBrowserMediaSource();
-		if(media_source)
-		{
-			media_source->setOwner(owner);
-			media_source->setTarget(target);
-			media_source->setSize(default_width, default_height);
-						
-			return media_source;
-		}
-	}
-	
-	if(plugin_basename.empty())
-	{
-		LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
-	}
-	else
-	{
-		std::string launcher_name = gDirUtilp->getLLPluginLauncher();
-		std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename);
-		std::string user_data_path = gDirUtilp->getOSUserAppDir();
-		user_data_path += gDirUtilp->getDirDelimiter();
-
-		// Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.)
-		// If the linden username returned is blank, that can only mean we are
-		// at the login page displaying login Web page or Web browser test via Develop menu.
-		// In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this
-		// is what we always used before this change)
-		std::string linden_user_dir = gDirUtilp->getLindenUserDir();
-		if ( ! linden_user_dir.empty() )
-		{
-			// gDirUtilp->getLindenUserDir() is whole path, not just Linden name
-			user_data_path = linden_user_dir;
-			user_data_path += gDirUtilp->getDirDelimiter();
-		};
-
-		// See if the plugin executable exists
-		llstat s;
-		if(LLFile::stat(launcher_name, &s))
-		{
-			LL_WARNS("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL;
-		}
-		else if(LLFile::stat(plugin_name, &s))
-		{
-			LL_WARNS("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL;
-		}
-		else
-		{
-			media_source = new LLPluginClassMedia(owner);
-			media_source->setSize(default_width, default_height);
-			media_source->setUserDataPath(user_data_path);
-			media_source->setLanguageCode(LLUI::getLanguage());
-
-			// collect 'cookies enabled' setting from prefs and send to embedded browser
-			bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
-			media_source->enable_cookies( cookies_enabled );
-
-			// collect 'plugins enabled' setting from prefs and send to embedded browser
-			bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
-			media_source->setPluginsEnabled( plugins_enabled );
-
-			// collect 'javascript enabled' setting from prefs and send to embedded browser
-			bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
-			media_source->setJavascriptEnabled( javascript_enabled );
-			
-			media_source->setTarget(target);
-			
-			const std::string plugin_dir = gDirUtilp->getLLPluginDir();
-			if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
-			{
-				return media_source;
-			}
-			else
-			{
-				LL_WARNS("Media") << "Failed to init plugin.  Destroying." << LL_ENDL;
-				delete media_source;
-			}
-		}
-	}
-	
-	LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
-	LLSD args;
-	args["MIME_TYPE"] = media_type;
-	LLNotificationsUtil::add("NoPlugin", args);
-
-	return NULL;
-}							
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
-{
-	if(mMediaSource)
-	{
-		// Save the previous media source's last set size before destroying it.
-		mMediaWidth = mMediaSource->getSetWidth();
-		mMediaHeight = mMediaSource->getSetHeight();
-	}
-	
-	// Always delete the old media impl first.
-	destroyMediaSource();
-	
-	// and unconditionally set the mime type
-	mMimeType = media_type;
-
-	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
-	{
-		// This impl should not be loaded at this time.
-		LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
-		
-		return false;
-	}
-
-	// If we got here, we want to ignore previous init failures.
-	mMediaSourceFailed = false;
-
-	// Save the MIME type that really caused the plugin to load
-	mCurrentMimeType = mMimeType;
-
-	LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget);
-	
-	if (media_source)
-	{
-		media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout"));
-		media_source->setLoop(mMediaLoop);
-		media_source->setAutoScale(mMediaAutoScale);
-		media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
-		media_source->focus(mHasFocus);
-		media_source->setBackgroundColor(mBackgroundColor);
-		
-		if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors"))
-		{
-			media_source->ignore_ssl_cert_errors(true);
-		}
-
-		// the correct way to deal with certs it to load ours from CA.pem and append them to the ones
-		// Qt/WebKit loads from your system location.
-		// Note: This needs the new CA.pem file with the Equifax Secure Certificate Authority 
-		// cert at the bottom: (MIIDIDCCAomgAwIBAgIENd70zzANBg)
-		std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" );
-		media_source->addCertificateFilePath( ca_path );
-
-		media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"));
-		
-		if(mClearCache)
-		{
-			mClearCache = false;
-			media_source->clear_cache();
-		}
-		
-		// TODO: Only send cookies to plugins that need them
-		//  Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message.
-		//  Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message,
-		//  which could cause odd race conditions.
-		std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies();
-		lldebugs << "setting cookies: " << all_cookies << llendl;
-		if(!all_cookies.empty())
-		{
-			media_source->set_cookies(all_cookies);
-		}
-				
-		mMediaSource = media_source;
-		mMediaSource->setDeleteOK(false) ;
-		updateVolume();
-
-		return true;
-	}
-
-	// Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes.
-	mMediaSourceFailed = true;
-
-	return false;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::loadURI()
-{
-	if(mMediaSource)
-	{
-		// trim whitespace from front and back of URL - fixes EXT-5363
-		LLStringUtil::trim( mMediaURL );
-
-		// *HACK: we don't know if the URI coming in is properly escaped
-		// (the contract doesn't specify whether it is escaped or not.
-		// but LLQtWebKit expects it to be, so we do our best to encode
-		// special characters)
-		// The strings below were taken right from http://www.ietf.org/rfc/rfc1738.txt
-		// Note especially that '%' and '/' are there.
-		std::string uri = LLURI::escape(mMediaURL,
-										"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-										"0123456789"
-										"$-_.+"
-										"!*'(),"
-										"{}|\\^~[]`"
-										"<>#%"
-										";/?:@&=",
-										false);
-		llinfos << "Asking media source to load URI: " << uri << llendl;
-		
-		mMediaSource->loadURI( uri );
-		
-		// A non-zero mPreviousMediaTime means that either this media was previously unloaded by the priority code while playing/paused, 
-		// or a seek happened before the media loaded.  In either case, seek to the saved time.
-		if(mPreviousMediaTime != 0.0f)
-		{
-			seek(mPreviousMediaTime);
-		}
-			
-		if(mPreviousMediaState == MEDIA_PLAYING)
-		{
-			// This media was playing before this instance was unloaded.
-			start();
-		}
-		else if(mPreviousMediaState == MEDIA_PAUSED)
-		{
-			// This media was paused before this instance was unloaded.
-			pause();
-		}
-		else
-		{
-			// No relevant previous media play state -- if we're loading the URL, we want to start playing.
-			start();
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::setSize(int width, int height)
-{
-	mMediaWidth = width;
-	mMediaHeight = height;
-	if(mMediaSource)
-	{
-		mMediaSource->setSize(width, height);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::showNotification(LLNotificationPtr notify)
-{
-	mNotification = notify;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::hideNotification()
-{
-	mNotification.reset();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::play()
-{
-	// If the media source isn't there, try to initialize it and load an URL.
-	if(mMediaSource == NULL)
-	{
-	 	if(!initializeMedia(mMimeType))
-		{
-			// This may be the case where the plugin's priority is PRIORITY_UNLOADED
-			return;
-		}
-		
-		// Only do this if the media source was just loaded.
-		loadURI();
-	}
-	
-	// always start the media
-	start();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::stop()
-{
-	if(mMediaSource)
-	{
-		mMediaSource->stop();
-		// destroyMediaSource();
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::pause()
-{
-	if(mMediaSource)
-	{
-		mMediaSource->pause();
-	}
-	else
-	{
-		mPreviousMediaState = MEDIA_PAUSED;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::start()
-{
-	if(mMediaSource)
-	{
-		mMediaSource->start();
-	}
-	else
-	{
-		mPreviousMediaState = MEDIA_PLAYING;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::seek(F32 time)
-{
-	if(mMediaSource)
-	{
-		mMediaSource->seek(time);
-	}
-	else
-	{
-		// Save the seek time to be set when the media is loaded.
-		mPreviousMediaTime = time;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::skipBack(F32 step_scale)
-{
-	if(mMediaSource)
-	{
-		if(mMediaSource->pluginSupportsMediaTime())
-		{
-			F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale);
-			if(back_step < 0.0)
-			{
-				back_step = 0.0;
-			}
-			mMediaSource->seek(back_step);
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::skipForward(F32 step_scale)
-{
-	if(mMediaSource)
-	{
-		if(mMediaSource->pluginSupportsMediaTime())
-		{
-			F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale);
-			if(forward_step > mMediaSource->getDuration())
-			{
-				forward_step = mMediaSource->getDuration();
-			}
-			mMediaSource->seek(forward_step);
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::setVolume(F32 volume)
-{
-	mRequestedVolume = volume;
-	updateVolume();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::updateVolume()
-{
-	if(mMediaSource)
-	{
-		// always scale the volume by the global media volume 
-		F32 volume = mRequestedVolume * LLViewerMedia::getVolume();
-
-		if (mProximityCamera > 0) 
-		{
-			if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMax"))
-			{
-				volume = 0;
-			}
-			else if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMin"))
-			{
-				// attenuated_volume = 1 / (roll_off_rate * (d - min))^2
-				// the +1 is there so that for distance 0 the volume stays the same
-				F64 adjusted_distance = mProximityCamera - gSavedSettings.getF32("MediaRollOffMin");
-				F64 attenuation = 1.0 + (gSavedSettings.getF32("MediaRollOffRate") * adjusted_distance);
-				attenuation = 1.0 / (attenuation * attenuation);
-				// the attenuation multiplier should never be more than one since that would increase volume
-				volume = volume * llmin(1.0, attenuation);
-			}
-		}
-
-		mMediaSource->setVolume(volume);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-F32 LLViewerMediaImpl::getVolume()
-{
-	return mRequestedVolume;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::focus(bool focus)
-{
-	mHasFocus = focus;
-	
-	if (mMediaSource)
-	{
-		// call focus just for the hell of it, even though this apopears to be a nop
-		mMediaSource->focus(focus);
-		if (focus)
-		{
-			// spoof a mouse click to *actually* pass focus
-			// Don't do this anymore -- it actually clicks through now.
-//			mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0);
-//			mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0);
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::hasFocus() const
-{
-	// FIXME: This might be able to be a bit smarter by hooking into LLViewerMediaFocus, etc.
-	return mHasFocus;
-}
-
-std::string LLViewerMediaImpl::getCurrentMediaURL()
-{
-	if(!mCurrentMediaURL.empty())
-	{
-		return mCurrentMediaURL;
-	}
-	
-	return mMediaURL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::clearCache()
-{
-	if(mMediaSource)
-	{
-		mMediaSource->clear_cache();
-	}
-	else
-	{
-		mClearCache = true;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button)
-{
-	scaleMouse(&x, &y);
-	mLastMouseX = x;
-	mLastMouseY = y;
-//	llinfos << "mouse down (" << x << ", " << y << ")" << llendl;
-	if (mMediaSource)
-	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, button, x, y, mask);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseUp(S32 x, S32 y, MASK mask, S32 button)
-{
-	scaleMouse(&x, &y);
-	mLastMouseX = x;
-	mLastMouseY = y;
-//	llinfos << "mouse up (" << x << ", " << y << ")" << llendl;
-	if (mMediaSource)
-	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, button, x, y, mask);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask)
-{
-    scaleMouse(&x, &y);
-	mLastMouseX = x;
-	mLastMouseY = y;
-//	llinfos << "mouse move (" << x << ", " << y << ")" << llendl;
-	if (mMediaSource)
-	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, x, y, mask);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//static 
-void LLViewerMediaImpl::scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y)
-{
-	F32 texture_x = texture_coords.mV[VX];
-	F32 texture_y = texture_coords.mV[VY];
-	
-	// Deal with repeating textures by wrapping the coordinates into the range [0, 1.0)
-	texture_x = fmodf(texture_x, 1.0f);
-	if(texture_x < 0.0f)
-		texture_x = 1.0 + texture_x;
-		
-	texture_y = fmodf(texture_y, 1.0f);
-	if(texture_y < 0.0f)
-		texture_y = 1.0 + texture_y;
-
-	// scale x and y to texel units.
-	*x = llround(texture_x * mMediaSource->getTextureWidth());
-	*y = llround((1.0f - texture_y) * mMediaSource->getTextureHeight());
-
-	// Adjust for the difference between the actual texture height and the amount of the texture in use.
-	*y -= (mMediaSource->getTextureHeight() - mMediaSource->getHeight());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button)
-{
-	if(mMediaSource)
-	{
-		S32 x, y;
-		scaleTextureCoords(texture_coords, &x, &y);
-
-		mouseDown(x, y, mask, button);
-	}
-}
-
-void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button)
-{
-	if(mMediaSource)
-	{		
-		S32 x, y;
-		scaleTextureCoords(texture_coords, &x, &y);
-
-		mouseUp(x, y, mask, button);
-	}
-}
-
-void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
-{
-	if(mMediaSource)
-	{		
-		S32 x, y;
-		scaleTextureCoords(texture_coords, &x, &y);
-
-		mouseMove(x, y, mask);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
-{
-	scaleMouse(&x, &y);
-	mLastMouseX = x;
-	mLastMouseY = y;
-	if (mMediaSource)
-	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, button, x, y, mask);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask)
-{
-	scaleMouse(&x, &y);
-	mLastMouseX = x;
-	mLastMouseY = y;
-	if (mMediaSource)
-	{
-		mMediaSource->scrollEvent(x, y, mask);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::onMouseCaptureLost()
-{
-	if (mMediaSource)
-	{
-		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 0, mLastMouseX, mLastMouseY, 0);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) 
-{ 
-	// NOTE: this is called when the mouse is released when we have capture.
-	// Due to the way mouse coordinates are mapped to the object, we can't use the x and y coordinates that come in with the event.
-	
-	if(hasMouseCapture())
-	{
-		// Release the mouse -- this will also send a mouseup to the media
-		gFocusMgr.setMouseCapture( FALSE );
-	}
-
-	return TRUE; 
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-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 );
-
-		// 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
-		bool logged_in = LLLoginInstance::getInstance()->authSuccess();
-		mMediaSource->jsValuesValidEvent( logged_in );
-
-		// current location within a region
-		LLVector3 agent_pos = gAgent.getPositionAgent();
-		double x = agent_pos.mV[ VX ];
-		double y = agent_pos.mV[ VY ];
-		double z = agent_pos.mV[ VZ ];
-		mMediaSource->jsAgentLocationEvent( x, y, z );
-
-		// current region agent is in
-		std::string region_name("");
-		LLViewerRegion* region = gAgent.getRegion();
-		if ( region )
-		{
-			region_name = region->getName();
-		};
-		mMediaSource->jsAgentRegionEvent( region_name );
-
-		// language code the viewer is set to
-		mMediaSource->jsAgentLanguageEvent( LLUI::getLanguage() );
-
-		// maturity setting the agent has selected
-		if ( gAgent.prefersAdult() )
-			mMediaSource->jsAgentMaturityEvent( "GMA" );	// Adult means see adult, mature and general content
-		else
-		if ( gAgent.prefersMature() )
-			mMediaSource->jsAgentMaturityEvent( "GM" );	// Mature means see mature and general content
-		else
-		if ( gAgent.prefersPG() )
-			mMediaSource->jsAgentMaturityEvent( "G" );	// PG means only see General content
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-std::string LLViewerMediaImpl::getName() const 
-{ 
-	if (mMediaSource)
-	{
-		return mMediaSource->getMediaName();
-	}
-	
-	return LLStringUtil::null; 
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateBack()
-{
-	if (mMediaSource)
-	{
-		mMediaSource->browse_back();
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateForward()
-{
-	if (mMediaSource)
-	{
-		mMediaSource->browse_forward();
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateReload()
-{
-	navigateTo(getCurrentMediaURL(), "", true, false);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateHome()
-{
-	bool rediscover_mimetype = mHomeMimeType.empty();
-	navigateTo(mHomeURL, mHomeMimeType, rediscover_mimetype, false);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::unload()
-{
-	// Unload the media impl and clear its state.
-	destroyMediaSource();
-	resetPreviousMediaState();
-	mMediaURL.clear();
-	mMimeType.clear();
-	mCurrentMediaURL.clear();
-	mCurrentMimeType.clear();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type,  bool rediscover_type, bool server_request)
-{
-	cancelMimeTypeProbe();
-
-	if(mMediaURL != url)
-	{
-		// Don't carry media play state across distinct URLs.
-		resetPreviousMediaState();
-	}
-	
-	// Always set the current URL and MIME type.
-	mMediaURL = url;
-	mMimeType = mime_type;
-	
-	// Clear the current media URL, since it will no longer be correct.
-	mCurrentMediaURL.clear();
-	
-	// if mime type discovery was requested, we'll need to do it when the media loads
-	mNavigateRediscoverType = rediscover_type;
-	
-	// and if this was a server request, the navigate on load will also need to be one.
-	mNavigateServerRequest = server_request;
-	
-	// An explicit navigate resets the "failed" flag.
-	mMediaSourceFailed = false;
-
-	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
-	{
-		// Helpful to have media urls in log file. Shouldn't be spammy.
-		llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
-
-		// This impl should not be loaded at this time.
-		LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
-		
-		return;
-	}
-
-	navigateInternal();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateInternal()
-{
-	// Helpful to have media urls in log file. Shouldn't be spammy.
-	llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
-
-	if(mNavigateSuspended)
-	{
-		llwarns << "Deferring navigate." << llendl;
-		mNavigateSuspendedDeferred = true;
-		return;
-	}
-	
-	if(mMimeTypeProbe != NULL)
-	{
-		llwarns << "MIME type probe already in progress -- bailing out." << llendl;
-		return;
-	}
-	
-	if(mNavigateServerRequest)
-	{
-		setNavState(MEDIANAVSTATE_SERVER_SENT);
-	}
-	else
-	{
-		setNavState(MEDIANAVSTATE_NONE);
-	}
-			
-	// If the caller has specified a non-empty MIME type, look that up in our MIME types list.
-	// If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
-	// This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
-	// but the parcel owner has correctly set the MIME type in the parcel media settings.
-	
-	if(!mMimeType.empty() && (mMimeType != LLMIMETypes::getDefaultMimeType()))
-	{
-		std::string plugin_basename = LLMIMETypes::implType(mMimeType);
-		if(!plugin_basename.empty())
-		{
-			// We have a plugin for this mime type
-			mNavigateRediscoverType = false;
-		}
-	}
-
-	if(mNavigateRediscoverType)
-	{
-
-		LLURI uri(mMediaURL);
-		std::string scheme = uri.scheme();
-
-		if(scheme.empty() || "http" == scheme || "https" == scheme)
-		{
-			// If we don't set an Accept header, LLHTTPClient will add one like this:
-			//    Accept: application/llsd+xml
-			// which is really not what we want.
-			LLSD headers = LLSD::emptyMap();
-			headers["Accept"] = "*/*";
-			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com
-			headers["Cookie"] = "";
-			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
-		}
-		else if("data" == scheme || "file" == scheme || "about" == scheme)
-		{
-			// FIXME: figure out how to really discover the type for these schemes
-			// We use "data" internally for a text/html url for loading the login screen
-			if(initializeMedia("text/html"))
-			{
-				loadURI();
-			}
-		}
-		else
-		{
-			// This catches 'rtsp://' urls
-			if(initializeMedia(scheme))
-			{
-				loadURI();
-			}
-		}
-	}
-	else if(initializeMedia(mMimeType))
-	{
-		loadURI();
-	}
-	else
-	{
-		LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateStop()
-{
-	if(mMediaSource)
-	{
-		mMediaSource->browse_stop();
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
-{
-	bool result = false;
-	
-	if (mMediaSource)
-	{
-		// FIXME: THIS IS SO WRONG.
-		// Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
-		if( MASK_CONTROL & mask )
-		{
-			result = true;
-		}
-		
-		if(!result)
-		{
-			
-			LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData();
-			
-			result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data);
-			// Since the viewer internal event dispatching doesn't give us key-up events, simulate one here.
-			(void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data);
-		}
-	}
-	
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
-{
-	bool result = false;
-	
-	if (mMediaSource)
-	{
-		// only accept 'printable' characters, sigh...
-		if (uni_char >= 32 // discard 'control' characters
-			&& uni_char != 127) // SDL thinks this is 'delete' - yuck.
-		{
-			LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData();
-			
-			mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data);
-		}
-	}
-	
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::canNavigateForward()
-{
-	BOOL result = FALSE;
-	if (mMediaSource)
-	{
-		result = mMediaSource->getHistoryForwardAvailable();
-	}
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::canNavigateBack()
-{
-	BOOL result = FALSE;
-	if (mMediaSource)
-	{
-		result = mMediaSource->getHistoryBackAvailable();
-	}
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::update()
-{
-	if(mMediaSource == NULL)
-	{
-		if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
-		{
-			// This media source should not be loaded.
-		}
-		else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW)
-		{
-			// Don't load new instances that are at PRIORITY_SLIDESHOW or below.  They're just kept around to preserve state.
-		}
-		else if(mMimeTypeProbe != NULL)
-		{
-			// this media source is doing a MIME type probe -- don't try loading it again.
-		}
-		else
-		{
-			// This media may need to be loaded.
-			if(sMediaCreateTimer.hasExpired())
-			{
-				LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL;
-				createMediaSource();
-				sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY);
-			}
-			else
-			{
-				LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL;
-			}
-		}
-	}
-	else
-	{
-		updateVolume();
-
-		// TODO: this is updated every frame - is this bad?
-		updateJavascriptObject();
-
-		// If we didn't just create the impl, it may need to get cookie updates.
-		if(!sUpdatedCookies.empty())
-		{
-			// TODO: Only send cookies to plugins that need them
-			mMediaSource->set_cookies(sUpdatedCookies);
-		}
-	}
-
-	
-	if(mMediaSource == NULL)
-	{
-		return;
-	}
-	
-	// Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash.
-	setNavigateSuspended(true);
-	
-	mMediaSource->idle();
-
-	setNavigateSuspended(false);
-
-	if(mMediaSource == NULL)
-	{
-		return;
-	}
-	
-	if(mMediaSource->isPluginExited())
-	{
-		resetPreviousMediaState();
-		destroyMediaSource();
-		return;
-	}
-
-	if(!mMediaSource->textureValid())
-	{
-		return;
-	}
-	
-	if(mSuspendUpdates || !mVisible)
-	{
-		return;
-	}
-	
-	LLViewerMediaTexture* placeholder_image = updatePlaceholderImage();
-		
-	if(placeholder_image)
-	{
-		LLRect dirty_rect;
-		
-		// Since we're updating this texture, we know it's playing.  Tell the texture to do its replacement magic so it gets rendered.
-		placeholder_image->setPlaying(TRUE);
-
-		if(mMediaSource->getDirty(&dirty_rect))
-		{
-			// Constrain the dirty rect to be inside the texture
-			S32 x_pos = llmax(dirty_rect.mLeft, 0);
-			S32 y_pos = llmax(dirty_rect.mBottom, 0);
-			S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos;
-			S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos;
-			
-			if(width > 0 && height > 0)
-			{
-
-				U8* data = mMediaSource->getBitsData();
-
-				// Offset the pixels pointer to match x_pos and y_pos
-				data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() );
-				data += ( y_pos * mMediaSource->getTextureDepth() );
-				
-				placeholder_image->setSubImage(
-						data, 
-						mMediaSource->getBitsWidth(), 
-						mMediaSource->getBitsHeight(),
-						x_pos, 
-						y_pos, 
-						width, 
-						height);
-
-			}
-			
-			mMediaSource->resetDirty();
-		}
-	}
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::updateImagesMediaStreams()
-{
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
-{
-	if(mTextureId.isNull())
-	{
-		// The code that created this instance will read from the plugin's bits.
-		return NULL;
-	}
-	
-	LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId );
-	
-	if (mNeedsNewTexture 
-		|| placeholder_image->getUseMipMaps()
-		|| (placeholder_image->getWidth() != mMediaSource->getTextureWidth())
-		|| (placeholder_image->getHeight() != mMediaSource->getTextureHeight())
-		|| (mTextureUsedWidth != mMediaSource->getWidth())
-		|| (mTextureUsedHeight != mMediaSource->getHeight())
-		)
-	{
-		LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL;
-		LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL;
-
-		int texture_width = mMediaSource->getTextureWidth();
-		int texture_height = mMediaSource->getTextureHeight();
-		int texture_depth = mMediaSource->getTextureDepth();
-		
-		// MEDIAOPT: check to see if size actually changed before doing work
-		placeholder_image->destroyGLTexture();
-		// MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work?
-		placeholder_image->reinit(FALSE);	// probably not needed
-
-		// MEDIAOPT: seems insane that we actually have to make an imageraw then
-		// immediately discard it
-		LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth);
-		// Clear the texture to the background color, ignoring alpha.
-		// convert background color channels from [0.0, 1.0] to [0, 255];
-		raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff);
-		int discard_level = 0;
-
-		// ask media source for correct GL image format constants
-		placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(),
-											 mMediaSource->getTextureFormatPrimary(),
-											 mMediaSource->getTextureFormatType(),
-											 mMediaSource->getTextureFormatSwapBytes());
-
-		placeholder_image->createGLTexture(discard_level, raw);
-
-		// MEDIAOPT: set this dynamically on play/stop
-		// FIXME
-//		placeholder_image->mIsMediaTexture = true;
-		mNeedsNewTexture = false;
-				
-		// If the amount of the texture being drawn by the media goes down in either width or height, 
-		// recreate the texture to avoid leaving parts of the old image behind.
-		mTextureUsedWidth = mMediaSource->getWidth();
-		mTextureUsedHeight = mMediaSource->getHeight();
-	}
-	
-	return placeholder_image;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-LLUUID LLViewerMediaImpl::getMediaTextureID() const
-{
-	return mTextureId;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::setVisible(bool visible)
-{
-	mVisible = visible;
-	
-	if(mVisible)
-	{
-		if(mMediaSource && mMediaSource->isPluginExited())
-		{
-			destroyMediaSource();
-		}
-		
-		if(!mMediaSource)
-		{
-			createMediaSource();
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseCapture()
-{
-	gFocusMgr.setMouseCapture(this);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y)
-{
-#if 0
-	S32 media_width, media_height;
-	S32 texture_width, texture_height;
-	getMediaSize( &media_width, &media_height );
-	getTextureSize( &texture_width, &texture_height );
-	S32 y_delta = texture_height - media_height;
-
-	*mouse_y -= y_delta;
-#endif
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::isMediaTimeBased()
-{
-	bool result = false;
-	
-	if(mMediaSource)
-	{
-		result = mMediaSource->pluginSupportsMediaTime();
-	}
-	
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::isMediaPlaying()
-{
-	bool result = false;
-	
-	if(mMediaSource)
-	{
-		EMediaStatus status = mMediaSource->getStatus();
-		if(status == MEDIA_PLAYING || status == MEDIA_LOADING)
-			result = true;
-	}
-	
-	return result;
-}
-//////////////////////////////////////////////////////////////////////////////////////////
-bool LLViewerMediaImpl::isMediaPaused()
-{
-	bool result = false;
-
-	if(mMediaSource)
-	{
-		if(mMediaSource->getStatus() == MEDIA_PAUSED)
-			result = true;
-	}
-	
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaImpl::hasMedia() const
-{
-	return mMediaSource != NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-void LLViewerMediaImpl::resetPreviousMediaState()
-{
-	mPreviousMediaState = MEDIA_NONE;
-	mPreviousMediaTime = 0.0f;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-void LLViewerMediaImpl::setDisabled(bool disabled, bool forcePlayOnEnable)
-{
-	if(mIsDisabled != disabled)
-	{
-		// Only do this on actual state transitions.
-		mIsDisabled = disabled;
-		
-		if(mIsDisabled)
-		{
-			// We just disabled this media.  Clear all state.
-			unload();
-		}
-		else
-		{
-			// We just (re)enabled this media.  Do a navigate if auto-play is in order.
-			if(isAutoPlayable() || forcePlayOnEnable)
-			{
-				navigateTo(mMediaEntryURL, "", true, true);
-			}
-		}
-
-	}
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaImpl::isForcedUnloaded() const
-{
-	if(mIsMuted || mMediaSourceFailed || mIsDisabled)
-	{
-		return true;
-	}
-	
-	if(sInWorldMediaDisabled)
-	{
-		// When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded.
-		if(!mUsedInUI)
-		{
-			return true;
-		}
-	}
-	
-	// If this media's class is not supposed to be shown, unload
-	if (!shouldShowBasedOnClass())
-	{
-		return true;
-	}
-	
-	return false;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaImpl::isPlayable() const
-{
-	if(isForcedUnloaded())
-	{
-		// All of the forced-unloaded criteria also imply not playable.
-		return false;
-	}
-	
-	if(hasMedia())
-	{
-		// Anything that's already playing is, by definition, playable.
-		return true;
-	}
-	
-	if(!mMediaURL.empty())
-	{
-		// If something has navigated the instance, it's ready to be played.
-		return true;
-	}
-	
-	return false;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
-{
-	bool pass_through = true;
-	switch(event)
-	{
-		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
-		{
-			LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL; 
-			std::string url = plugin->getClickURL();
-			std::string nav_type = plugin->getClickNavType();
-			LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser);
-		}
-		break;
-		case MEDIA_EVENT_CLICK_LINK_HREF:
-		{
-			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << plugin->getClickTarget() << "\", uri is " << plugin->getClickURL() << LL_ENDL;
-		};
-		break;
-		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
-		{
-			// The plugin failed to load properly.  Make sure the timer doesn't retry.
-			// TODO: maybe mark this plugin as not loadable somehow?
-			mMediaSourceFailed = true;
-
-			// Reset the last known state of the media to defaults.
-			resetPreviousMediaState();
-			
-			// TODO: may want a different message for this case?
-			LLSD args;
-			args["PLUGIN"] = LLMIMETypes::implType(mCurrentMimeType);
-			LLNotificationsUtil::add("MediaPluginFailed", args);
-		}
-		break;
-
-		case MEDIA_EVENT_PLUGIN_FAILED:
-		{
-			// The plugin crashed.
-			mMediaSourceFailed = true;
-
-			// Reset the last known state of the media to defaults.
-			resetPreviousMediaState();
-
-			LLSD args;
-			args["PLUGIN"] = LLMIMETypes::implType(mCurrentMimeType);
-			// SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
-			//LLNotificationsUtil::add("MediaPluginFailed", args);
-		}
-		break;
-		
-		case MEDIA_EVENT_CURSOR_CHANGED:
-		{
-			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << plugin->getCursorName() << LL_ENDL;
-
-			std::string cursor = plugin->getCursorName();
-			
-			if(cursor == "arrow")
-				mLastSetCursor = UI_CURSOR_ARROW;
-			else if(cursor == "ibeam")
-				mLastSetCursor = UI_CURSOR_IBEAM;
-			else if(cursor == "splith")
-				mLastSetCursor = UI_CURSOR_SIZEWE;
-			else if(cursor == "splitv")
-				mLastSetCursor = UI_CURSOR_SIZENS;
-			else if(cursor == "hand")
-				mLastSetCursor = UI_CURSOR_HAND;
-			else // for anything else, default to the arrow
-				mLastSetCursor = UI_CURSOR_ARROW;
-		}
-		break;
-
-		case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN:
-		{
-			LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL;
-			hideNotification();
-
-			if(getNavState() == MEDIANAVSTATE_SERVER_SENT)
-			{
-				setNavState(MEDIANAVSTATE_SERVER_BEGUN);
-			}
-			else
-			{
-				setNavState(MEDIANAVSTATE_BEGUN);
-			}
-		}
-		break;
-
-		case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
-		{
-			LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
-
-			std::string url = plugin->getNavigateURI();
-			if(getNavState() == MEDIANAVSTATE_BEGUN)
-			{
-				if(mCurrentMediaURL == url)
-				{
-					// This is a navigate that takes us to the same url as the previous navigate.
-					setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS);
-				}
-				else
-				{
-					mCurrentMediaURL = url;
-					setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED);
-				}
-			}
-			else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
-			{
-				mCurrentMediaURL = url;
-				setNavState(MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED);
-			}
-			else
-			{
-				// all other cases need to leave the state alone.
-			}
-		}
-		break;
-		
-		case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
-		{
-			LL_DEBUGS("Media") << "MEDIA_EVENT_LOCATION_CHANGED, uri is: " << plugin->getLocation() << LL_ENDL;
-
-			std::string url = plugin->getLocation();
-
-			if(getNavState() == MEDIANAVSTATE_BEGUN)
-			{
-				if(mCurrentMediaURL == url)
-				{
-					// This is a navigate that takes us to the same url as the previous navigate.
-					setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS);
-				}
-				else
-				{
-					mCurrentMediaURL = url;
-					setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED);
-				}
-			}
-			else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
-			{
-				mCurrentMediaURL = url;
-				setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED);
-			}
-			else
-			{
-				// Don't track redirects.
-				setNavState(MEDIANAVSTATE_NONE);
-			}
-		}
-		break;
-
-		case LLViewerMediaObserver::MEDIA_EVENT_PICK_FILE_REQUEST:
-		{
-			// Display a file picker
-			std::string response;
-			
-			LLFilePicker& picker = LLFilePicker::instance();
-			if (!picker.getOpenFile(LLFilePicker::FFLOAD_ALL))
-			{
-				// The user didn't pick a file -- the empty response string will indicate this.
-			}
-			
-			response = picker.getFirstFile();
-			
-			plugin->sendPickFileResponse(response);
-		}
-		break;
-
-
-		case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST:
-		{
-			LLNotification::Params auth_request_params;
-			auth_request_params.name = "AuthRequest";
-
-			// pass in host name and realm for site (may be zero length but will always exist)
-			LLSD args;
-			LLURL raw_url( plugin->getAuthURL().c_str() );
-			args["HOST_NAME"] = raw_url.getAuthority();
-			args["REALM"] = plugin->getAuthRealm();
-			auth_request_params.substitutions = args;
-
-			auth_request_params.payload = LLSD().with("media_id", mTextureId);
-			auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2);
-			LLNotifications::instance().add(auth_request_params);
-		};
-		break;
-
-		case LLViewerMediaObserver::MEDIA_EVENT_CLOSE_REQUEST:
-		{
-			std::string uuid = plugin->getClickUUID();
-
-			llinfos << "MEDIA_EVENT_CLOSE_REQUEST for uuid " << uuid << llendl;
-
-			if(uuid.empty())
-			{
-				// This close request is directed at this instance, let it fall through.
-			}
-			else
-			{
-				// This close request is directed at another instance
-				pass_through = false;
-				LLFloaterMediaBrowser::closeRequest(uuid);
-				LLFloaterWebContent::closeRequest(uuid);
-			}
-		}
-		break;
-
-		case LLViewerMediaObserver::MEDIA_EVENT_GEOMETRY_CHANGE:
-		{
-			std::string uuid = plugin->getClickUUID();
-
-			llinfos << "MEDIA_EVENT_GEOMETRY_CHANGE for uuid " << uuid << llendl;
-
-			if(uuid.empty())
-			{
-				// This geometry change request is directed at this instance, let it fall through.
-			}
-			else
-			{
-				// This request is directed at another instance
-				pass_through = false;
-				LLFloaterMediaBrowser::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
-				LLFloaterWebContent::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
-			}
-		}
-		break;
-
-		default:
-		break;
-	}
-
-	if(pass_through)
-	{
-		// Just chain the event to observers.
-		emitEvent(plugin, event);
-	}
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie)
-{
-	LLViewerMedia::getCookieStore()->setCookies(cookie);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-void
-LLViewerMediaImpl::cut()
-{
-	if (mMediaSource)
-		mMediaSource->cut();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-BOOL
-LLViewerMediaImpl::canCut() const
-{
-	if (mMediaSource)
-		return mMediaSource->canCut();
-	else
-		return FALSE;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-void
-LLViewerMediaImpl::copy()
-{
-	if (mMediaSource)
-		mMediaSource->copy();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-BOOL
-LLViewerMediaImpl::canCopy() const
-{
-	if (mMediaSource)
-		return mMediaSource->canCopy();
-	else
-		return FALSE;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-void
-LLViewerMediaImpl::paste()
-{
-	if (mMediaSource)
-		mMediaSource->paste();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-BOOL
-LLViewerMediaImpl::canPaste() const
-{
-	if (mMediaSource)
-		return mMediaSource->canPaste();
-	else
-		return FALSE;
-}
-
-void LLViewerMediaImpl::setUpdated(BOOL updated)
-{
-	mIsUpdated = updated ;
-}
-
-BOOL LLViewerMediaImpl::isUpdated()
-{
-	return mIsUpdated ;
-}
-
-void LLViewerMediaImpl::calculateInterest()
-{
-	LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId );
-	
-	if(texture != NULL)
-	{
-		mInterest = texture->getMaxVirtualSize();
-	}
-	else
-	{
-		// This will be a relatively common case now, since it will always be true for unloaded media.
-		mInterest = 0.0f;
-	}
-	
-	// Calculate distance from the avatar, for use in the proximity calculation.
-	mProximityDistance = 0.0f;
-	mProximityCamera = 0.0f;
-	if(!mObjectList.empty())
-	{
-		// Just use the first object in the list.  We could go through the list and find the closest object, but this should work well enough.
-		std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
-		LLVOVolume* objp = *iter ;
-		llassert_always(objp != NULL) ;
-		
-		// The distance calculation is invalid for HUD attachments -- leave both mProximityDistance and mProximityCamera at 0 for them.
-		if(!objp->isHUDAttachment())
-		{
-			LLVector3d obj_global = objp->getPositionGlobal() ;
-			LLVector3d agent_global = gAgent.getPositionGlobal() ;
-			LLVector3d global_delta = agent_global - obj_global ;
-			mProximityDistance = global_delta.magVecSquared();  // use distance-squared because it's cheaper and sorts the same.
-
-			LLVector3d camera_delta = gAgentCamera.getCameraPositionGlobal() - obj_global;
-			mProximityCamera = camera_delta.magVec();
-		}
-	}
-	
-	if(mNeedsMuteCheck)
-	{
-		// Check all objects this instance is associated with, and those objects' owners, against the mute list
-		mIsMuted = false;
-		
-		std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
-		for(; iter != mObjectList.end() ; ++iter)
-		{
-			LLVOVolume *obj = *iter;
-			llassert(obj);
-			if (!obj) continue;
-			if(LLMuteList::getInstance() &&
-			   LLMuteList::getInstance()->isMuted(obj->getID()))
-			{
-				mIsMuted = true;
-			}
-			else
-			{
-				// We won't have full permissions data for all objects.  Attempt to mute objects when we can tell their owners are muted.
-				if (LLSelectMgr::getInstance())
-				{
-					LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(obj);
-					if(obj_perm)
-					{
-						if(LLMuteList::getInstance() &&
-						   LLMuteList::getInstance()->isMuted(obj_perm->getOwner()))
-							mIsMuted = true;
-					}
-				}
-			}
-		}
-		
-		mNeedsMuteCheck = false;
-	}
-}
-
-F64 LLViewerMediaImpl::getApproximateTextureInterest()
-{
-	F64 result = 0.0f;
-	
-	if(mMediaSource)
-	{
-		result = mMediaSource->getFullWidth();
-		result *= mMediaSource->getFullHeight();
-	}
-	else
-	{
-		// No media source is loaded -- all we have to go on is the texture size that has been set on the impl, if any.
-		result = mMediaWidth;
-		result *= mMediaHeight;
-	}
-
-	return result;
-}
-
-void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
-{
-	mUsedInUI = used_in_ui; 
-	
-	// HACK: Force elements used in UI to load right away.
-	// This fixes some issues where UI code that uses the browser instance doesn't expect it to be unloaded.
-	if(mUsedInUI && (mPriority == LLPluginClassMedia::PRIORITY_UNLOADED))
-	{
-		if(getVisible())
-		{
-			setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
-		}
-		else
-		{
-			setPriority(LLPluginClassMedia::PRIORITY_HIDDEN);
-		}
-
-		createMediaSource();
-	}
-};
-
-void LLViewerMediaImpl::setBackgroundColor(LLColor4 color)
-{
-	mBackgroundColor = color; 
-
-	if(mMediaSource)
-	{
-		mMediaSource->setBackgroundColor(mBackgroundColor);
-	}
-};
-
-F64 LLViewerMediaImpl::getCPUUsage() const
-{
-	F64 result = 0.0f;
-	
-	if(mMediaSource)
-	{
-		result = mMediaSource->getCPUUsage();
-	}
-	
-	return result;
-}
-
-void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
-{
-	if(mPriority != priority)
-	{
-		LL_DEBUGS("PluginPriority")
-			<< "changing priority of media id " << mTextureId
-			<< " from " << LLPluginClassMedia::priorityToString(mPriority)
-			<< " to " << LLPluginClassMedia::priorityToString(priority)
-			<< LL_ENDL;
-	}
-	
-	mPriority = priority;
-	
-	if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
-	{
-		if(mMediaSource)
-		{
-			// Need to unload the media source
-			
-			// First, save off previous media state
-			mPreviousMediaState = mMediaSource->getStatus();
-			mPreviousMediaTime = mMediaSource->getCurrentTime();
-			
-			destroyMediaSource();
-		}
-	}
-
-	if(mMediaSource)
-	{
-		mMediaSource->setPriority(mPriority);
-	}
-	
-	// NOTE: loading (or reloading) media sources whose priority has risen above PRIORITY_UNLOADED is done in update().
-}
-
-void LLViewerMediaImpl::setLowPrioritySizeLimit(int size)
-{
-	if(mMediaSource)
-	{
-		mMediaSource->setLowPrioritySizeLimit(size);
-	}
-}
-
-void LLViewerMediaImpl::setNavState(EMediaNavState state)
-{
-	mMediaNavState = state;
-	
-	switch (state) 
-	{
-		case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break;
-		case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break;
-		case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break;
-		case MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS" << llendl; break;
-		case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
-		case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS" << llendl; break;
-		case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break;
-		case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break;
-		case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break;
-		case MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
-	}
-}
-
-void LLViewerMediaImpl::setNavigateSuspended(bool suspend)
-{
-	if(mNavigateSuspended != suspend)
-	{
-		mNavigateSuspended = suspend;
-		if(!suspend)
-		{
-			// We're coming out of suspend.  If someone tried to do a navigate while suspended, do one now instead.
-			if(mNavigateSuspendedDeferred)
-			{
-				mNavigateSuspendedDeferred = false;
-				navigateInternal();
-			}
-		}
-	}
-}
-
-void LLViewerMediaImpl::cancelMimeTypeProbe()
-{
-	if(mMimeTypeProbe != NULL)
-	{
-		// There doesn't seem to be a way to actually cancel an outstanding request.
-		// Simulate it by telling the LLMimeDiscoveryResponder not to write back any results.
-		mMimeTypeProbe->cancelRequest();
-		
-		// The above should already have set mMimeTypeProbe to NULL.
-		if(mMimeTypeProbe != NULL)
-		{
-			llerrs << "internal error: mMimeTypeProbe is not NULL after cancelling request." << llendl;
-		}
-	}
-}
-
-void LLViewerMediaImpl::addObject(LLVOVolume* obj) 
-{
-	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
-	for(; iter != mObjectList.end() ; ++iter)
-	{
-		if(*iter == obj)
-		{
-			return ; //already in the list.
-		}
-	}
-
-	mObjectList.push_back(obj) ;
-	mNeedsMuteCheck = true;
-}
-	
-void LLViewerMediaImpl::removeObject(LLVOVolume* obj) 
-{
-	mObjectList.remove(obj) ;	
-	mNeedsMuteCheck = true;
-}
-	
-const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const 
-{
-	return &mObjectList ;
-}
-
-LLVOVolume *LLViewerMediaImpl::getSomeObject()
-{
-	LLVOVolume *result = NULL;
-	
-	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
-	if(iter != mObjectList.end())
-	{
-		result = *iter;
-	}
-	
-	return result;
-}
-
-void LLViewerMediaImpl::setTextureID(LLUUID id)
-{
-	if(id != mTextureId)
-	{
-		if(mTextureId.notNull())
-		{
-			// Remove this item's entry from the map
-			sViewerMediaTextureIDMap.erase(mTextureId);
-		}
-		
-		if(id.notNull())
-		{
-			sViewerMediaTextureIDMap.insert(LLViewerMedia::impl_id_map::value_type(id, this));
-		}
-		
-		mTextureId = id;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaImpl::isAutoPlayable() const
-{
-	return (mMediaAutoPlay && 
-			gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
-			gSavedSettings.getBOOL("MediaTentativeAutoPlay"));
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaImpl::shouldShowBasedOnClass() const
-{
-	// If this is parcel media or in the UI, return true always
-	if (getUsedInUI() || isParcelMedia()) return true;
-	
-	bool attached_to_another_avatar = isAttachedToAnotherAvatar();
-	bool inside_parcel = isInAgentParcel();
-	
-	//	llinfos << " hasFocus = " << hasFocus() <<
-	//	" others = " << (attached_to_another_avatar && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING)) <<
-	//	" within = " << (inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING)) <<
-	//	" outside = " << (!inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING)) << llendl;
-	
-	// If it has focus, we should show it
-	// This is incorrect, and causes EXT-6750 (disabled attachment media still plays)
-//	if (hasFocus())
-//		return true;
-	
-	// If it is attached to an avatar and the pref is off, we shouldn't show it
-	if (attached_to_another_avatar)
-		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING);
-	
-	if (inside_parcel)
-		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING);
-	else 
-		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaImpl::isAttachedToAnotherAvatar() const
-{
-	bool result = false;
-	
-	std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
-	std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
-	for ( ; iter != end; iter++)
-	{
-		if (isObjectAttachedToAnotherAvatar(*iter))
-		{
-			result = true;
-			break;
-		}
-	}
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-//static
-bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj)
-{
-	bool result = false;
-	LLXform *xform = obj;
-	// Walk up parent chain
-	while (NULL != xform)
-	{
-		LLViewerObject *object = dynamic_cast<LLViewerObject*> (xform);
-		if (NULL != object)
-		{
-			LLVOAvatar *avatar = object->asAvatar();
-			if ((NULL != avatar) && (avatar != gAgentAvatarp))
-			{
-				result = true;
-				break;
-			}
-		}
-		xform = xform->getParent();
-	}
-	return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-bool LLViewerMediaImpl::isInAgentParcel() const
-{
-	bool result = false;
-	
-	std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
-	std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
-	for ( ; iter != end; iter++)
-	{
-		LLVOVolume *object = *iter;
-		if (LLViewerMediaImpl::isObjectInAgentParcel(object))
-		{
-			result = true;
-			break;
-		}
-	}
-	return result;
-}
-
-LLNotificationPtr LLViewerMediaImpl::getCurrentNotification() const
-{
-	return mNotification;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-// static
-bool LLViewerMediaImpl::isObjectInAgentParcel(LLVOVolume *obj)
-{
-	return (LLViewerParcelMgr::getInstance()->inAgentParcel(obj->getPositionGlobal()));
-}
+/**
+ * @file llviewermedia.cpp
+ * @brief Client interface to the media engine
+ *
+ * $LicenseInfo:firstyear=2007&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 "llagent.h"
+#include "llagentcamera.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llmimetypes.h"
+#include "llmediaentry.h"
+#include "llversioninfo.h"
+#include "llviewercontrol.h"
+#include "llviewertexture.h"
+#include "llviewerparcelmedia.h"
+#include "llviewerparcelmgr.h"
+#include "llviewertexturelist.h"
+#include "llvovolume.h"
+#include "llpluginclassmedia.h"
+#include "llplugincookiestore.h"
+#include "llviewerwindow.h"
+#include "llfocusmgr.h"
+#include "llcallbacklist.h"
+#include "llparcel.h"
+#include "llaudioengine.h"  // for gAudiop
+#include "llurldispatcher.h"
+#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llviewerregion.h"
+#include "llwebsharing.h"	// For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
+#include "llfilepicker.h"
+#include "llnotifications.h"
+#include "lldir.h"
+#include "lldiriterator.h"
+#include "llevent.h"		// LLSimpleListener
+#include "llnotificationsutil.h"
+#include "lluuid.h"
+#include "llkeyboard.h"
+#include "llmutelist.h"
+#include "llpanelprofile.h"
+#include "llappviewer.h"
+#include "lllogininstance.h" 
+//#include "llfirstuse.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.
+
+#include <boost/bind.hpp>	// for SkinFolder listener
+#include <boost/signals2.hpp>
+
+/*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable";
+/*static*/ const char* LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING = "MediaShowOnOthers";
+/*static*/ const char* LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING = "MediaShowWithinParcel";
+/*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel";
+
+
+// Move this to its own file.
+
+LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter()
+{
+	observerListType::iterator iter = mObservers.begin();
+
+	while( iter != mObservers.end() )
+	{
+		LLViewerMediaObserver *self = *iter;
+		iter++;
+		remObserver(self);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer )
+{
+	if ( ! observer )
+		return false;
+
+	if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() )
+		return false;
+
+	mObservers.push_back( observer );
+	observer->mEmitters.push_back( this );
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer )
+{
+	if ( ! observer )
+		return false;
+
+	mObservers.remove( observer );
+	observer->mEmitters.remove(this);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLViewerMediaObserver::EMediaEvent event )
+{
+	// Broadcast the event to any observers.
+	observerListType::iterator iter = mObservers.begin();
+	while( iter != mObservers.end() )
+	{
+		LLViewerMediaObserver *self = *iter;
+		++iter;
+		self->handleMediaEvent( media, event );
+	}
+}
+
+// Move this to its own file.
+LLViewerMediaObserver::~LLViewerMediaObserver()
+{
+	std::list<LLViewerMediaEventEmitter *>::iterator iter = mEmitters.begin();
+
+	while( iter != mEmitters.end() )
+	{
+		LLViewerMediaEventEmitter *self = *iter;
+		iter++;
+		self->remObserver( this );
+	}
+}
+
+
+// Move this to its own file.
+// helper class that tries to download a URL from a web site and calls a method
+// on the Panel Land Media and to discover the MIME type
+class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
+{
+LOG_CLASS(LLMimeDiscoveryResponder);
+public:
+	LLMimeDiscoveryResponder( viewer_media_t media_impl)
+		: mMediaImpl(media_impl),
+		  mInitialized(false)
+	{
+		if(mMediaImpl->mMimeTypeProbe != NULL)
+		{
+			llerrs << "impl already has an outstanding responder" << llendl;
+		}
+		
+		mMediaImpl->mMimeTypeProbe = this;
+	}
+
+	~LLMimeDiscoveryResponder()
+	{
+		disconnectOwner();
+	}
+
+	virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	{
+		std::string media_type = content["content-type"].asString();
+		std::string::size_type idx1 = media_type.find_first_of(";");
+		std::string mime_type = media_type.substr(0, idx1);
+
+		lldebugs << "status is " << status << ", media type \"" << media_type << "\"" << llendl;
+		
+		// 2xx status codes indicate success.
+		// Most 4xx status codes are successful enough for our purposes.
+		// 499 is the error code for host not found, timeout, etc.
+		// 500 means "Internal Server error" but we decided it's okay to 
+		//     accept this and go past it in the MIME type probe
+		// 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com
+		// 499 is a code specifc to join.secondlife.com (????) apparently safe to ignore
+//		if(	((status >= 200) && (status < 300))	||
+//			((status >= 400) && (status < 499))	|| 
+//			(status == 500) ||
+//			(status == 302) ||
+//			(status == 499) 
+//			)
+		// We now no longer check the error code returned from the probe.
+		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
+		if(1)
+		{
+			// The probe was successful.
+			if(mime_type.empty())
+			{
+				// Some sites don't return any content-type header at all.
+				// Treat an empty mime type as text/html.
+				mime_type = "text/html";
+			}
+			
+			completeAny(status, mime_type);
+		}
+		else
+		{
+			llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
+		
+			if(mMediaImpl)
+			{
+				mMediaImpl->mMediaSourceFailed = true;
+			}
+		}
+
+	}
+
+	void completeAny(U32 status, const std::string& mime_type)
+	{
+		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
+		// Make a local copy so we can call loadURI() afterwards.
+		LLViewerMediaImpl *impl = mMediaImpl;
+		
+		if(impl && !mInitialized && ! mime_type.empty())
+		{
+			if(impl->initializeMedia(mime_type))
+			{
+				mInitialized = true;
+				impl->loadURI();
+				disconnectOwner();
+			}
+		}
+	}
+	
+	void cancelRequest()
+	{
+		disconnectOwner();
+	}
+	
+private:
+	void disconnectOwner()
+	{
+		if(mMediaImpl)
+		{
+			if(mMediaImpl->mMimeTypeProbe != this)
+			{
+				llerrs << "internal error: mMediaImpl->mMimeTypeProbe != this" << llendl;
+			}
+
+			mMediaImpl->mMimeTypeProbe = NULL;
+		}
+		mMediaImpl = NULL;
+	}
+	
+	
+public:
+		LLViewerMediaImpl *mMediaImpl;
+		bool mInitialized;
+};
+
+class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
+{
+LOG_CLASS(LLViewerMediaOpenIDResponder);
+public:
+	LLViewerMediaOpenIDResponder( )
+	{
+	}
+
+	~LLViewerMediaOpenIDResponder()
+	{
+	}
+
+	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	{
+		LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
+		LL_DEBUGS("MediaAuth") << content << LL_ENDL;
+		std::string cookie = content["set-cookie"].asString();
+		
+		LLViewerMedia::openIDCookieResponse(cookie);
+	}
+
+	/* virtual */ void completedRaw(
+		U32 status,
+		const std::string& reason,
+		const LLChannelDescriptors& channels,
+		const LLIOPipe::buffer_ptr_t& buffer)
+	{
+		// This is just here to disable the default behavior (attempting to parse the response as llsd).
+		// We don't care about the content of the response, only the set-cookie header.
+	}
+
+};
+
+class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder
+{
+LOG_CLASS(LLViewerMediaWebProfileResponder);
+public:
+	LLViewerMediaWebProfileResponder(std::string host)
+	{
+		mHost = host;
+	}
+
+	~LLViewerMediaWebProfileResponder()
+	{
+	}
+
+	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	{
+		LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
+		LL_WARNS("MediaAuth") << content << LL_ENDL;
+
+		std::string cookie = content["set-cookie"].asString();
+
+		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
+	}
+
+	 void completedRaw(
+		U32 status,
+		const std::string& reason,
+		const LLChannelDescriptors& channels,
+		const LLIOPipe::buffer_ptr_t& buffer)
+	{
+		// This is just here to disable the default behavior (attempting to parse the response as llsd).
+		// We don't care about the content of the response, only the set-cookie header.
+	}
+
+	std::string mHost;
+};
+
+
+LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
+LLURL LLViewerMedia::sOpenIDURL;
+std::string LLViewerMedia::sOpenIDCookie;
+LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL;
+static LLViewerMedia::impl_list sViewerMediaImplList;
+static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
+static LLTimer sMediaCreateTimer;
+static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
+static F32 sGlobalVolume = 1.0f;
+static F64 sLowestLoadableImplInterest = 0.0f;
+static bool sAnyMediaShowing = false;
+static boost::signals2::connection sTeleportFinishConnection;
+static std::string sUpdatedCookies;
+static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt";
+
+//////////////////////////////////////////////////////////////////////////////////////////
+static void add_media_impl(LLViewerMediaImpl* media)
+{
+	sViewerMediaImplList.push_back(media);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+static void remove_media_impl(LLViewerMediaImpl* media)
+{
+	LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
+	LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
+	
+	for(; iter != end; iter++)
+	{
+		if(media == *iter)
+		{
+			sViewerMediaImplList.erase(iter);
+			return;
+		}
+	}
+}
+
+class LLViewerMediaMuteListObserver : public LLMuteListObserver
+{
+	/* virtual */ void onChange()  { LLViewerMedia::muteListChanged();}
+};
+
+static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
+static bool sViewerMediaMuteListObserverInitialized = false;
+static bool sInWorldMediaDisabled = false;
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// LLViewerMedia
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+viewer_media_t LLViewerMedia::newMediaImpl(
+											 const LLUUID& texture_id,
+											 S32 media_width, 
+											 S32 media_height, 
+											 U8 media_auto_scale,
+											 U8 media_loop)
+{
+	LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id);
+	if(media_impl == NULL || texture_id.isNull())
+	{
+		// Create the media impl
+		media_impl = new LLViewerMediaImpl(texture_id, media_width, media_height, media_auto_scale, media_loop);
+	}
+	else
+	{
+		media_impl->unload();
+		media_impl->setTextureID(texture_id);
+		media_impl->mMediaWidth = media_width;
+		media_impl->mMediaHeight = media_height;
+		media_impl->mMediaAutoScale = media_auto_scale;
+		media_impl->mMediaLoop = media_loop;
+	}
+
+	return media_impl;
+}
+
+viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self)
+{	
+	// Try to find media with the same media ID
+	viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
+	
+	lldebugs << "called, current URL is \"" << media_entry->getCurrentURL() 
+			<< "\", previous URL is \"" << previous_url 
+			<< "\", update_from_self is " << (update_from_self?"true":"false")
+			<< llendl;
+			
+	bool was_loaded = false;
+	bool needs_navigate = false;
+	
+	if(media_impl)
+	{	
+		was_loaded = media_impl->hasMedia();
+		
+		media_impl->setHomeURL(media_entry->getHomeURL());
+		
+		media_impl->mMediaAutoScale = media_entry->getAutoScale();
+		media_impl->mMediaLoop = media_entry->getAutoLoop();
+		media_impl->mMediaWidth = media_entry->getWidthPixels();
+		media_impl->mMediaHeight = media_entry->getHeightPixels();
+		media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
+		media_impl->mMediaEntryURL = media_entry->getCurrentURL();
+		if (media_impl->mMediaSource)
+		{
+			media_impl->mMediaSource->setAutoScale(media_impl->mMediaAutoScale);
+			media_impl->mMediaSource->setLoop(media_impl->mMediaLoop);
+			media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
+		}
+		
+		bool url_changed = (media_impl->mMediaEntryURL != previous_url);
+		if(media_impl->mMediaEntryURL.empty())
+		{
+			if(url_changed)
+			{
+				// The current media URL is now empty.  Unload the media source.
+				media_impl->unload();
+			
+				lldebugs << "Unloading media instance (new current URL is empty)." << llendl;
+			}
+		}
+		else
+		{
+			// The current media URL is not empty.
+			// If (the media was already loaded OR the media was set to autoplay) AND this update didn't come from this agent,
+			// do a navigate.
+			bool auto_play = media_impl->isAutoPlayable();			
+			if((was_loaded || auto_play) && !update_from_self)
+			{
+				needs_navigate = url_changed;
+			}
+			
+			lldebugs << "was_loaded is " << (was_loaded?"true":"false") 
+					<< ", auto_play is " << (auto_play?"true":"false") 
+					<< ", needs_navigate is " << (needs_navigate?"true":"false") << llendl;
+		}
+	}
+	else
+	{
+		media_impl = newMediaImpl(
+			media_entry->getMediaID(), 
+			media_entry->getWidthPixels(),
+			media_entry->getHeightPixels(), 
+			media_entry->getAutoScale(), 
+			media_entry->getAutoLoop());
+		
+		media_impl->setHomeURL(media_entry->getHomeURL());
+		media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
+		media_impl->mMediaEntryURL = media_entry->getCurrentURL();
+		if(media_impl->isAutoPlayable())
+		{
+			needs_navigate = true;
+		}
+	}
+	
+	if(media_impl)
+	{
+		if(needs_navigate)
+		{
+			media_impl->navigateTo(media_impl->mMediaEntryURL, "", true, true);
+			lldebugs << "navigating to URL " << media_impl->mMediaEntryURL << llendl;
+		}
+		else if(!media_impl->mMediaURL.empty() && (media_impl->mMediaURL != media_impl->mMediaEntryURL))
+		{
+			// If we already have a non-empty media URL set and we aren't doing a navigate, update the media URL to match the media entry.
+			media_impl->mMediaURL = media_impl->mMediaEntryURL;
+
+			// If this causes a navigate at some point (such as after a reload), it should be considered server-driven so it isn't broadcast.
+			media_impl->mNavigateServerRequest = true;
+
+			lldebugs << "updating URL in the media impl to " << media_impl->mMediaEntryURL << llendl;
+		}
+	}
+	
+	return media_impl;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)
+{
+	LLViewerMediaImpl* result = NULL;
+	
+	// Look up the texture ID in the texture id->impl map.
+	impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id);
+	if(iter != sViewerMediaTextureIDMap.end())
+	{
+		result = iter->second;
+	}
+
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+std::string LLViewerMedia::getCurrentUserAgent()
+{
+	// Don't use user-visible string to avoid 
+	// punctuation and strange characters.
+	std::string skin_name = gSavedSettings.getString("SkinCurrent");
+
+	// Just in case we need to check browser differences in A/B test
+	// builds.
+	std::string channel = LLVersionInfo::getChannel();
+
+	// append our magic version number string to the browser user agent id
+	// See the HTTP 1.0 and 1.1 specifications for allowed formats:
+	// http://www.ietf.org/rfc/rfc1945.txt section 10.15
+	// http://www.ietf.org/rfc/rfc2068.txt section 3.8
+	// This was also helpful:
+	// http://www.mozilla.org/build/revised-user-agent-strings.html
+	std::ostringstream codec;
+	codec << "SecondLife/";
+	codec << LLVersionInfo::getVersion();
+	codec << " (" << channel << "; " << skin_name << " skin)";
+	llinfos << codec.str() << llendl;
+	
+	return codec.str();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::updateBrowserUserAgent()
+{
+	std::string user_agent = getCurrentUserAgent();
+	
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+
+	for(; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser())
+		{
+			pimpl->mMediaSource->setBrowserUserAgent(user_agent);
+		}
+	}
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::handleSkinCurrentChanged(const LLSD& /*newvalue*/)
+{
+	// gSavedSettings is already updated when this function is called.
+	updateBrowserUserAgent();
+	return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id)
+{
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+
+	for(; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if(pimpl->getMediaTextureID() == texture_id)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setVolume(F32 volume)
+{
+	if(volume != sGlobalVolume)
+	{
+		sGlobalVolume = volume;
+		impl_list::iterator iter = sViewerMediaImplList.begin();
+		impl_list::iterator end = sViewerMediaImplList.end();
+
+		for(; iter != end; iter++)
+		{
+			LLViewerMediaImpl* pimpl = *iter;
+			pimpl->updateVolume();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+F32 LLViewerMedia::getVolume()
+{
+	return sGlobalVolume;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::muteListChanged()
+{
+	// When the mute list changes, we need to check mute status on all impls.
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+
+	for(; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		pimpl->mNeedsMuteCheck = true;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
+{
+	sInWorldMediaDisabled = disabled;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::getInWorldMediaDisabled()
+{
+	return sInWorldMediaDisabled;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)
+{
+	bool result = false;
+	
+	if (NULL == object)
+	{
+		result = false;
+	}
+	// Focused?  Then it is interesting!
+	else if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == object->getID())
+	{
+		result = true;
+	}
+	// Selected?  Then it is interesting!
+	// XXX Sadly, 'contains()' doesn't take a const :(
+	else if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(object)))
+	{
+		result = true;
+	}
+	else 
+	{
+		lldebugs << "object interest = " << object_interest << ", lowest loadable = " << sLowestLoadableImplInterest << llendl;
+		if(object_interest >= sLowestLoadableImplInterest)
+			result = true;
+	}
+	
+	return result;
+}
+
+LLViewerMedia::impl_list &LLViewerMedia::getPriorityList()
+{
+	return sViewerMediaImplList;
+}
+
+// This is the predicate function used to sort sViewerMediaImplList by priority.
+bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+{
+	if(i1->isForcedUnloaded() && !i2->isForcedUnloaded())
+	{
+		// Muted or failed items always go to the end of the list, period.
+		return false;
+	}
+	else if(i2->isForcedUnloaded() && !i1->isForcedUnloaded())
+	{
+		// Muted or failed items always go to the end of the list, period.
+		return true;
+	}
+	else if(i1->hasFocus())
+	{
+		// The item with user focus always comes to the front of the list, period.
+		return true;
+	}
+	else if(i2->hasFocus())
+	{
+		// The item with user focus always comes to the front of the list, period.
+		return false;
+	}
+	else if(i1->isParcelMedia())
+	{
+		// The parcel media impl sorts above all other inworld media, unless one has focus.
+		return true;
+	}
+	else if(i2->isParcelMedia())
+	{
+		// The parcel media impl sorts above all other inworld media, unless one has focus.
+		return false;
+	}
+	else if(i1->getUsedInUI() && !i2->getUsedInUI())
+	{
+		// i1 is a UI element, i2 is not.  This makes i1 "less than" i2, so it sorts earlier in our list.
+		return true;
+	}
+	else if(i2->getUsedInUI() && !i1->getUsedInUI())
+	{
+		// i2 is a UI element, i1 is not.  This makes i2 "less than" i1, so it sorts earlier in our list.
+		return false;
+	}
+	else if(i1->isPlayable() && !i2->isPlayable())
+	{
+		// Playable items sort above ones that wouldn't play even if they got high enough priority
+		return true;
+	}
+	else if(!i1->isPlayable() && i2->isPlayable())
+	{
+		// Playable items sort above ones that wouldn't play even if they got high enough priority
+		return false;
+	}
+	else if(i1->getInterest() == i2->getInterest())
+	{
+		// Generally this will mean both objects have zero interest.  In this case, sort on distance.
+		return (i1->getProximityDistance() < i2->getProximityDistance());
+	}
+	else
+	{
+		// The object with the larger interest value should be earlier in the list, so we reverse the sense of the comparison here.
+		return (i1->getInterest() > i2->getInterest());
+	}
+}
+
+static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+{
+	if(i1->getProximityDistance() < i2->getProximityDistance())
+	{
+		return true;
+	}
+	else if(i1->getProximityDistance() > i2->getProximityDistance())
+	{
+		return false;
+	}
+	else
+	{
+		// Both objects have the same distance.  This most likely means they're two faces of the same object.
+		// They may also be faces on different objects with exactly the same distance (like HUD objects).
+		// We don't actually care what the sort order is for this case, as long as it's stable and doesn't change when you enable/disable media.
+		// Comparing the impl pointers gives a completely arbitrary ordering, but it will be stable.
+		return (i1 < i2);
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE("Update Media");
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::updateMedia(void *dummy_arg)
+{
+	LLFastTimer t1(FTM_MEDIA_UPDATE);
+	
+	// Enable/disable the plugin read thread
+	LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
+	
+	// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
+	createSpareBrowserMediaSource();
+	
+	sAnyMediaShowing = false;
+	sUpdatedCookies = getCookieStore()->getChangedCookies();
+	if(!sUpdatedCookies.empty())
+	{
+		lldebugs << "updated cookies will be sent to all loaded plugins: " << llendl;
+		lldebugs << sUpdatedCookies << llendl;
+	}
+	
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+
+	for(; iter != end;)
+	{
+		LLViewerMediaImpl* pimpl = *iter++;
+		pimpl->update();
+		pimpl->calculateInterest();
+	}
+	
+	// Let the spare media source actually launch
+	if(sSpareBrowserMediaSource)
+	{
+		sSpareBrowserMediaSource->idle();
+	}
+		
+	// Sort the static instance list using our interest criteria
+	sViewerMediaImplList.sort(priorityComparitor);
+
+	// Go through the list again and adjust according to priority.
+	iter = sViewerMediaImplList.begin();
+	end = sViewerMediaImplList.end();
+	
+	F64 total_cpu = 0.0f;
+	int impl_count_total = 0;
+	int impl_count_interest_low = 0;
+	int impl_count_interest_normal = 0;
+	
+	std::vector<LLViewerMediaImpl*> proximity_order;
+	
+	bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia");
+	bool inworld_audio_enabled = gSavedSettings.getBOOL("AudioStreamingMusic");
+	U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal");
+	U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal");
+	U32 max_low = gSavedSettings.getU32("PluginInstancesLow");
+	F32 max_cpu = gSavedSettings.getF32("PluginInstancesCPULimit");
+	// Setting max_cpu to 0.0 disables CPU usage checking.
+	bool check_cpu_usage = (max_cpu != 0.0f);
+	
+	LLViewerMediaImpl* lowest_interest_loadable = NULL;
+	
+	// Notes on tweakable params:
+	// max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded.
+	// If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow.
+	
+	for(; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		
+		LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+
+		if(pimpl->isForcedUnloaded() || (impl_count_total >= (int)max_instances))
+		{
+			// Never load muted or failed impls.
+			// Hard limit on the number of instances that will be loaded at one time
+			new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
+		}
+		else if(!pimpl->getVisible())
+		{
+			new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+		}
+		else if(pimpl->hasFocus())
+		{
+			new_priority = LLPluginClassMedia::PRIORITY_HIGH;
+			impl_count_interest_normal++;	// count this against the count of "normal" instances for priority purposes
+		}
+		else if(pimpl->getUsedInUI())
+		{
+			new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+			impl_count_interest_normal++;
+		}
+		else if(pimpl->isParcelMedia())
+		{
+			new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+			impl_count_interest_normal++;
+		}
+		else
+		{
+			// Look at interest and CPU usage for instances that aren't in any of the above states.
+			
+			// Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture,
+			// turn it down to low instead of normal.  This may downsample for plugins that support it.
+			bool media_is_small = false;
+			F64 approximate_interest = pimpl->getApproximateTextureInterest();
+			if(approximate_interest == 0.0f)
+			{
+				// this media has no current size, which probably means it's not loaded.
+				media_is_small = true;
+			}
+			else if(pimpl->getInterest() < (approximate_interest / 4))
+			{
+				media_is_small = true;
+			}
+			
+			if(pimpl->getInterest() == 0.0f)
+			{
+				// This media is completely invisible, due to being outside the view frustrum or out of range.
+				new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+			}
+			else if(check_cpu_usage && (total_cpu > max_cpu))
+			{
+				// Higher priority plugins have already used up the CPU budget.  Set remaining ones to slideshow priority.
+				new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
+			}
+			else if((impl_count_interest_normal < (int)max_normal) && !media_is_small)
+			{
+				// Up to max_normal inworld get normal priority
+				new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+				impl_count_interest_normal++;
+			}
+			else if (impl_count_interest_low + impl_count_interest_normal < (int)max_low + (int)max_normal)
+			{
+				// The next max_low inworld get turned down
+				new_priority = LLPluginClassMedia::PRIORITY_LOW;
+				impl_count_interest_low++;
+				
+				// Set the low priority size for downsampling to approximately the size the texture is displayed at.
+				{
+					F32 approximate_interest_dimension = fsqrtf(pimpl->getInterest());
+					
+					pimpl->setLowPrioritySizeLimit(llround(approximate_interest_dimension));
+				}
+			}
+			else
+			{
+				// Any additional impls (up to max_instances) get very infrequent time
+				new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
+			}
+		}
+		
+		if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED))
+		{
+			// This is a loadable inworld impl -- the last one in the list in this class defines the lowest loadable interest.
+			lowest_interest_loadable = pimpl;
+			
+			impl_count_total++;
+		}
+
+		// Overrides if the window is minimized or we lost focus (taking care
+		// not to accidentally "raise" the priority either)
+		if (!gViewerWindow->getActive() /* viewer window minimized? */ 
+			&& new_priority > LLPluginClassMedia::PRIORITY_HIDDEN)
+		{
+			new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+		}
+		else if (!gFocusMgr.getAppHasFocus() /* viewer window lost focus? */
+				 && new_priority > LLPluginClassMedia::PRIORITY_LOW)
+		{
+			new_priority = LLPluginClassMedia::PRIORITY_LOW;
+		}
+		
+		if(!inworld_media_enabled)
+		{
+			// If inworld media is locked out, force all inworld media to stay unloaded.
+			if(!pimpl->getUsedInUI())
+			{
+				new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
+			}
+		}
+		// update the audio stream here as well
+		if( !inworld_audio_enabled)
+		{
+			if(LLViewerMedia::isParcelAudioPlaying() && gAudiop && LLViewerMedia::hasParcelAudio())
+			{
+				gAudiop->stopInternetStream();
+			}
+		}
+		pimpl->setPriority(new_priority);
+		
+		if(pimpl->getUsedInUI())
+		{
+			// Any impls used in the UI should not be in the proximity list.
+			pimpl->mProximity = -1;
+		}
+		else
+		{
+			proximity_order.push_back(pimpl);
+		}
+
+		total_cpu += pimpl->getCPUUsage();
+		
+		if (!pimpl->getUsedInUI() && pimpl->hasMedia())
+		{
+			sAnyMediaShowing = true;
+		}
+
+	}
+
+	// Re-calculate this every time.
+	sLowestLoadableImplInterest	= 0.0f;
+
+	// Only do this calculation if we've hit the impl count limit -- up until that point we always need to load media data.
+	if(lowest_interest_loadable && (impl_count_total >= (int)max_instances))
+	{
+		// Get the interest value of this impl's object for use by isInterestingEnough
+		LLVOVolume *object = lowest_interest_loadable->getSomeObject();
+		if(object)
+		{
+			// NOTE: Don't use getMediaInterest() here.  We want the pixel area, not the total media interest,
+			// 		so that we match up with the calculation done in LLMediaDataClient.
+			sLowestLoadableImplInterest = object->getPixelArea();
+		}
+	}
+	
+	if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug"))
+	{
+		// Give impls the same ordering as the priority list
+		// they're already in the right order for this.
+	}
+	else
+	{
+		// Use a distance-based sort for proximity values.  
+		std::stable_sort(proximity_order.begin(), proximity_order.end(), proximity_comparitor);
+	}
+
+	// Transfer the proximity order to the proximity fields in the objects.
+	for(int i = 0; i < (int)proximity_order.size(); i++)
+	{
+		proximity_order[i]->mProximity = i;
+	}
+	
+	LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::isAnyMediaShowing()
+{
+	return sAnyMediaShowing;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setAllMediaEnabled(bool val)
+{
+	// Set "tentative" autoplay first.  We need to do this here or else
+	// re-enabling won't start up the media below.
+	gSavedSettings.setBOOL("MediaTentativeAutoPlay", val);
+	
+	// Then 
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+	
+	for(; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if (!pimpl->getUsedInUI())
+		{
+			pimpl->setDisabled(!val);
+		}
+	}
+	
+	// Also do Parcel Media and Parcel Audio
+	if (val)
+	{
+		if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
+		{	
+			LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+		}
+		
+		if (gSavedSettings.getBOOL("AudioStreamingMusic") &&
+			!LLViewerMedia::isParcelAudioPlaying() &&
+			gAudiop && 
+			LLViewerMedia::hasParcelAudio())
+		{
+			gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
+		}
+	}
+	else {
+		// This actually unloads the impl, as opposed to "stop"ping the media
+		LLViewerParcelMedia::stop();
+		if (gAudiop) gAudiop->stopInternetStream();
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::isParcelMediaPlaying()
+{
+	return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::isParcelAudioPlaying()
+{
+	return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());
+}
+
+void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response)
+{
+	LLViewerMediaImpl *impl = LLViewerMedia::getMediaImplFromTextureID(notification["payload"]["media_id"]);
+	if(impl)
+	{
+		LLPluginClassMedia* media = impl->getMediaPlugin();
+		if(media)
+		{
+			if (response["ok"])
+			{
+				media->sendAuthResponse(true, response["username"], response["password"]);
+			}
+			else
+			{
+				media->sendAuthResponse(false, "", "");
+			}
+		}
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::clearAllCookies()
+{
+	// Clear all cookies for all plugins
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+	for (; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if(pimpl->mMediaSource)
+		{
+			pimpl->mMediaSource->clear_cookies();
+		}
+	}
+	
+	// Clear all cookies from the cookie store
+	getCookieStore()->setAllCookies("");
+
+	// FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly.
+	// It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded.
+	// Until such time as we can centralize cookie storage, the following hack should cover these cases:
+	
+	// HACK: Look for cookie files in all possible places and delete them.
+	// NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file)
+	
+	// Places that cookie files can be:
+	// <getOSUserAppDir>/browser_profile/cookies
+	// <getOSUserAppDir>/first_last/browser_profile/cookies  (note that there may be any number of these!)
+	// <getOSUserAppDir>/first_last/plugin_cookies.txt  (note that there may be any number of these!)
+	
+	std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter();
+	std::string target;
+	std::string filename;
+	
+	lldebugs << "base dir = " << base_dir << llendl;
+
+	// The non-logged-in version is easy
+	target = base_dir;
+	target += "browser_profile";
+	target += gDirUtilp->getDirDelimiter();
+	target += "cookies";
+	lldebugs << "target = " << target << llendl;
+	if(LLFile::isfile(target))
+	{
+		LLFile::remove(target);
+	}
+	
+	// the hard part: iterate over all user directories and delete the cookie file from each one
+	LLDirIterator dir_iter(base_dir, "*_*");
+	while (dir_iter.next(filename))
+	{
+		target = base_dir;
+		target += filename;
+		target += gDirUtilp->getDirDelimiter();
+		target += "browser_profile";
+		target += gDirUtilp->getDirDelimiter();
+		target += "cookies";
+		lldebugs << "target = " << target << llendl;
+		if(LLFile::isfile(target))
+		{	
+			LLFile::remove(target);
+		}
+		
+		// Other accounts may have new-style cookie files too -- delete them as well
+		target = base_dir;
+		target += filename;
+		target += gDirUtilp->getDirDelimiter();
+		target += PLUGIN_COOKIE_FILE_NAME;
+		lldebugs << "target = " << target << llendl;
+		if(LLFile::isfile(target))
+		{	
+			LLFile::remove(target);
+		}
+	}
+	
+	// If we have an OpenID cookie, re-add it to the cookie store.
+	setOpenIDCookie();
+}
+	
+/////////////////////////////////////////////////////////////////////////////////////////
+// static 
+void LLViewerMedia::clearAllCaches()
+{
+	// Clear all plugins' caches
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+	for (; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		pimpl->clearCache();
+	}
+}
+	
+/////////////////////////////////////////////////////////////////////////////////////////
+// static 
+void LLViewerMedia::setCookiesEnabled(bool enabled)
+{
+	// Set the "cookies enabled" flag for all loaded plugins
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+	for (; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if(pimpl->mMediaSource)
+		{
+			pimpl->mMediaSource->enable_cookies(enabled);
+		}
+	}
+}
+	
+/////////////////////////////////////////////////////////////////////////////////////////
+// static 
+void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int port)
+{
+	// Set the proxy config for all loaded plugins
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+	for (; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if(pimpl->mMediaSource)
+		{
+			pimpl->mMediaSource->proxy_setup(enable, host, port);
+		}
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static 
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+LLPluginCookieStore *LLViewerMedia::getCookieStore()
+{
+	if(sCookieStore == NULL)
+	{
+		sCookieStore = new LLPluginCookieStore;
+	}
+	
+	return sCookieStore;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::loadCookieFile()
+{
+	// build filename for each user
+	std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
+
+	if (resolved_filename.empty())
+	{
+		llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
+		return;
+	}
+	
+	// open the file for reading
+	llifstream file(resolved_filename);
+	if (!file.is_open())
+	{
+		llwarns << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << llendl;
+		return;
+	}
+	
+	getCookieStore()->readAllCookies(file, true);
+
+	file.close();
+	
+	// send the clear_cookies message to all loaded plugins
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+	for (; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if(pimpl->mMediaSource)
+		{
+			pimpl->mMediaSource->clear_cookies();
+		}
+	}
+	
+	// If we have an OpenID cookie, re-add it to the cookie store.
+	setOpenIDCookie();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::saveCookieFile()
+{
+	// build filename for each user
+	std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
+
+	if (resolved_filename.empty())
+	{
+		llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
+		return;
+	}
+
+	// open a file for writing
+	llofstream file (resolved_filename);
+	if (!file.is_open())
+	{
+		llwarns << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << llendl;
+		return;
+	}
+
+	getCookieStore()->writePersistentCookies(file);
+
+	file.close();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure)
+{
+	std::stringstream cookie;
+	
+	cookie << name << "=" << LLPluginCookieStore::quoteString(value);
+	
+	if(expires.notNull())
+	{
+		cookie << "; expires=" << expires.asRFC1123();
+	}
+	
+	cookie << "; domain=" << domain;
+
+	cookie << "; path=" << path;
+	
+	if(secure)
+	{
+		cookie << "; secure";
+	}
+	
+	getCookieStore()->setCookies(cookie.str());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure)
+{
+	// A session cookie just has a NULL date.
+	addCookie(name, value, domain, LLDate(), path, secure);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path )
+{
+	// To remove a cookie, add one with the same name, domain, and path that expires in the past.
+	
+	addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setOpenIDCookie()
+{
+	if(!sOpenIDCookie.empty())
+	{
+		// The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port]
+		// We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.
+		// We therefore do it here.
+		std::string authority = sOpenIDURL.mAuthority;
+		std::string::size_type host_start = authority.find('@'); 
+		if(host_start == std::string::npos)
+		{
+			// no username/password
+			host_start = 0;
+		}
+		else
+		{
+			// Hostname starts after the @. 
+			// (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.)
+			++host_start;
+		}
+		std::string::size_type host_end = authority.rfind(':'); 
+		if((host_end == std::string::npos) || (host_end < host_start))
+		{
+			// no port
+			host_end = authority.size();
+		}
+		
+		getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start));
+
+		// *HACK: Doing this here is nasty, find a better way.
+		LLWebSharing::instance().setOpenIDCookie(sOpenIDCookie);
+
+		// Do a web profile get so we can store the cookie 
+		LLSD headers = LLSD::emptyMap();
+		headers["Accept"] = "*/*";
+		headers["Cookie"] = sOpenIDCookie;
+		headers["User-Agent"] = getCurrentUserAgent();
+
+		std::string profile_url = getProfileURL("");
+		LLURL raw_profile_url( profile_url.c_str() );
+
+		LLHTTPClient::get(profile_url,  
+			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
+			headers);
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token)
+{
+	LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL;
+
+	// post the token to the url 
+	// the responder will need to extract the cookie(s).
+
+	// Save the OpenID URL for later -- we may need the host when adding the cookie.
+	sOpenIDURL.init(openid_url.c_str());
+	
+	// We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
+	sOpenIDCookie.clear();
+
+	LLSD headers = LLSD::emptyMap();
+	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
+	headers["Accept"] = "*/*";
+	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
+	headers["Content-Type"] = "application/x-www-form-urlencoded";
+
+	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
+	size_t size = openid_token.size();
+	U8 *data = new U8[size];
+	memcpy(data, openid_token.data(), size);
+
+	LLHTTPClient::postRaw( 
+		openid_url, 
+		data, 
+		size, 
+		new LLViewerMediaOpenIDResponder(),
+		headers);
+			
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::openIDCookieResponse(const std::string &cookie)
+{
+	LL_DEBUGS("MediaAuth") << "Cookie received: \"" << cookie << "\"" << LL_ENDL;
+	
+	sOpenIDCookie += cookie;
+
+	setOpenIDCookie();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
+{
+	if(uuid.empty())
+		return;
+		
+	for (impl_list::iterator iter = sViewerMediaImplList.begin(); iter != sViewerMediaImplList.end(); iter++)
+	{
+		if((*iter)->mMediaSource && (*iter)->mMediaSource->pluginSupportsMediaBrowser())
+		{
+			(*iter)->mMediaSource->proxyWindowOpened(target, uuid);
+		}
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::proxyWindowClosed(const std::string &uuid)
+{
+	if(uuid.empty())
+		return;
+
+	for (impl_list::iterator iter = sViewerMediaImplList.begin(); iter != sViewerMediaImplList.end(); iter++)
+	{
+		if((*iter)->mMediaSource && (*iter)->mMediaSource->pluginSupportsMediaBrowser())
+		{
+			(*iter)->mMediaSource->proxyWindowClosed(uuid);
+		}
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::createSpareBrowserMediaSource()
+{
+	// If we don't have a spare browser media source, create one.
+	// However, if PluginAttachDebuggerToPlugins is set then don't spawn a spare
+	// SLPlugin process in order to not be confused by an unrelated gdb terminal
+	// popping up at the moment we start a media plugin.
+	if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
+	{
+		// The null owner will keep the browser plugin from fully initializing 
+		// (specifically, it keeps LLPluginClassMedia from negotiating a size change, 
+		// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
+		sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() 
+{
+	LLPluginClassMedia* result = sSpareBrowserMediaSource;
+	sSpareBrowserMediaSource = NULL;
+	return result; 
+};
+
+bool LLViewerMedia::hasInWorldMedia()
+{
+	if (sInWorldMediaDisabled) return false;
+	impl_list::iterator iter = sViewerMediaImplList.begin();
+	impl_list::iterator end = sViewerMediaImplList.end();
+	// This should be quick, because there should be very few non-in-world-media impls
+	for (; iter != end; iter++)
+	{
+		LLViewerMediaImpl* pimpl = *iter;
+		if (!pimpl->getUsedInUI() && !pimpl->isParcelMedia())
+		{
+			// Found an in-world media impl
+			return true;
+		}
+	}
+	return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::hasParcelMedia()
+{
+	return !LLViewerParcelMedia::getURL().empty();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::hasParcelAudio()
+{
+	return !LLViewerMedia::getParcelAudioURL().empty();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+std::string LLViewerMedia::getParcelAudioURL()
+{
+	return LLViewerParcelMgr::getInstance()->getAgentParcel()->getMusicURL();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::initClass()
+{
+	gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);	
+	sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
+		setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::cleanupClass()
+{
+	gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
+	sTeleportFinishConnection.disconnect();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::onTeleportFinished()
+{
+	// On teleport, clear this setting (i.e. set it to true)
+	gSavedSettings.setBOOL("MediaTentativeAutoPlay", true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// LLViewerMediaImpl
+//////////////////////////////////////////////////////////////////////////////////////////
+LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id, 
+										  S32 media_width, 
+										  S32 media_height, 
+										  U8 media_auto_scale, 
+										  U8 media_loop)
+:	
+	mMediaSource( NULL ),
+	mMovieImageHasMips(false),
+	mMediaWidth(media_width),
+	mMediaHeight(media_height),
+	mMediaAutoScale(media_auto_scale),
+	mMediaLoop(media_loop),
+	mNeedsNewTexture(true),
+	mTextureUsedWidth(0),
+	mTextureUsedHeight(0),
+	mSuspendUpdates(false),
+	mVisible(true),
+	mLastSetCursor( UI_CURSOR_ARROW ),
+	mMediaNavState( MEDIANAVSTATE_NONE ),
+	mInterest(0.0f),
+	mUsedInUI(false),
+	mHasFocus(false),
+	mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
+	mNavigateRediscoverType(false),
+	mNavigateServerRequest(false),
+	mMediaSourceFailed(false),
+	mRequestedVolume(1.0f),
+	mIsMuted(false),
+	mNeedsMuteCheck(false),
+	mPreviousMediaState(MEDIA_NONE),
+	mPreviousMediaTime(0.0f),
+	mIsDisabled(false),
+	mIsParcelMedia(false),
+	mProximity(-1),
+	mProximityDistance(0.0f),
+	mMimeTypeProbe(NULL),
+	mMediaAutoPlay(false),
+	mInNearbyMediaList(false),
+	mClearCache(false),
+	mBackgroundColor(LLColor4::white),
+	mNavigateSuspended(false),
+	mNavigateSuspendedDeferred(false),
+	mIsUpdated(false),
+	mTrustedBrowser(false)
+{ 
+
+	// Set up the mute list observer if it hasn't been set up already.
+	if(!sViewerMediaMuteListObserverInitialized)
+	{
+		LLMuteList::getInstance()->addObserver(&sViewerMediaMuteListObserver);
+		sViewerMediaMuteListObserverInitialized = true;
+	}
+	
+	add_media_impl(this);
+
+	setTextureID(texture_id);
+	
+	// connect this media_impl to the media texture, creating it if it doesn't exist.0
+	// This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded.
+	LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId);
+	if(media_tex)
+	{
+		media_tex->setMediaImpl();
+	}
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+LLViewerMediaImpl::~LLViewerMediaImpl()
+{
+	destroyMediaSource();
+	
+	LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;
+
+	setTextureID();
+	remove_media_impl(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
+{
+	// Broadcast to observers using the superclass version
+	LLViewerMediaEventEmitter::emitEvent(plugin, event);
+	
+	// If this media is on one or more LLVOVolume objects, tell them about the event as well.
+	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+	while(iter != mObjectList.end())
+	{
+		LLVOVolume *self = *iter;
+		++iter;
+		self->mediaEvent(this, plugin, event);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
+{
+	bool mimeTypeChanged = (mMimeType != mime_type);
+	bool pluginChanged = (LLMIMETypes::implType(mCurrentMimeType) != LLMIMETypes::implType(mime_type));
+	
+	if(!mMediaSource || pluginChanged)
+	{
+		// We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type.
+		(void)initializePlugin(mime_type);
+	}
+	else if(mimeTypeChanged)
+	{
+		// The same plugin should be able to handle the new media -- just update the stored mime type.
+		mMimeType = mime_type;
+	}
+
+	return (mMediaSource != NULL);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::createMediaSource()
+{
+	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+	{
+		// This media shouldn't be created yet.
+		return;
+	}
+	
+	if(! mMediaURL.empty())
+	{
+		navigateInternal();
+	}
+	else if(! mMimeType.empty())
+	{
+		if (!initializeMedia(mMimeType))
+		{
+			LL_WARNS("Media") << "Failed to initialize media for mime type " << mMimeType << LL_ENDL;
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::destroyMediaSource()
+{
+	mNeedsNewTexture = true;
+
+	// Tell the viewer media texture it's no longer active
+	LLViewerMediaTexture* oldImage = LLViewerTextureManager::findMediaTexture( mTextureId );
+	if (oldImage)
+	{
+		oldImage->setPlaying(FALSE) ;
+	}
+	
+	cancelMimeTypeProbe();
+	
+	if(mMediaSource)
+	{
+		mMediaSource->setDeleteOK(true) ;
+		delete mMediaSource;
+		mMediaSource = NULL;
+	}	
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::setMediaType(const std::string& media_type)
+{
+	mMimeType = media_type;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/*static*/
+LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target)
+{
+	std::string plugin_basename = LLMIMETypes::implType(media_type);
+	LLPluginClassMedia* media_source = NULL;
+	
+	// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
+	// If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
+	if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
+	{
+		media_source = LLViewerMedia::getSpareBrowserMediaSource();
+		if(media_source)
+		{
+			media_source->setOwner(owner);
+			media_source->setTarget(target);
+			media_source->setSize(default_width, default_height);
+						
+			return media_source;
+		}
+	}
+	
+	if(plugin_basename.empty())
+	{
+		LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
+	}
+	else
+	{
+		std::string launcher_name = gDirUtilp->getLLPluginLauncher();
+		std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename);
+		std::string user_data_path = gDirUtilp->getOSUserAppDir();
+		user_data_path += gDirUtilp->getDirDelimiter();
+
+		// Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.)
+		// If the linden username returned is blank, that can only mean we are
+		// at the login page displaying login Web page or Web browser test via Develop menu.
+		// In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this
+		// is what we always used before this change)
+		std::string linden_user_dir = gDirUtilp->getLindenUserDir();
+		if ( ! linden_user_dir.empty() )
+		{
+			// gDirUtilp->getLindenUserDir() is whole path, not just Linden name
+			user_data_path = linden_user_dir;
+			user_data_path += gDirUtilp->getDirDelimiter();
+		};
+
+		// See if the plugin executable exists
+		llstat s;
+		if(LLFile::stat(launcher_name, &s))
+		{
+			LL_WARNS("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL;
+		}
+		else if(LLFile::stat(plugin_name, &s))
+		{
+			LL_WARNS("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL;
+		}
+		else
+		{
+			media_source = new LLPluginClassMedia(owner);
+			media_source->setSize(default_width, default_height);
+			media_source->setUserDataPath(user_data_path);
+			media_source->setLanguageCode(LLUI::getLanguage());
+
+			// collect 'cookies enabled' setting from prefs and send to embedded browser
+			bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
+			media_source->enable_cookies( cookies_enabled );
+
+			// collect 'plugins enabled' setting from prefs and send to embedded browser
+			bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
+			media_source->setPluginsEnabled( plugins_enabled );
+
+			// collect 'javascript enabled' setting from prefs and send to embedded browser
+			bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
+			media_source->setJavascriptEnabled( javascript_enabled );
+			
+			media_source->setTarget(target);
+			
+			const std::string plugin_dir = gDirUtilp->getLLPluginDir();
+			if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
+			{
+				return media_source;
+			}
+			else
+			{
+				LL_WARNS("Media") << "Failed to init plugin.  Destroying." << LL_ENDL;
+				delete media_source;
+			}
+		}
+	}
+	
+	LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
+	LLSD args;
+	args["MIME_TYPE"] = media_type;
+	LLNotificationsUtil::add("NoPlugin", args);
+
+	return NULL;
+}							
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
+{
+	if(mMediaSource)
+	{
+		// Save the previous media source's last set size before destroying it.
+		mMediaWidth = mMediaSource->getSetWidth();
+		mMediaHeight = mMediaSource->getSetHeight();
+	}
+	
+	// Always delete the old media impl first.
+	destroyMediaSource();
+	
+	// and unconditionally set the mime type
+	mMimeType = media_type;
+
+	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+	{
+		// This impl should not be loaded at this time.
+		LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
+		
+		return false;
+	}
+
+	// If we got here, we want to ignore previous init failures.
+	mMediaSourceFailed = false;
+
+	// Save the MIME type that really caused the plugin to load
+	mCurrentMimeType = mMimeType;
+
+	LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget);
+	
+	if (media_source)
+	{
+		media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout"));
+		media_source->setLoop(mMediaLoop);
+		media_source->setAutoScale(mMediaAutoScale);
+		media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
+		media_source->focus(mHasFocus);
+		media_source->setBackgroundColor(mBackgroundColor);
+		
+		if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors"))
+		{
+			media_source->ignore_ssl_cert_errors(true);
+		}
+
+		// the correct way to deal with certs it to load ours from CA.pem and append them to the ones
+		// Qt/WebKit loads from your system location.
+		// Note: This needs the new CA.pem file with the Equifax Secure Certificate Authority 
+		// cert at the bottom: (MIIDIDCCAomgAwIBAgIENd70zzANBg)
+		std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" );
+		media_source->addCertificateFilePath( ca_path );
+
+		media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"));
+		
+		if(mClearCache)
+		{
+			mClearCache = false;
+			media_source->clear_cache();
+		}
+		
+		// TODO: Only send cookies to plugins that need them
+		//  Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message.
+		//  Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message,
+		//  which could cause odd race conditions.
+		std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies();
+		lldebugs << "setting cookies: " << all_cookies << llendl;
+		if(!all_cookies.empty())
+		{
+			media_source->set_cookies(all_cookies);
+		}
+				
+		mMediaSource = media_source;
+		mMediaSource->setDeleteOK(false) ;
+		updateVolume();
+
+		return true;
+	}
+
+	// Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes.
+	mMediaSourceFailed = true;
+
+	return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::loadURI()
+{
+	if(mMediaSource)
+	{
+		// trim whitespace from front and back of URL - fixes EXT-5363
+		LLStringUtil::trim( mMediaURL );
+
+		// *HACK: we don't know if the URI coming in is properly escaped
+		// (the contract doesn't specify whether it is escaped or not.
+		// but LLQtWebKit expects it to be, so we do our best to encode
+		// special characters)
+		// The strings below were taken right from http://www.ietf.org/rfc/rfc1738.txt
+		// Note especially that '%' and '/' are there.
+		std::string uri = LLURI::escape(mMediaURL,
+										"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+										"0123456789"
+										"$-_.+"
+										"!*'(),"
+										"{}|\\^~[]`"
+										"<>#%"
+										";/?:@&=",
+										false);
+		llinfos << "Asking media source to load URI: " << uri << llendl;
+		
+		mMediaSource->loadURI( uri );
+		
+		// A non-zero mPreviousMediaTime means that either this media was previously unloaded by the priority code while playing/paused, 
+		// or a seek happened before the media loaded.  In either case, seek to the saved time.
+		if(mPreviousMediaTime != 0.0f)
+		{
+			seek(mPreviousMediaTime);
+		}
+			
+		if(mPreviousMediaState == MEDIA_PLAYING)
+		{
+			// This media was playing before this instance was unloaded.
+			start();
+		}
+		else if(mPreviousMediaState == MEDIA_PAUSED)
+		{
+			// This media was paused before this instance was unloaded.
+			pause();
+		}
+		else
+		{
+			// No relevant previous media play state -- if we're loading the URL, we want to start playing.
+			start();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::setSize(int width, int height)
+{
+	mMediaWidth = width;
+	mMediaHeight = height;
+	if(mMediaSource)
+	{
+		mMediaSource->setSize(width, height);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::showNotification(LLNotificationPtr notify)
+{
+	mNotification = notify;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::hideNotification()
+{
+	mNotification.reset();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::play()
+{
+	// If the media source isn't there, try to initialize it and load an URL.
+	if(mMediaSource == NULL)
+	{
+	 	if(!initializeMedia(mMimeType))
+		{
+			// This may be the case where the plugin's priority is PRIORITY_UNLOADED
+			return;
+		}
+		
+		// Only do this if the media source was just loaded.
+		loadURI();
+	}
+	
+	// always start the media
+	start();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::stop()
+{
+	if(mMediaSource)
+	{
+		mMediaSource->stop();
+		// destroyMediaSource();
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::pause()
+{
+	if(mMediaSource)
+	{
+		mMediaSource->pause();
+	}
+	else
+	{
+		mPreviousMediaState = MEDIA_PAUSED;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::start()
+{
+	if(mMediaSource)
+	{
+		mMediaSource->start();
+	}
+	else
+	{
+		mPreviousMediaState = MEDIA_PLAYING;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::seek(F32 time)
+{
+	if(mMediaSource)
+	{
+		mMediaSource->seek(time);
+	}
+	else
+	{
+		// Save the seek time to be set when the media is loaded.
+		mPreviousMediaTime = time;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::skipBack(F32 step_scale)
+{
+	if(mMediaSource)
+	{
+		if(mMediaSource->pluginSupportsMediaTime())
+		{
+			F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale);
+			if(back_step < 0.0)
+			{
+				back_step = 0.0;
+			}
+			mMediaSource->seek(back_step);
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::skipForward(F32 step_scale)
+{
+	if(mMediaSource)
+	{
+		if(mMediaSource->pluginSupportsMediaTime())
+		{
+			F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale);
+			if(forward_step > mMediaSource->getDuration())
+			{
+				forward_step = mMediaSource->getDuration();
+			}
+			mMediaSource->seek(forward_step);
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::setVolume(F32 volume)
+{
+	mRequestedVolume = volume;
+	updateVolume();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::updateVolume()
+{
+	if(mMediaSource)
+	{
+		// always scale the volume by the global media volume 
+		F32 volume = mRequestedVolume * LLViewerMedia::getVolume();
+
+		if (mProximityCamera > 0) 
+		{
+			if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMax"))
+			{
+				volume = 0;
+			}
+			else if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMin"))
+			{
+				// attenuated_volume = 1 / (roll_off_rate * (d - min))^2
+				// the +1 is there so that for distance 0 the volume stays the same
+				F64 adjusted_distance = mProximityCamera - gSavedSettings.getF32("MediaRollOffMin");
+				F64 attenuation = 1.0 + (gSavedSettings.getF32("MediaRollOffRate") * adjusted_distance);
+				attenuation = 1.0 / (attenuation * attenuation);
+				// the attenuation multiplier should never be more than one since that would increase volume
+				volume = volume * llmin(1.0, attenuation);
+			}
+		}
+
+		mMediaSource->setVolume(volume);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+F32 LLViewerMediaImpl::getVolume()
+{
+	return mRequestedVolume;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::focus(bool focus)
+{
+	mHasFocus = focus;
+	
+	if (mMediaSource)
+	{
+		// call focus just for the hell of it, even though this apopears to be a nop
+		mMediaSource->focus(focus);
+		if (focus)
+		{
+			// spoof a mouse click to *actually* pass focus
+			// Don't do this anymore -- it actually clicks through now.
+//			mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0);
+//			mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0);
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::hasFocus() const
+{
+	// FIXME: This might be able to be a bit smarter by hooking into LLViewerMediaFocus, etc.
+	return mHasFocus;
+}
+
+std::string LLViewerMediaImpl::getCurrentMediaURL()
+{
+	if(!mCurrentMediaURL.empty())
+	{
+		return mCurrentMediaURL;
+	}
+	
+	return mMediaURL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::clearCache()
+{
+	if(mMediaSource)
+	{
+		mMediaSource->clear_cache();
+	}
+	else
+	{
+		mClearCache = true;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button)
+{
+	scaleMouse(&x, &y);
+	mLastMouseX = x;
+	mLastMouseY = y;
+//	llinfos << "mouse down (" << x << ", " << y << ")" << llendl;
+	if (mMediaSource)
+	{
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, button, x, y, mask);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseUp(S32 x, S32 y, MASK mask, S32 button)
+{
+	scaleMouse(&x, &y);
+	mLastMouseX = x;
+	mLastMouseY = y;
+//	llinfos << "mouse up (" << x << ", " << y << ")" << llendl;
+	if (mMediaSource)
+	{
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, button, x, y, mask);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask)
+{
+    scaleMouse(&x, &y);
+	mLastMouseX = x;
+	mLastMouseY = y;
+//	llinfos << "mouse move (" << x << ", " << y << ")" << llendl;
+	if (mMediaSource)
+	{
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, x, y, mask);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//static 
+void LLViewerMediaImpl::scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y)
+{
+	F32 texture_x = texture_coords.mV[VX];
+	F32 texture_y = texture_coords.mV[VY];
+	
+	// Deal with repeating textures by wrapping the coordinates into the range [0, 1.0)
+	texture_x = fmodf(texture_x, 1.0f);
+	if(texture_x < 0.0f)
+		texture_x = 1.0 + texture_x;
+		
+	texture_y = fmodf(texture_y, 1.0f);
+	if(texture_y < 0.0f)
+		texture_y = 1.0 + texture_y;
+
+	// scale x and y to texel units.
+	*x = llround(texture_x * mMediaSource->getTextureWidth());
+	*y = llround((1.0f - texture_y) * mMediaSource->getTextureHeight());
+
+	// Adjust for the difference between the actual texture height and the amount of the texture in use.
+	*y -= (mMediaSource->getTextureHeight() - mMediaSource->getHeight());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button)
+{
+	if(mMediaSource)
+	{
+		S32 x, y;
+		scaleTextureCoords(texture_coords, &x, &y);
+
+		mouseDown(x, y, mask, button);
+	}
+}
+
+void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button)
+{
+	if(mMediaSource)
+	{		
+		S32 x, y;
+		scaleTextureCoords(texture_coords, &x, &y);
+
+		mouseUp(x, y, mask, button);
+	}
+}
+
+void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
+{
+	if(mMediaSource)
+	{		
+		S32 x, y;
+		scaleTextureCoords(texture_coords, &x, &y);
+
+		mouseMove(x, y, mask);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
+{
+	scaleMouse(&x, &y);
+	mLastMouseX = x;
+	mLastMouseY = y;
+	if (mMediaSource)
+	{
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, button, x, y, mask);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask)
+{
+	scaleMouse(&x, &y);
+	mLastMouseX = x;
+	mLastMouseY = y;
+	if (mMediaSource)
+	{
+		mMediaSource->scrollEvent(x, y, mask);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::onMouseCaptureLost()
+{
+	if (mMediaSource)
+	{
+		mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 0, mLastMouseX, mLastMouseY, 0);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) 
+{ 
+	// NOTE: this is called when the mouse is released when we have capture.
+	// Due to the way mouse coordinates are mapped to the object, we can't use the x and y coordinates that come in with the event.
+	
+	if(hasMouseCapture())
+	{
+		// Release the mouse -- this will also send a mouseup to the media
+		gFocusMgr.setMouseCapture( FALSE );
+	}
+
+	return TRUE; 
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+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 );
+
+		// 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
+		bool logged_in = LLLoginInstance::getInstance()->authSuccess();
+		mMediaSource->jsValuesValidEvent( logged_in );
+
+		// current location within a region
+		LLVector3 agent_pos = gAgent.getPositionAgent();
+		double x = agent_pos.mV[ VX ];
+		double y = agent_pos.mV[ VY ];
+		double z = agent_pos.mV[ VZ ];
+		mMediaSource->jsAgentLocationEvent( x, y, z );
+
+		// current region agent is in
+		std::string region_name("");
+		LLViewerRegion* region = gAgent.getRegion();
+		if ( region )
+		{
+			region_name = region->getName();
+		};
+		mMediaSource->jsAgentRegionEvent( region_name );
+
+		// language code the viewer is set to
+		mMediaSource->jsAgentLanguageEvent( LLUI::getLanguage() );
+
+		// maturity setting the agent has selected
+		if ( gAgent.prefersAdult() )
+			mMediaSource->jsAgentMaturityEvent( "GMA" );	// Adult means see adult, mature and general content
+		else
+		if ( gAgent.prefersMature() )
+			mMediaSource->jsAgentMaturityEvent( "GM" );	// Mature means see mature and general content
+		else
+		if ( gAgent.prefersPG() )
+			mMediaSource->jsAgentMaturityEvent( "G" );	// PG means only see General content
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+std::string LLViewerMediaImpl::getName() const 
+{ 
+	if (mMediaSource)
+	{
+		return mMediaSource->getMediaName();
+	}
+	
+	return LLStringUtil::null; 
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateBack()
+{
+	if (mMediaSource)
+	{
+		mMediaSource->browse_back();
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateForward()
+{
+	if (mMediaSource)
+	{
+		mMediaSource->browse_forward();
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateReload()
+{
+	navigateTo(getCurrentMediaURL(), "", true, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateHome()
+{
+	bool rediscover_mimetype = mHomeMimeType.empty();
+	navigateTo(mHomeURL, mHomeMimeType, rediscover_mimetype, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::unload()
+{
+	// Unload the media impl and clear its state.
+	destroyMediaSource();
+	resetPreviousMediaState();
+	mMediaURL.clear();
+	mMimeType.clear();
+	mCurrentMediaURL.clear();
+	mCurrentMimeType.clear();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type,  bool rediscover_type, bool server_request)
+{
+	cancelMimeTypeProbe();
+
+	if(mMediaURL != url)
+	{
+		// Don't carry media play state across distinct URLs.
+		resetPreviousMediaState();
+	}
+	
+	// Always set the current URL and MIME type.
+	mMediaURL = url;
+	mMimeType = mime_type;
+	
+	// Clear the current media URL, since it will no longer be correct.
+	mCurrentMediaURL.clear();
+	
+	// if mime type discovery was requested, we'll need to do it when the media loads
+	mNavigateRediscoverType = rediscover_type;
+	
+	// and if this was a server request, the navigate on load will also need to be one.
+	mNavigateServerRequest = server_request;
+	
+	// An explicit navigate resets the "failed" flag.
+	mMediaSourceFailed = false;
+
+	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+	{
+		// Helpful to have media urls in log file. Shouldn't be spammy.
+		llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
+
+		// This impl should not be loaded at this time.
+		LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
+		
+		return;
+	}
+
+	navigateInternal();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateInternal()
+{
+	// Helpful to have media urls in log file. Shouldn't be spammy.
+	llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
+
+	if(mNavigateSuspended)
+	{
+		llwarns << "Deferring navigate." << llendl;
+		mNavigateSuspendedDeferred = true;
+		return;
+	}
+	
+	if(mMimeTypeProbe != NULL)
+	{
+		llwarns << "MIME type probe already in progress -- bailing out." << llendl;
+		return;
+	}
+	
+	if(mNavigateServerRequest)
+	{
+		setNavState(MEDIANAVSTATE_SERVER_SENT);
+	}
+	else
+	{
+		setNavState(MEDIANAVSTATE_NONE);
+	}
+			
+	// If the caller has specified a non-empty MIME type, look that up in our MIME types list.
+	// If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
+	// This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
+	// but the parcel owner has correctly set the MIME type in the parcel media settings.
+	
+	if(!mMimeType.empty() && (mMimeType != LLMIMETypes::getDefaultMimeType()))
+	{
+		std::string plugin_basename = LLMIMETypes::implType(mMimeType);
+		if(!plugin_basename.empty())
+		{
+			// We have a plugin for this mime type
+			mNavigateRediscoverType = false;
+		}
+	}
+
+	if(mNavigateRediscoverType)
+	{
+
+		LLURI uri(mMediaURL);
+		std::string scheme = uri.scheme();
+
+		if(scheme.empty() || "http" == scheme || "https" == scheme)
+		{
+			// If we don't set an Accept header, LLHTTPClient will add one like this:
+			//    Accept: application/llsd+xml
+			// which is really not what we want.
+			LLSD headers = LLSD::emptyMap();
+			headers["Accept"] = "*/*";
+			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com
+			headers["Cookie"] = "";
+			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
+		}
+		else if("data" == scheme || "file" == scheme || "about" == scheme)
+		{
+			// FIXME: figure out how to really discover the type for these schemes
+			// We use "data" internally for a text/html url for loading the login screen
+			if(initializeMedia("text/html"))
+			{
+				loadURI();
+			}
+		}
+		else
+		{
+			// This catches 'rtsp://' urls
+			if(initializeMedia(scheme))
+			{
+				loadURI();
+			}
+		}
+	}
+	else if(initializeMedia(mMimeType))
+	{
+		loadURI();
+	}
+	else
+	{
+		LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateStop()
+{
+	if(mMediaSource)
+	{
+		mMediaSource->browse_stop();
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
+{
+	bool result = false;
+	
+	if (mMediaSource)
+	{
+		// FIXME: THIS IS SO WRONG.
+		// Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
+		if( MASK_CONTROL & mask )
+		{
+			result = true;
+		}
+		
+		if(!result)
+		{
+			
+			LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData();
+			
+			result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data);
+			// Since the viewer internal event dispatching doesn't give us key-up events, simulate one here.
+			(void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data);
+		}
+	}
+	
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
+{
+	bool result = false;
+	
+	if (mMediaSource)
+	{
+		// only accept 'printable' characters, sigh...
+		if (uni_char >= 32 // discard 'control' characters
+			&& uni_char != 127) // SDL thinks this is 'delete' - yuck.
+		{
+			LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData();
+			
+			mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data);
+		}
+	}
+	
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::canNavigateForward()
+{
+	BOOL result = FALSE;
+	if (mMediaSource)
+	{
+		result = mMediaSource->getHistoryForwardAvailable();
+	}
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::canNavigateBack()
+{
+	BOOL result = FALSE;
+	if (mMediaSource)
+	{
+		result = mMediaSource->getHistoryBackAvailable();
+	}
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::update()
+{
+	if(mMediaSource == NULL)
+	{
+		if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+		{
+			// This media source should not be loaded.
+		}
+		else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW)
+		{
+			// Don't load new instances that are at PRIORITY_SLIDESHOW or below.  They're just kept around to preserve state.
+		}
+		else if(mMimeTypeProbe != NULL)
+		{
+			// this media source is doing a MIME type probe -- don't try loading it again.
+		}
+		else
+		{
+			// This media may need to be loaded.
+			if(sMediaCreateTimer.hasExpired())
+			{
+				LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL;
+				createMediaSource();
+				sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY);
+			}
+			else
+			{
+				LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL;
+			}
+		}
+	}
+	else
+	{
+		updateVolume();
+
+		// TODO: this is updated every frame - is this bad?
+		updateJavascriptObject();
+
+		// If we didn't just create the impl, it may need to get cookie updates.
+		if(!sUpdatedCookies.empty())
+		{
+			// TODO: Only send cookies to plugins that need them
+			mMediaSource->set_cookies(sUpdatedCookies);
+		}
+	}
+
+	
+	if(mMediaSource == NULL)
+	{
+		return;
+	}
+	
+	// Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash.
+	setNavigateSuspended(true);
+	
+	mMediaSource->idle();
+
+	setNavigateSuspended(false);
+
+	if(mMediaSource == NULL)
+	{
+		return;
+	}
+	
+	if(mMediaSource->isPluginExited())
+	{
+		resetPreviousMediaState();
+		destroyMediaSource();
+		return;
+	}
+
+	if(!mMediaSource->textureValid())
+	{
+		return;
+	}
+	
+	if(mSuspendUpdates || !mVisible)
+	{
+		return;
+	}
+	
+	LLViewerMediaTexture* placeholder_image = updatePlaceholderImage();
+		
+	if(placeholder_image)
+	{
+		LLRect dirty_rect;
+		
+		// Since we're updating this texture, we know it's playing.  Tell the texture to do its replacement magic so it gets rendered.
+		placeholder_image->setPlaying(TRUE);
+
+		if(mMediaSource->getDirty(&dirty_rect))
+		{
+			// Constrain the dirty rect to be inside the texture
+			S32 x_pos = llmax(dirty_rect.mLeft, 0);
+			S32 y_pos = llmax(dirty_rect.mBottom, 0);
+			S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos;
+			S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos;
+			
+			if(width > 0 && height > 0)
+			{
+
+				U8* data = mMediaSource->getBitsData();
+
+				// Offset the pixels pointer to match x_pos and y_pos
+				data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() );
+				data += ( y_pos * mMediaSource->getTextureDepth() );
+				
+				placeholder_image->setSubImage(
+						data, 
+						mMediaSource->getBitsWidth(), 
+						mMediaSource->getBitsHeight(),
+						x_pos, 
+						y_pos, 
+						width, 
+						height);
+
+			}
+			
+			mMediaSource->resetDirty();
+		}
+	}
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::updateImagesMediaStreams()
+{
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
+{
+	if(mTextureId.isNull())
+	{
+		// The code that created this instance will read from the plugin's bits.
+		return NULL;
+	}
+	
+	LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId );
+	
+	if (mNeedsNewTexture 
+		|| placeholder_image->getUseMipMaps()
+		|| (placeholder_image->getWidth() != mMediaSource->getTextureWidth())
+		|| (placeholder_image->getHeight() != mMediaSource->getTextureHeight())
+		|| (mTextureUsedWidth != mMediaSource->getWidth())
+		|| (mTextureUsedHeight != mMediaSource->getHeight())
+		)
+	{
+		LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL;
+		LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL;
+
+		int texture_width = mMediaSource->getTextureWidth();
+		int texture_height = mMediaSource->getTextureHeight();
+		int texture_depth = mMediaSource->getTextureDepth();
+		
+		// MEDIAOPT: check to see if size actually changed before doing work
+		placeholder_image->destroyGLTexture();
+		// MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work?
+		placeholder_image->reinit(FALSE);	// probably not needed
+
+		// MEDIAOPT: seems insane that we actually have to make an imageraw then
+		// immediately discard it
+		LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth);
+		// Clear the texture to the background color, ignoring alpha.
+		// convert background color channels from [0.0, 1.0] to [0, 255];
+		raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff);
+		int discard_level = 0;
+
+		// ask media source for correct GL image format constants
+		placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(),
+											 mMediaSource->getTextureFormatPrimary(),
+											 mMediaSource->getTextureFormatType(),
+											 mMediaSource->getTextureFormatSwapBytes());
+
+		placeholder_image->createGLTexture(discard_level, raw);
+
+		// MEDIAOPT: set this dynamically on play/stop
+		// FIXME
+//		placeholder_image->mIsMediaTexture = true;
+		mNeedsNewTexture = false;
+				
+		// If the amount of the texture being drawn by the media goes down in either width or height, 
+		// recreate the texture to avoid leaving parts of the old image behind.
+		mTextureUsedWidth = mMediaSource->getWidth();
+		mTextureUsedHeight = mMediaSource->getHeight();
+	}
+	
+	return placeholder_image;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+LLUUID LLViewerMediaImpl::getMediaTextureID() const
+{
+	return mTextureId;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::setVisible(bool visible)
+{
+	mVisible = visible;
+	
+	if(mVisible)
+	{
+		if(mMediaSource && mMediaSource->isPluginExited())
+		{
+			destroyMediaSource();
+		}
+		
+		if(!mMediaSource)
+		{
+			createMediaSource();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseCapture()
+{
+	gFocusMgr.setMouseCapture(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y)
+{
+#if 0
+	S32 media_width, media_height;
+	S32 texture_width, texture_height;
+	getMediaSize( &media_width, &media_height );
+	getTextureSize( &texture_width, &texture_height );
+	S32 y_delta = texture_height - media_height;
+
+	*mouse_y -= y_delta;
+#endif
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::isMediaTimeBased()
+{
+	bool result = false;
+	
+	if(mMediaSource)
+	{
+		result = mMediaSource->pluginSupportsMediaTime();
+	}
+	
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::isMediaPlaying()
+{
+	bool result = false;
+	
+	if(mMediaSource)
+	{
+		EMediaStatus status = mMediaSource->getStatus();
+		if(status == MEDIA_PLAYING || status == MEDIA_LOADING)
+			result = true;
+	}
+	
+	return result;
+}
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::isMediaPaused()
+{
+	bool result = false;
+
+	if(mMediaSource)
+	{
+		if(mMediaSource->getStatus() == MEDIA_PAUSED)
+			result = true;
+	}
+	
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::hasMedia() const
+{
+	return mMediaSource != NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::resetPreviousMediaState()
+{
+	mPreviousMediaState = MEDIA_NONE;
+	mPreviousMediaTime = 0.0f;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::setDisabled(bool disabled, bool forcePlayOnEnable)
+{
+	if(mIsDisabled != disabled)
+	{
+		// Only do this on actual state transitions.
+		mIsDisabled = disabled;
+		
+		if(mIsDisabled)
+		{
+			// We just disabled this media.  Clear all state.
+			unload();
+		}
+		else
+		{
+			// We just (re)enabled this media.  Do a navigate if auto-play is in order.
+			if(isAutoPlayable() || forcePlayOnEnable)
+			{
+				navigateTo(mMediaEntryURL, "", true, true);
+			}
+		}
+
+	}
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isForcedUnloaded() const
+{
+	if(mIsMuted || mMediaSourceFailed || mIsDisabled)
+	{
+		return true;
+	}
+	
+	if(sInWorldMediaDisabled)
+	{
+		// When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded.
+		if(!mUsedInUI)
+		{
+			return true;
+		}
+	}
+	
+	// If this media's class is not supposed to be shown, unload
+	if (!shouldShowBasedOnClass())
+	{
+		return true;
+	}
+	
+	return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isPlayable() const
+{
+	if(isForcedUnloaded())
+	{
+		// All of the forced-unloaded criteria also imply not playable.
+		return false;
+	}
+	
+	if(hasMedia())
+	{
+		// Anything that's already playing is, by definition, playable.
+		return true;
+	}
+	
+	if(!mMediaURL.empty())
+	{
+		// If something has navigated the instance, it's ready to be played.
+		return true;
+	}
+	
+	return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
+{
+	bool pass_through = true;
+	switch(event)
+	{
+		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
+		{
+			LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL; 
+			std::string url = plugin->getClickURL();
+			std::string nav_type = plugin->getClickNavType();
+			LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser);
+		}
+		break;
+		case MEDIA_EVENT_CLICK_LINK_HREF:
+		{
+			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << plugin->getClickTarget() << "\", uri is " << plugin->getClickURL() << LL_ENDL;
+		};
+		break;
+		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+		{
+			// The plugin failed to load properly.  Make sure the timer doesn't retry.
+			// TODO: maybe mark this plugin as not loadable somehow?
+			mMediaSourceFailed = true;
+
+			// Reset the last known state of the media to defaults.
+			resetPreviousMediaState();
+			
+			// TODO: may want a different message for this case?
+			LLSD args;
+			args["PLUGIN"] = LLMIMETypes::implType(mCurrentMimeType);
+			LLNotificationsUtil::add("MediaPluginFailed", args);
+		}
+		break;
+
+		case MEDIA_EVENT_PLUGIN_FAILED:
+		{
+			// The plugin crashed.
+			mMediaSourceFailed = true;
+
+			// Reset the last known state of the media to defaults.
+			resetPreviousMediaState();
+
+			LLSD args;
+			args["PLUGIN"] = LLMIMETypes::implType(mCurrentMimeType);
+			// SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
+			//LLNotificationsUtil::add("MediaPluginFailed", args);
+		}
+		break;
+		
+		case MEDIA_EVENT_CURSOR_CHANGED:
+		{
+			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << plugin->getCursorName() << LL_ENDL;
+
+			std::string cursor = plugin->getCursorName();
+			
+			if(cursor == "arrow")
+				mLastSetCursor = UI_CURSOR_ARROW;
+			else if(cursor == "ibeam")
+				mLastSetCursor = UI_CURSOR_IBEAM;
+			else if(cursor == "splith")
+				mLastSetCursor = UI_CURSOR_SIZEWE;
+			else if(cursor == "splitv")
+				mLastSetCursor = UI_CURSOR_SIZENS;
+			else if(cursor == "hand")
+				mLastSetCursor = UI_CURSOR_HAND;
+			else // for anything else, default to the arrow
+				mLastSetCursor = UI_CURSOR_ARROW;
+		}
+		break;
+
+		case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN:
+		{
+			LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+			hideNotification();
+
+			if(getNavState() == MEDIANAVSTATE_SERVER_SENT)
+			{
+				setNavState(MEDIANAVSTATE_SERVER_BEGUN);
+			}
+			else
+			{
+				setNavState(MEDIANAVSTATE_BEGUN);
+			}
+		}
+		break;
+
+		case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
+		{
+			LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+
+			std::string url = plugin->getNavigateURI();
+			if(getNavState() == MEDIANAVSTATE_BEGUN)
+			{
+				if(mCurrentMediaURL == url)
+				{
+					// This is a navigate that takes us to the same url as the previous navigate.
+					setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS);
+				}
+				else
+				{
+					mCurrentMediaURL = url;
+					setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED);
+				}
+			}
+			else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
+			{
+				mCurrentMediaURL = url;
+				setNavState(MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED);
+			}
+			else
+			{
+				// all other cases need to leave the state alone.
+			}
+		}
+		break;
+		
+		case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
+		{
+			LL_DEBUGS("Media") << "MEDIA_EVENT_LOCATION_CHANGED, uri is: " << plugin->getLocation() << LL_ENDL;
+
+			std::string url = plugin->getLocation();
+
+			if(getNavState() == MEDIANAVSTATE_BEGUN)
+			{
+				if(mCurrentMediaURL == url)
+				{
+					// This is a navigate that takes us to the same url as the previous navigate.
+					setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS);
+				}
+				else
+				{
+					mCurrentMediaURL = url;
+					setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED);
+				}
+			}
+			else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
+			{
+				mCurrentMediaURL = url;
+				setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED);
+			}
+			else
+			{
+				// Don't track redirects.
+				setNavState(MEDIANAVSTATE_NONE);
+			}
+		}
+		break;
+
+		case LLViewerMediaObserver::MEDIA_EVENT_PICK_FILE_REQUEST:
+		{
+			// Display a file picker
+			std::string response;
+			
+			LLFilePicker& picker = LLFilePicker::instance();
+			if (!picker.getOpenFile(LLFilePicker::FFLOAD_ALL))
+			{
+				// The user didn't pick a file -- the empty response string will indicate this.
+			}
+			
+			response = picker.getFirstFile();
+			
+			plugin->sendPickFileResponse(response);
+		}
+		break;
+
+
+		case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST:
+		{
+			LLNotification::Params auth_request_params;
+			auth_request_params.name = "AuthRequest";
+
+			// pass in host name and realm for site (may be zero length but will always exist)
+			LLSD args;
+			LLURL raw_url( plugin->getAuthURL().c_str() );
+			args["HOST_NAME"] = raw_url.getAuthority();
+			args["REALM"] = plugin->getAuthRealm();
+			auth_request_params.substitutions = args;
+
+			auth_request_params.payload = LLSD().with("media_id", mTextureId);
+			auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2);
+			LLNotifications::instance().add(auth_request_params);
+		};
+		break;
+
+		case LLViewerMediaObserver::MEDIA_EVENT_CLOSE_REQUEST:
+		{
+			std::string uuid = plugin->getClickUUID();
+
+			llinfos << "MEDIA_EVENT_CLOSE_REQUEST for uuid " << uuid << llendl;
+
+			if(uuid.empty())
+			{
+				// This close request is directed at this instance, let it fall through.
+			}
+			else
+			{
+				// This close request is directed at another instance
+				pass_through = false;
+				LLFloaterMediaBrowser::closeRequest(uuid);
+				LLFloaterWebContent::closeRequest(uuid);
+			}
+		}
+		break;
+
+		case LLViewerMediaObserver::MEDIA_EVENT_GEOMETRY_CHANGE:
+		{
+			std::string uuid = plugin->getClickUUID();
+
+			llinfos << "MEDIA_EVENT_GEOMETRY_CHANGE for uuid " << uuid << llendl;
+
+			if(uuid.empty())
+			{
+				// This geometry change request is directed at this instance, let it fall through.
+			}
+			else
+			{
+				// This request is directed at another instance
+				pass_through = false;
+				LLFloaterMediaBrowser::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
+				LLFloaterWebContent::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
+			}
+		}
+		break;
+
+		default:
+		break;
+	}
+
+	if(pass_through)
+	{
+		// Just chain the event to observers.
+		emitEvent(plugin, event);
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie)
+{
+	LLViewerMedia::getCookieStore()->setCookies(cookie);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void
+LLViewerMediaImpl::cut()
+{
+	if (mMediaSource)
+		mMediaSource->cut();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL
+LLViewerMediaImpl::canCut() const
+{
+	if (mMediaSource)
+		return mMediaSource->canCut();
+	else
+		return FALSE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void
+LLViewerMediaImpl::copy()
+{
+	if (mMediaSource)
+		mMediaSource->copy();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL
+LLViewerMediaImpl::canCopy() const
+{
+	if (mMediaSource)
+		return mMediaSource->canCopy();
+	else
+		return FALSE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void
+LLViewerMediaImpl::paste()
+{
+	if (mMediaSource)
+		mMediaSource->paste();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL
+LLViewerMediaImpl::canPaste() const
+{
+	if (mMediaSource)
+		return mMediaSource->canPaste();
+	else
+		return FALSE;
+}
+
+void LLViewerMediaImpl::setUpdated(BOOL updated)
+{
+	mIsUpdated = updated ;
+}
+
+BOOL LLViewerMediaImpl::isUpdated()
+{
+	return mIsUpdated ;
+}
+
+void LLViewerMediaImpl::calculateInterest()
+{
+	LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId );
+	
+	if(texture != NULL)
+	{
+		mInterest = texture->getMaxVirtualSize();
+	}
+	else
+	{
+		// This will be a relatively common case now, since it will always be true for unloaded media.
+		mInterest = 0.0f;
+	}
+	
+	// Calculate distance from the avatar, for use in the proximity calculation.
+	mProximityDistance = 0.0f;
+	mProximityCamera = 0.0f;
+	if(!mObjectList.empty())
+	{
+		// Just use the first object in the list.  We could go through the list and find the closest object, but this should work well enough.
+		std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+		LLVOVolume* objp = *iter ;
+		llassert_always(objp != NULL) ;
+		
+		// The distance calculation is invalid for HUD attachments -- leave both mProximityDistance and mProximityCamera at 0 for them.
+		if(!objp->isHUDAttachment())
+		{
+			LLVector3d obj_global = objp->getPositionGlobal() ;
+			LLVector3d agent_global = gAgent.getPositionGlobal() ;
+			LLVector3d global_delta = agent_global - obj_global ;
+			mProximityDistance = global_delta.magVecSquared();  // use distance-squared because it's cheaper and sorts the same.
+
+			LLVector3d camera_delta = gAgentCamera.getCameraPositionGlobal() - obj_global;
+			mProximityCamera = camera_delta.magVec();
+		}
+	}
+	
+	if(mNeedsMuteCheck)
+	{
+		// Check all objects this instance is associated with, and those objects' owners, against the mute list
+		mIsMuted = false;
+		
+		std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+		for(; iter != mObjectList.end() ; ++iter)
+		{
+			LLVOVolume *obj = *iter;
+			llassert(obj);
+			if (!obj) continue;
+			if(LLMuteList::getInstance() &&
+			   LLMuteList::getInstance()->isMuted(obj->getID()))
+			{
+				mIsMuted = true;
+			}
+			else
+			{
+				// We won't have full permissions data for all objects.  Attempt to mute objects when we can tell their owners are muted.
+				if (LLSelectMgr::getInstance())
+				{
+					LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(obj);
+					if(obj_perm)
+					{
+						if(LLMuteList::getInstance() &&
+						   LLMuteList::getInstance()->isMuted(obj_perm->getOwner()))
+							mIsMuted = true;
+					}
+				}
+			}
+		}
+		
+		mNeedsMuteCheck = false;
+	}
+}
+
+F64 LLViewerMediaImpl::getApproximateTextureInterest()
+{
+	F64 result = 0.0f;
+	
+	if(mMediaSource)
+	{
+		result = mMediaSource->getFullWidth();
+		result *= mMediaSource->getFullHeight();
+	}
+	else
+	{
+		// No media source is loaded -- all we have to go on is the texture size that has been set on the impl, if any.
+		result = mMediaWidth;
+		result *= mMediaHeight;
+	}
+
+	return result;
+}
+
+void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
+{
+	mUsedInUI = used_in_ui; 
+	
+	// HACK: Force elements used in UI to load right away.
+	// This fixes some issues where UI code that uses the browser instance doesn't expect it to be unloaded.
+	if(mUsedInUI && (mPriority == LLPluginClassMedia::PRIORITY_UNLOADED))
+	{
+		if(getVisible())
+		{
+			setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
+		}
+		else
+		{
+			setPriority(LLPluginClassMedia::PRIORITY_HIDDEN);
+		}
+
+		createMediaSource();
+	}
+};
+
+void LLViewerMediaImpl::setBackgroundColor(LLColor4 color)
+{
+	mBackgroundColor = color; 
+
+	if(mMediaSource)
+	{
+		mMediaSource->setBackgroundColor(mBackgroundColor);
+	}
+};
+
+F64 LLViewerMediaImpl::getCPUUsage() const
+{
+	F64 result = 0.0f;
+	
+	if(mMediaSource)
+	{
+		result = mMediaSource->getCPUUsage();
+	}
+	
+	return result;
+}
+
+void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
+{
+	if(mPriority != priority)
+	{
+		LL_DEBUGS("PluginPriority")
+			<< "changing priority of media id " << mTextureId
+			<< " from " << LLPluginClassMedia::priorityToString(mPriority)
+			<< " to " << LLPluginClassMedia::priorityToString(priority)
+			<< LL_ENDL;
+	}
+	
+	mPriority = priority;
+	
+	if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
+	{
+		if(mMediaSource)
+		{
+			// Need to unload the media source
+			
+			// First, save off previous media state
+			mPreviousMediaState = mMediaSource->getStatus();
+			mPreviousMediaTime = mMediaSource->getCurrentTime();
+			
+			destroyMediaSource();
+		}
+	}
+
+	if(mMediaSource)
+	{
+		mMediaSource->setPriority(mPriority);
+	}
+	
+	// NOTE: loading (or reloading) media sources whose priority has risen above PRIORITY_UNLOADED is done in update().
+}
+
+void LLViewerMediaImpl::setLowPrioritySizeLimit(int size)
+{
+	if(mMediaSource)
+	{
+		mMediaSource->setLowPrioritySizeLimit(size);
+	}
+}
+
+void LLViewerMediaImpl::setNavState(EMediaNavState state)
+{
+	mMediaNavState = state;
+	
+	switch (state) 
+	{
+		case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break;
+		case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break;
+		case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break;
+		case MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS" << llendl; break;
+		case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
+		case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS" << llendl; break;
+		case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break;
+		case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break;
+		case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break;
+		case MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
+	}
+}
+
+void LLViewerMediaImpl::setNavigateSuspended(bool suspend)
+{
+	if(mNavigateSuspended != suspend)
+	{
+		mNavigateSuspended = suspend;
+		if(!suspend)
+		{
+			// We're coming out of suspend.  If someone tried to do a navigate while suspended, do one now instead.
+			if(mNavigateSuspendedDeferred)
+			{
+				mNavigateSuspendedDeferred = false;
+				navigateInternal();
+			}
+		}
+	}
+}
+
+void LLViewerMediaImpl::cancelMimeTypeProbe()
+{
+	if(mMimeTypeProbe != NULL)
+	{
+		// There doesn't seem to be a way to actually cancel an outstanding request.
+		// Simulate it by telling the LLMimeDiscoveryResponder not to write back any results.
+		mMimeTypeProbe->cancelRequest();
+		
+		// The above should already have set mMimeTypeProbe to NULL.
+		if(mMimeTypeProbe != NULL)
+		{
+			llerrs << "internal error: mMimeTypeProbe is not NULL after cancelling request." << llendl;
+		}
+	}
+}
+
+void LLViewerMediaImpl::addObject(LLVOVolume* obj) 
+{
+	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+	for(; iter != mObjectList.end() ; ++iter)
+	{
+		if(*iter == obj)
+		{
+			return ; //already in the list.
+		}
+	}
+
+	mObjectList.push_back(obj) ;
+	mNeedsMuteCheck = true;
+}
+	
+void LLViewerMediaImpl::removeObject(LLVOVolume* obj) 
+{
+	mObjectList.remove(obj) ;	
+	mNeedsMuteCheck = true;
+}
+	
+const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const 
+{
+	return &mObjectList ;
+}
+
+LLVOVolume *LLViewerMediaImpl::getSomeObject()
+{
+	LLVOVolume *result = NULL;
+	
+	std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+	if(iter != mObjectList.end())
+	{
+		result = *iter;
+	}
+	
+	return result;
+}
+
+void LLViewerMediaImpl::setTextureID(LLUUID id)
+{
+	if(id != mTextureId)
+	{
+		if(mTextureId.notNull())
+		{
+			// Remove this item's entry from the map
+			sViewerMediaTextureIDMap.erase(mTextureId);
+		}
+		
+		if(id.notNull())
+		{
+			sViewerMediaTextureIDMap.insert(LLViewerMedia::impl_id_map::value_type(id, this));
+		}
+		
+		mTextureId = id;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isAutoPlayable() const
+{
+	return (mMediaAutoPlay && 
+			gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+			gSavedSettings.getBOOL("MediaTentativeAutoPlay"));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::shouldShowBasedOnClass() const
+{
+	// If this is parcel media or in the UI, return true always
+	if (getUsedInUI() || isParcelMedia()) return true;
+	
+	bool attached_to_another_avatar = isAttachedToAnotherAvatar();
+	bool inside_parcel = isInAgentParcel();
+	
+	//	llinfos << " hasFocus = " << hasFocus() <<
+	//	" others = " << (attached_to_another_avatar && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING)) <<
+	//	" within = " << (inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING)) <<
+	//	" outside = " << (!inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING)) << llendl;
+	
+	// If it has focus, we should show it
+	// This is incorrect, and causes EXT-6750 (disabled attachment media still plays)
+//	if (hasFocus())
+//		return true;
+	
+	// If it is attached to an avatar and the pref is off, we shouldn't show it
+	if (attached_to_another_avatar)
+		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING);
+	
+	if (inside_parcel)
+		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING);
+	else 
+		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isAttachedToAnotherAvatar() const
+{
+	bool result = false;
+	
+	std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
+	std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
+	for ( ; iter != end; iter++)
+	{
+		if (isObjectAttachedToAnotherAvatar(*iter))
+		{
+			result = true;
+			break;
+		}
+	}
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+//static
+bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj)
+{
+	bool result = false;
+	LLXform *xform = obj;
+	// Walk up parent chain
+	while (NULL != xform)
+	{
+		LLViewerObject *object = dynamic_cast<LLViewerObject*> (xform);
+		if (NULL != object)
+		{
+			LLVOAvatar *avatar = object->asAvatar();
+			if ((NULL != avatar) && (avatar != gAgentAvatarp))
+			{
+				result = true;
+				break;
+			}
+		}
+		xform = xform->getParent();
+	}
+	return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isInAgentParcel() const
+{
+	bool result = false;
+	
+	std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
+	std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
+	for ( ; iter != end; iter++)
+	{
+		LLVOVolume *object = *iter;
+		if (LLViewerMediaImpl::isObjectInAgentParcel(object))
+		{
+			result = true;
+			break;
+		}
+	}
+	return result;
+}
+
+LLNotificationPtr LLViewerMediaImpl::getCurrentNotification() const
+{
+	return mNotification;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+// static
+bool LLViewerMediaImpl::isObjectInAgentParcel(LLVOVolume *obj)
+{
+	return (LLViewerParcelMgr::getInstance()->inAgentParcel(obj->getPositionGlobal()));
+}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index d958551a0a8b7dceb379922ac96c413558ca5f7e..b4ec3c135b73dad5f09ee62b8c32a43ee9bafbf0 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -37,6 +37,7 @@
 
 // newview includes
 #include "llagent.h"
+#include "llagentaccess.h"
 #include "llagentcamera.h"
 #include "llagentwearables.h"
 #include "llagentpilot.h"
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index c84a14f62c71833090d243fdcccd410004e0a0cf..5ae4e872f3dad6aa4287da779e0bf1906369881b 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -42,6 +42,7 @@
 
 // Viewer includes
 #include "llagent.h"
+#include "llagentaccess.h"
 #include "llviewerwindow.h"
 #include "llviewercontrol.h"
 //#include "llfirstuse.h"
@@ -54,6 +55,7 @@
 #include "llresmgr.h"
 #include "llsdutil.h"
 #include "llsdutil_math.h"
+#include "llslurl.h"
 #include "llstatusbar.h"
 #include "llui.h"
 #include "llviewertexture.h"
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index ab07adce5d3d26dfdd7942a604c87e759417bb18..45c9b3e91f24f88ca66927d041d1005886dc6dd1 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -99,8 +99,6 @@
 #include "llcoord.h"
 #include "llcoordframe.h"
 #include "llcrc.h"
-#include "llinterp.h"
-#include "llperlin.h"
 #include "llplane.h"
 #include "llquantize.h"
 #include "llrand.h"
@@ -109,7 +107,6 @@
 #include "m3math.h"
 #include "m4math.h"
 #include "llquaternion.h"
-#include "raytrace.h"
 #include "v2math.h"
 #include "v3color.h"
 #include "v3dmath.h"
@@ -117,16 +114,12 @@
 #include "v4color.h"
 #include "v4coloru.h"
 #include "v4math.h"
-////#include "vmath.h"
 #include "xform.h"
 
 // Library includes from llvfs
 #include "lldir.h"
-
-// Library includes from llmessage project
+
+// Library includes from llmessage project
 #include "llcachename.h"
 
-// llxuixml
-#include "llinitparam.h"
-
 #endif
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index c53fdc339338568347a32f0ce3c9e46f7710b05b..8909abf36ef42c7e1aeb9af7cf14584302306cb5 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -46,6 +46,7 @@
 #include "llagentcamera.h"
 #include "llcallingcard.h"
 #include "llcaphttpsender.h"
+#include "llcapabilitylistener.h"
 #include "llcommandhandler.h"
 #include "lldir.h"
 #include "lleventpoll.h"
@@ -76,6 +77,71 @@
 const F32 WATER_TEXTURE_SCALE = 8.f;			//  Number of times to repeat the water texture across a region
 const S16 MAX_MAP_DIST = 10;
 
+typedef std::map<std::string, std::string> CapabilityMap;
+
+class LLViewerRegionImpl {
+public:
+	LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host)
+		:	mHost(host),
+			mCompositionp(NULL),
+			mEventPoll(NULL),
+		    // I'd prefer to set the LLCapabilityListener name to match the region
+		    // name -- it's disappointing that's not available at construction time.
+		    // We could instead store an LLCapabilityListener*, making
+		    // setRegionNameAndZone() replace the instance. Would that pose
+		    // consistency problems? Can we even request a capability before calling
+		    // setRegionNameAndZone()?
+		    // For testability -- the new Michael Feathers paradigm --
+		    // LLCapabilityListener binds all the globals it expects to need at
+		    // construction time.
+		    mCapabilityListener(host.getString(), gMessageSystem, *region,
+		                        gAgent.getID(), gAgent.getSessionID())
+	{
+	}
+
+	// The surfaces and other layers
+	LLSurface*	mLandp;
+
+	// Region geometry data
+	LLVector3d	mOriginGlobal;	// Location of southwest corner of region (meters)
+	LLVector3d	mCenterGlobal;	// Location of center in world space (meters)
+	LLHost		mHost;
+
+	// The unique ID for this region.
+	LLUUID mRegionID;
+
+	// region/estate owner - usually null.
+	LLUUID mOwnerID;
+
+	// Network statistics for the region's circuit...
+	LLTimer mLastNetUpdate;
+
+	// Misc
+	LLVLComposition *mCompositionp;		// Composition layer for the surface
+
+	LLVOCacheEntry::vocache_entry_map_t		mCacheMap;
+	// time?
+	// LRU info?
+
+	// Cache ID is unique per-region, across renames, moving locations,
+	// etc.
+	LLUUID mCacheID;
+
+	CapabilityMap mCapabilities;
+	
+	LLEventPoll* mEventPoll;
+
+	/// Post an event to this LLCapabilityListener to invoke a capability message on
+	/// this LLViewerRegion's server
+	/// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
+	LLCapabilityListener mCapabilityListener;
+
+	//spatial partitions for objects in this region
+	std::vector<LLSpatialPartition*> mObjectPartition;
+
+	LLHTTPClient::ResponderPtr  mHttpResponderPtr ;
+};
+
 // support for secondlife:///app/region/{REGION} SLapps
 // N.B. this is defined to work exactly like the classic secondlife://{REGION}
 // However, the later syntax cannot support spaces in the region name because
@@ -191,15 +257,12 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 							   const U32 grids_per_region_edge, 
 							   const U32 grids_per_patch_edge, 
 							   const F32 region_width_meters)
-:	mCenterGlobal(),
+:	mImpl(new LLViewerRegionImpl(this, host)),
 	mHandle(handle),
-	mHost( host ),
 	mTimeDilation(1.0f),
 	mName(""),
 	mZoning(""),
-	mOwnerID(),
 	mIsEstateManager(FALSE),
-	mCompositionp(NULL),
 	mRegionFlags( REGION_FLAGS_DEFAULT ),
 	mSimAccess( SIM_ACCESS_MIN ),
 	mBillableFactor(1.0),
@@ -212,37 +275,27 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 	mHttpUrl(""),
 	mCacheLoaded(FALSE),
 	mCacheDirty(FALSE),
-	mCacheID(),
-	mEventPoll(NULL),
 	mReleaseNotesRequested(FALSE),
-    // I'd prefer to set the LLCapabilityListener name to match the region
-    // name -- it's disappointing that's not available at construction time.
-    // We could instead store an LLCapabilityListener*, making
-    // setRegionNameAndZone() replace the instance. Would that pose
-    // consistency problems? Can we even request a capability before calling
-    // setRegionNameAndZone()?
-    // For testability -- the new Michael Feathers paradigm --
-    // LLCapabilityListener binds all the globals it expects to need at
-    // construction time.
-    mCapabilityListener(host.getString(), gMessageSystem, *this,
-                        gAgent.getID(), gAgent.getSessionID()),
 	mCapabilitiesReceived(false)
 {
 	mWidth = region_width_meters;
-	mOriginGlobal = from_region_handle(handle); 
+	mImpl->mOriginGlobal = from_region_handle(handle); 
 	updateRenderMatrix();
 
-	mLandp = new LLSurface('l', NULL);
+	mImpl->mLandp = new LLSurface('l', NULL);
 
 	// Create the composition layer for the surface
-	mCompositionp = new LLVLComposition(mLandp, grids_per_region_edge, region_width_meters/grids_per_region_edge);
-	mCompositionp->setSurface(mLandp);
+	mImpl->mCompositionp =
+		new LLVLComposition(mImpl->mLandp,
+							grids_per_region_edge,
+							region_width_meters / grids_per_region_edge);
+	mImpl->mCompositionp->setSurface(mImpl->mLandp);
 
 	// Create the surfaces
-	mLandp->setRegion(this);
-	mLandp->create(grids_per_region_edge,
+	mImpl->mLandp->setRegion(this);
+	mImpl->mLandp->create(grids_per_region_edge,
 					grids_per_patch_edge,
-					mOriginGlobal,
+					mImpl->mOriginGlobal,
 					mWidth);
 
 	mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters);
@@ -255,24 +308,24 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 
 	//create object partitions
 	//MUST MATCH declaration of eObjectPartitions
-	mObjectPartition.push_back(new LLHUDPartition());		//PARTITION_HUD
-	mObjectPartition.push_back(new LLTerrainPartition());	//PARTITION_TERRAIN
-	mObjectPartition.push_back(new LLVoidWaterPartition());	//PARTITION_VOIDWATER
-	mObjectPartition.push_back(new LLWaterPartition());		//PARTITION_WATER
-	mObjectPartition.push_back(new LLTreePartition());		//PARTITION_TREE
-	mObjectPartition.push_back(new LLParticlePartition());	//PARTITION_PARTICLE
-	mObjectPartition.push_back(new LLCloudPartition());		//PARTITION_CLOUD
-	mObjectPartition.push_back(new LLGrassPartition());		//PARTITION_GRASS
-	mObjectPartition.push_back(new LLVolumePartition());	//PARTITION_VOLUME
-	mObjectPartition.push_back(new LLBridgePartition());	//PARTITION_BRIDGE
-	mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE
-	mObjectPartition.push_back(NULL);						//PARTITION_NONE
+	mImpl->mObjectPartition.push_back(new LLHUDPartition());		//PARTITION_HUD
+	mImpl->mObjectPartition.push_back(new LLTerrainPartition());	//PARTITION_TERRAIN
+	mImpl->mObjectPartition.push_back(new LLVoidWaterPartition());	//PARTITION_VOIDWATER
+	mImpl->mObjectPartition.push_back(new LLWaterPartition());		//PARTITION_WATER
+	mImpl->mObjectPartition.push_back(new LLTreePartition());		//PARTITION_TREE
+	mImpl->mObjectPartition.push_back(new LLParticlePartition());	//PARTITION_PARTICLE
+	mImpl->mObjectPartition.push_back(new LLCloudPartition());		//PARTITION_CLOUD
+	mImpl->mObjectPartition.push_back(new LLGrassPartition());		//PARTITION_GRASS
+	mImpl->mObjectPartition.push_back(new LLVolumePartition());	//PARTITION_VOLUME
+	mImpl->mObjectPartition.push_back(new LLBridgePartition());	//PARTITION_BRIDGE
+	mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE
+	mImpl->mObjectPartition.push_back(NULL);						//PARTITION_NONE
 }
 
 
 void LLViewerRegion::initStats()
 {
-	mLastNetUpdate.reset();
+	mImpl->mLastNetUpdate.reset();
 	mPacketsIn = 0;
 	mBitsIn = 0;
 	mLastBitsIn = 0;
@@ -287,9 +340,9 @@ void LLViewerRegion::initStats()
 
 LLViewerRegion::~LLViewerRegion() 
 {
-	if(mHttpResponderPtr)
+	if(mImpl->mHttpResponderPtr)
 	{
-		(static_cast<BaseCapabilitiesComplete*>(mHttpResponderPtr.get()))->setRegion(NULL) ;
+		(static_cast<BaseCapabilitiesComplete*>(mImpl->mHttpResponderPtr.get()))->setRegion(NULL) ;
 	}
 
 	gVLManager.cleanupData(this);
@@ -301,21 +354,44 @@ LLViewerRegion::~LLViewerRegion()
 
 	gObjectList.killObjects(this);
 
-	delete mCompositionp;
+	delete mImpl->mCompositionp;
 	delete mParcelOverlay;
-	delete mLandp;
-	delete mEventPoll;
-	LLHTTPSender::clearSender(mHost);
+	delete mImpl->mLandp;
+	delete mImpl->mEventPoll;
+	LLHTTPSender::clearSender(mImpl->mHost);
 	
 	saveObjectCache();
 
-	std::for_each(mObjectPartition.begin(), mObjectPartition.end(), DeletePointer());
+	std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
+
+	delete mImpl;
+	mImpl = NULL;
+}
+
+LLEventPump& LLViewerRegion::getCapAPI() const
+{
+	return mImpl->mCapabilityListener.getCapAPI();
 }
 
 /*virtual*/ 
 const LLHost&	LLViewerRegion::getHost() const				
 { 
-	return mHost; 
+	return mImpl->mHost; 
+}
+
+LLSurface & LLViewerRegion::getLand() const
+{
+	return *mImpl->mLandp;
+}
+
+const LLUUID& LLViewerRegion::getRegionID() const
+{
+	return mImpl->mRegionID;
+}
+
+void LLViewerRegion::setRegionID(const LLUUID& region_id)
+{
+	mImpl->mRegionID = region_id;
 }
 
 void LLViewerRegion::loadObjectCache()
@@ -330,7 +406,7 @@ void LLViewerRegion::loadObjectCache()
 
 	if(LLVOCache::hasInstance())
 	{
-		LLVOCache::getInstance()->readFromCache(mHandle, mCacheID, mCacheMap) ;
+		LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ;
 	}
 }
 
@@ -342,32 +418,32 @@ void LLViewerRegion::saveObjectCache()
 		return;
 	}
 
-	if (mCacheMap.empty())
+	if (mImpl->mCacheMap.empty())
 	{
 		return;
 	}
 
 	if(LLVOCache::hasInstance())
 	{
-		LLVOCache::getInstance()->writeToCache(mHandle, mCacheID, mCacheMap, mCacheDirty) ;
+		LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ;
 		mCacheDirty = FALSE;
 	}
 
-	for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mCacheMap.begin(); iter != mCacheMap.end(); ++iter)
+	for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter)
 	{
 		delete iter->second;
 	}
-	mCacheMap.clear();
+	mImpl->mCacheMap.clear();
 }
 
 void LLViewerRegion::sendMessage()
 {
-	gMessageSystem->sendMessage(mHost);
+	gMessageSystem->sendMessage(mImpl->mHost);
 }
 
 void LLViewerRegion::sendReliableMessage()
 {
-	gMessageSystem->sendReliable(mHost);
+	gMessageSystem->sendReliable(mImpl->mHost);
 }
 
 void LLViewerRegion::setFlags(BOOL b, U32 flags)
@@ -384,12 +460,12 @@ void LLViewerRegion::setFlags(BOOL b, U32 flags)
 
 void LLViewerRegion::setWaterHeight(F32 water_level)
 {
-	mLandp->setWaterHeight(water_level);
+	mImpl->mLandp->setWaterHeight(water_level);
 }
 
 F32 LLViewerRegion::getWaterHeight() const
 {
-	return mLandp->getWaterHeight();
+	return mImpl->mLandp->getWaterHeight();
 }
 
 BOOL LLViewerRegion::isVoiceEnabled() const
@@ -405,9 +481,9 @@ void LLViewerRegion::setRegionFlags(U32 flags)
 
 void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) 
 { 
-	mOriginGlobal = origin_global; 
+	mImpl->mOriginGlobal = origin_global; 
 	updateRenderMatrix();
-	mLandp->setOriginGlobal(origin_global);
+	mImpl->mLandp->setOriginGlobal(origin_global);
 	mWind.setOriginGlobal(origin_global);
 	mCloudLayer.setOriginGlobal(origin_global);
 	calculateCenterGlobal();
@@ -423,16 +499,34 @@ void LLViewerRegion::setTimeDilation(F32 time_dilation)
 	mTimeDilation = time_dilation;
 }
 
+const LLVector3d & LLViewerRegion::getOriginGlobal() const
+{
+	return mImpl->mOriginGlobal;
+}
 
 LLVector3 LLViewerRegion::getOriginAgent() const
 {
-	return gAgent.getPosAgentFromGlobal(mOriginGlobal);
+	return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal);
 }
 
+const LLVector3d & LLViewerRegion::getCenterGlobal() const
+{
+	return mImpl->mCenterGlobal;
+}
 
 LLVector3 LLViewerRegion::getCenterAgent() const
 {
-	return gAgent.getPosAgentFromGlobal(mCenterGlobal);
+	return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal);
+}
+
+void LLViewerRegion::setOwner(const LLUUID& owner_id)
+{
+	mImpl->mOwnerID = owner_id;
+}
+
+const LLUUID& LLViewerRegion::getOwner() const
+{
+	return mImpl->mOwnerID;
 }
 
 void LLViewerRegion::setRegionNameAndZone	(const std::string& name_zone)
@@ -557,7 +651,10 @@ void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
 	LLFloaterReporter::processRegionInfo(msg);
 }
 
-
+void LLViewerRegion::setCacheID(const LLUUID& id)
+{
+	mImpl->mCacheID = id;
+}
 
 S32 LLViewerRegion::renderPropertyLines()
 {
@@ -585,7 +682,7 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
 {
 	LLMemType mt_ivr(LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION);
 	// did_update returns TRUE if we did at least one significant update
-	BOOL did_update = mLandp->idleUpdate(max_update_time);
+	BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time);
 	
 	if (mParcelOverlay)
 	{
@@ -600,7 +697,7 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
 // As above, but forcibly do the update.
 void LLViewerRegion::forceUpdate()
 {
-	mLandp->idleUpdate(0.f);
+	mImpl->mLandp->idleUpdate(0.f);
 
 	if (mParcelOverlay)
 	{
@@ -610,17 +707,21 @@ void LLViewerRegion::forceUpdate()
 
 void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction)
 {
-	mLandp->connectNeighbor(neighborp->mLandp, direction);
+	mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction);
 	mCloudLayer.connectNeighbor(&(neighborp->mCloudLayer), direction);
 }
 
 
 void LLViewerRegion::disconnectAllNeighbors()
 {
-	mLandp->disconnectAllNeighbors();
+	mImpl->mLandp->disconnectAllNeighbors();
 	mCloudLayer.disconnectAllNeighbors();
 }
 
+LLVLComposition * LLViewerRegion::getComposition() const
+{
+	return mImpl->mCompositionp;
+}
 
 F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const
 {
@@ -714,10 +815,10 @@ F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const
 
 void LLViewerRegion::calculateCenterGlobal() 
 {
-	mCenterGlobal = mOriginGlobal;
-	mCenterGlobal.mdV[VX] += 0.5 * mWidth;
-	mCenterGlobal.mdV[VY] += 0.5 * mWidth;
-	mCenterGlobal.mdV[VZ] = 0.5*mLandp->getMinZ() + mLandp->getMaxZ();
+	mImpl->mCenterGlobal = mImpl->mOriginGlobal;
+	mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth;
+	mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth;
+	mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ();
 }
 
 void LLViewerRegion::calculateCameraDistance()
@@ -728,7 +829,7 @@ void LLViewerRegion::calculateCameraDistance()
 std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region)
 {
 	s << "{ ";
-	s << region.mHost;
+	s << region.mImpl->mHost;
 	s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n";
     std::string name(region.getName()), zone(region.getZoning());
     if (! name.empty())
@@ -748,9 +849,9 @@ std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region)
 
 void LLViewerRegion::updateNetStats()
 {
-	F32 dt = mLastNetUpdate.getElapsedTimeAndResetF32();
+	F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32();
 
-	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mHost);
+	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost);
 	if (!cdp)
 	{
 		mAlive = false;
@@ -779,10 +880,10 @@ void LLViewerRegion::updateNetStats()
 
 U32 LLViewerRegion::getPacketsLost() const
 {
-	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mHost);
+	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost);
 	if (!cdp)
 	{
-		llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mHost << llendl;
+		llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << llendl;
 		return 0;
 	}
 	else
@@ -791,6 +892,16 @@ U32 LLViewerRegion::getPacketsLost() const
 	}
 }
 
+void LLViewerRegion::setHttpResponderPtrNULL()
+{
+	mImpl->mHttpResponderPtr = NULL;
+}
+
+const LLHTTPClient::ResponderPtr LLViewerRegion::getHttpResponderPtr() const
+{
+	return mImpl->mHttpResponderPtr;
+}
+
 BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const
 {
 	LLVector3 pos_region = getPosRegionFromGlobal(point_global);
@@ -817,7 +928,7 @@ BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const
 LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const
 {
 	LLVector3 pos_region;
-	pos_region.setVec(point_global - mOriginGlobal);
+	pos_region.setVec(point_global - mImpl->mOriginGlobal);
 	return pos_region;
 }
 
@@ -825,7 +936,7 @@ LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) c
 {
 	LLVector3d pos_region_d;
 	pos_region_d.setVec(pos_region);
-	return pos_region_d + mOriginGlobal;
+	return pos_region_d + mImpl->mOriginGlobal;
 }
 
 LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const
@@ -842,7 +953,7 @@ LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) cons
 
 F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos)
 {
-	return mLandp->resolveHeightRegion( region_pos );
+	return mImpl->mLandp->resolveHeightRegion( region_pos );
 }
 
 bool LLViewerRegion::isAlive()
@@ -994,7 +1105,7 @@ void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
 		// treat the target specially for the map
 		if(i == target_index)
 		{
-			LLVector3d global_pos(mOriginGlobal);
+			LLVector3d global_pos(mImpl->mOriginGlobal);
 			global_pos.mdV[VX] += (F64)(x_pos);
 			global_pos.mdV[VY] += (F64)(y_pos);
 			global_pos.mdV[VZ] += (F64)(z_pos) * 4.0;
@@ -1034,7 +1145,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
 	U32 local_id = objectp->getLocalID();
 	U32 crc = objectp->getCRC();
 
-	LLVOCacheEntry* entry = get_if_there(mCacheMap, local_id, (LLVOCacheEntry*)NULL);
+	LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
 
 	if (entry)
 	{
@@ -1047,10 +1158,10 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
 		}
 
 		// Update the cache entry
-		mCacheMap.erase(local_id);
+		mImpl->mCacheMap.erase(local_id);
 		delete entry;
 		entry = new LLVOCacheEntry(local_id, crc, dp);
-		mCacheMap[local_id] = entry;
+		mImpl->mCacheMap[local_id] = entry;
 		return CACHE_UPDATE_CHANGED;
 	}
 
@@ -1058,15 +1169,15 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
 
 	// Create new entry and add to map
 	eCacheUpdateResult result = CACHE_UPDATE_ADDED;
-	if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
+	if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
 	{
-		mCacheMap.erase(mCacheMap.begin());
+		mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());
 		result = CACHE_UPDATE_REPLACED;
 		
 	}
 	entry = new LLVOCacheEntry(local_id, crc, dp);
 
-	mCacheMap[local_id] = entry;
+	mImpl->mCacheMap[local_id] = entry;
 	return result;
 }
 
@@ -1076,7 +1187,7 @@ LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)
 {
 	llassert(mCacheLoaded);
 
-	LLVOCacheEntry* entry = get_if_there(mCacheMap, local_id, (LLVOCacheEntry*)NULL);
+	LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
 
 	if (entry)
 	{
@@ -1203,7 +1314,7 @@ void LLViewerRegion::dumpCache()
 	}
 
 	LLVOCacheEntry *entry;
-	for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mCacheMap.begin(); iter != mCacheMap.end(); ++iter)
+	for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter)
 	{
 		entry = iter->second ;
 
@@ -1217,7 +1328,7 @@ void LLViewerRegion::dumpCache()
 		change_bin[changes]++;
 	}
 
-	llinfos << "Count " << mCacheMap.size() << llendl;
+	llinfos << "Count " << mImpl->mCacheMap.size() << llendl;
 	for (i = 0; i < BINS; i++)
 	{
 		llinfos << "Hits " << i << " " << hit_bin[i] << llendl;
@@ -1360,10 +1471,10 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 		return;
     }
 	
-	delete mEventPoll;
-	mEventPoll = NULL;
+	delete mImpl->mEventPoll;
+	mImpl->mEventPoll = NULL;
 	
-	mCapabilities.clear();
+	mImpl->mCapabilities.clear();
 	setCapability("Seed", url);
 
 	LLSD capabilityNames = LLSD::emptyArray();
@@ -1430,25 +1541,25 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 
 	llinfos << "posting to seed " << url << llendl;
 
-	mHttpResponderPtr = BaseCapabilitiesComplete::build(this) ;
-	LLHTTPClient::post(url, capabilityNames, mHttpResponderPtr);
+	mImpl->mHttpResponderPtr = BaseCapabilitiesComplete::build(this) ;
+	LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);
 }
 
 void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
 {
 	if(name == "EventQueueGet")
 	{
-		delete mEventPoll;
-		mEventPoll = NULL;
-		mEventPoll = new LLEventPoll(url, getHost());
+		delete mImpl->mEventPoll;
+		mImpl->mEventPoll = NULL;
+		mImpl->mEventPoll = new LLEventPoll(url, getHost());
 	}
 	else if(name == "UntrustedSimulatorMessage")
 	{
-		LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url));
+		LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
 	}
 	else
 	{
-		mCapabilities[name] = url;
+		mImpl->mCapabilities[name] = url;
 		if(name == "GetTexture")
 		{
 			mHttpUrl = url ;
@@ -1463,8 +1574,8 @@ bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
 
 std::string LLViewerRegion::getCapability(const std::string& name) const
 {
-	CapabilityMap::const_iterator iter = mCapabilities.find(name);
-	if(iter == mCapabilities.end())
+	CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
+	if(iter == mImpl->mCapabilities.end())
 	{
 		return "";
 	}
@@ -1485,7 +1596,7 @@ void LLViewerRegion::logActiveCapabilities() const
 {
 	int count = 0;
 	CapabilityMap::const_iterator iter;
-	for (iter = mCapabilities.begin(); iter != mCapabilities.end(); iter++, count++)
+	for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count)
 	{
 		if (!iter->second.empty())
 		{
@@ -1497,9 +1608,9 @@ void LLViewerRegion::logActiveCapabilities() const
 
 LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
 {
-	if (type < mObjectPartition.size())
+	if (type < mImpl->mObjectPartition.size())
 	{
-		return mObjectPartition[type];
+		return mImpl->mObjectPartition[type];
 	}
 	return NULL;
 }
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index dd40b876cd4c24173ab0104d8f9374946ff50981..9c5b85b77f58a745abfdf757a0770d557ae2865b 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -33,20 +33,16 @@
 
 #include "lldarray.h"
 #include "llwind.h"
-#include "llbbox.h"
 #include "llcloud.h"
 #include "llstat.h"
 #include "v3dmath.h"
-#include "llhost.h"
 #include "llstring.h"
 #include "llregionflags.h"
 #include "lluuid.h"
-#include "lldatapacker.h"
-#include "llvocache.h"
 #include "llweb.h"
 #include "llcapabilityprovider.h"
-#include "llcapabilitylistener.h"
 #include "m4math.h"					// LLMatrix4
+#include "llhttpclient.h"
 
 // Surface id's
 #define LAND  1
@@ -65,6 +61,13 @@ class LLVOCache;
 class LLVOCacheEntry;
 class LLSpatialPartition;
 class LLEventPump;
+class LLCapabilityListener;
+class LLDataPacker;
+class LLDataPackerBinaryBuffer;
+class LLHost;
+class LLBBox;
+
+class LLViewerRegionImpl;
 
 class LLViewerRegion: public LLCapabilityProvider // implements this interface
 {
@@ -159,19 +162,19 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	F32  getTimeDilation() const				{ return mTimeDilation; }
 
 	// Origin height is at zero.
-	const LLVector3d &getOriginGlobal() const	{ return mOriginGlobal; }
+	const LLVector3d &getOriginGlobal() const;
 	LLVector3 getOriginAgent() const;
 
 	// Center is at the height of the water table.
-	const LLVector3d &getCenterGlobal() const	{ return mCenterGlobal; }
+	const LLVector3d &getCenterGlobal() const;
 	LLVector3 getCenterAgent() const;
 
 	void setRegionNameAndZone(const std::string& name_and_zone);
 	const std::string& getName() const				{ return mName; }
 	const std::string& getZoning() const			{ return mZoning; }
 
-	void setOwner(const LLUUID& owner_id) { mOwnerID = owner_id; }
-	const LLUUID& getOwner() const { return mOwnerID; }
+	void setOwner(const LLUUID& owner_id);
+	const LLUUID& getOwner() const;
 
 	// Is the current agent on the estate manager list for this region?
 	void setIsEstateManager(BOOL b) { mIsEstateManager = b; }
@@ -206,7 +209,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	// can process the message.
 	static void processRegionInfo(LLMessageSystem* msg, void**);
 
-	void setCacheID(const LLUUID& id)			{ mCacheID = id; }
+	void setCacheID(const LLUUID& id);
 
 	F32	getWidth() const						{ return mWidth; }
 
@@ -222,8 +225,8 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	U32	getPacketsLost() const;
 
-	void setHttpResponderPtrNULL() {mHttpResponderPtr = NULL ;}
-	const LLHTTPClient::ResponderPtr getHttpResponderPtr() const {return mHttpResponderPtr ;}
+	void setHttpResponderPtrNULL();
+	const LLHTTPClient::ResponderPtr getHttpResponderPtr() const;
 
 	// Get/set named capability URLs for this region.
 	void setSeedCapability(const std::string& url);
@@ -238,21 +241,19 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	static bool isSpecialCapabilityName(const std::string &name);
 	void logActiveCapabilities() const;
 
-    /// Capability-request exception
-    typedef LLCapabilityListener::ArgError ArgError;
     /// Get LLEventPump on which we listen for capability requests
     /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
-    LLEventPump& getCapAPI() { return mCapabilityListener.getCapAPI(); }
+    LLEventPump& getCapAPI() const;
 
     /// implements LLCapabilityProvider
 	/*virtual*/ const LLHost& getHost() const;
 	const U64 		&getHandle() const 			{ return mHandle; }
 
-	LLSurface		&getLand() const			{ return *mLandp; }
+	LLSurface		&getLand() const;
 
 	// set and get the region id
-	const LLUUID& getRegionID() const { return mRegionID; }
-	void setRegionID(const LLUUID& region_id) { mRegionID = region_id; }
+	const LLUUID& getRegionID() const;
+	void setRegionID(const LLUUID& region_id);
 
 	BOOL pointInRegionGlobal(const LLVector3d &point_global) const;
 	LLVector3	getPosRegionFromGlobal(const LLVector3d &point_global) const;
@@ -260,7 +261,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	LLVector3	getPosAgentFromRegion(const LLVector3 &region_pos) const;
 	LLVector3d	getPosGlobalFromRegion(const LLVector3 &offset) const;
 
-	LLVLComposition *getComposition() const		{ return mCompositionp; }
+	LLVLComposition *getComposition() const;
 	F32 getCompositionXY(const S32 x, const S32 y) const;
 
 	BOOL isOwnedSelf(const LLVector3& pos);
@@ -347,34 +348,19 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	LLDynamicArray<LLUUID> mMapAvatarIDs;
 
 private:
-	// The surfaces and other layers
-	LLSurface*	mLandp;
+	LLViewerRegionImpl * mImpl;
 
-	// Region geometry data
-	LLVector3d	mOriginGlobal;	// Location of southwest corner of region (meters)
-	LLVector3d	mCenterGlobal;	// Location of center in world space (meters)
 	F32			mWidth;			// Width of region on a side (meters)
-
 	U64			mHandle;
-	LLHost		mHost;
-
-	// The unique ID for this region.
-	LLUUID mRegionID;
-
 	F32			mTimeDilation;	// time dilation of physics simulation on simulator
 
 	// simulator name
 	std::string mName;
 	std::string mZoning;
 
-	// region/estate owner - usually null.
-	LLUUID mOwnerID;
-
 	// Is this agent on the estate managers list for this region?
 	BOOL mIsEstateManager;
 
-	// Network statistics for the region's circuit...
-	LLTimer mLastNetUpdate;
 	U32		mPacketsIn;
 	U32		mBitsIn;
 	U32		mLastBitsIn;
@@ -386,9 +372,6 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	U32		mPingDelay;
 	F32		mDeltaTime;				// Time since last measurement of lastPackets, Bits, etc
 
-	// Misc
-	LLVLComposition *mCompositionp;		// Composition layer for the surface
-
 	U32		mRegionFlags;			// includes damage flags
 	U8		mSimAccess;
 	F32 	mBillableFactor;
@@ -398,46 +381,24 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	// Information for Homestead / CR-53
 	S32 mClassID;
 	S32 mCPURatio;
+
 	std::string mColoName;
 	std::string mProductSKU;
 	std::string mProductName;
 	std::string mHttpUrl ;
 	
-	
 	// Maps local ids to cache entries.
 	// Regions can have order 10,000 objects, so assume
 	// a structure of size 2^14 = 16,000
 	BOOL									mCacheLoaded;
 	BOOL                                    mCacheDirty;
-	LLVOCacheEntry::vocache_entry_map_t		mCacheMap;
+
 	LLDynamicArray<U32>						mCacheMissFull;
 	LLDynamicArray<U32>						mCacheMissCRC;
-	// time?
-	// LRU info?
 
-	// Cache ID is unique per-region, across renames, moving locations,
-	// etc.
-	LLUUID mCacheID;
-
-	typedef std::map<std::string, std::string> CapabilityMap;
-	CapabilityMap mCapabilities;
-	
-	LLEventPoll* mEventPoll;
-
-    /// Post an event to this LLCapabilityListener to invoke a capability message on
-    /// this LLViewerRegion's server
-    /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
-    LLCapabilityListener mCapabilityListener;
-
-private:
 	bool	mAlive;					// can become false if circuit disconnects
 	bool	mCapabilitiesReceived;
 
-	//spatial partitions for objects in this region
-	std::vector<LLSpatialPartition*> mObjectPartition;
-
-	LLHTTPClient::ResponderPtr  mHttpResponderPtr ;
-
 	BOOL mReleaseNotesRequested;
 };
 
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 27aab0c08191209fe2431fbc0b4ea3db522f5a04..d02b6be6b5d8ec73b6d00677ad9c652f9c3a6fcc 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -217,24 +217,24 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIIm
 {
 public:
 	// LLImageProviderInterface
-	/*virtual*/ LLUIImagePtr getUIImageByID(const LLUUID& id, S32 priority);
-	/*virtual*/ LLUIImagePtr getUIImage(const std::string& name, S32 priority);
+	/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority);
+	/*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority);
 	void cleanUp();
 
 	bool initFromFile();
 
-	LLUIImagePtr preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect);
+	LLPointer<LLUIImage> preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect);
 	
 	static void onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
 private:
-	LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename,
+	LLPointer<LLUIImage> loadUIImageByName(const std::string& name, const std::string& filename,
 		                           BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, 
 		                           LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI);
-	LLUIImagePtr loadUIImageByID(const LLUUID& id,
+	LLPointer<LLUIImage> loadUIImageByID(const LLUUID& id,
 								 BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, 
 								 LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI);
 
-	LLUIImagePtr loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
+	LLPointer<LLUIImage> loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
 
 
 	struct LLUIImageLoadData
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index e0202968429b6f87fd0d4e54d4709ba729689667..7728958ed8090a3400c6abde6f5e768aeca93f2b 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -79,6 +79,7 @@
 #include "lltooltip.h"
 #include "llmediaentry.h"
 #include "llurldispatcher.h"
+#include "raytrace.h"
 
 // newview includes
 #include "llagent.h"
@@ -234,17 +235,12 @@ BOOL				gDisplayCameraPos = FALSE;
 BOOL				gDisplayFOV = FALSE;
 BOOL				gDisplayBadge = FALSE;
 
-S32 CHAT_BAR_HEIGHT = 28; 
-S32 OVERLAY_BAR_HEIGHT = 20;
-
-const U8 NO_FACE = 255;
+static const U8 NO_FACE = 255;
 BOOL gQuietSnapshot = FALSE;
 
 const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before coming back
-const F32 MAX_FAST_FRAME_TIME = 0.5f;
-const F32 FAST_FRAME_INCREMENT = 0.1f;
 
-const F32 MIN_DISPLAY_SCALE = 0.75f;
+static const F32 MIN_DISPLAY_SCALE = 0.75f;
 
 std::string	LLViewerWindow::sSnapshotBaseName;
 std::string	LLViewerWindow::sSnapshotDir;
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 5eeb02b080409719e36de2205151a313fc430e13..bb0023b787a3b80400b180993f287fd2c66823c2 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -38,13 +38,12 @@
 
 #include "v3dmath.h"
 #include "v2math.h"
+#include "llcursortypes.h"
 #include "llwindowcallbacks.h"
 #include "lltimer.h"
 #include "llstat.h"
 #include "llmousehandler.h"
-#include "llcursortypes.h"
 #include "llhandle.h"
-#include "llimage.h"
 
 #include <boost/function.hpp>
 #include <boost/signals2.hpp>
@@ -59,6 +58,7 @@ class LLTool;
 class LLVelocityBar;
 class LLPanel;
 class LLImageRaw;
+class LLImageFormatted;
 class LLHUDIcon;
 class LLWindow;
 class LLRootView;
@@ -465,12 +465,6 @@ class LLViewerWindow : public LLWindowCallbacks
 	LLPointer<LLViewerObject>	mDragHoveredObject;
 };
 
-void toggle_flying(void*);
-void toggle_first_person();
-void toggle_build(void*);
-void reset_viewer_state_on_sim(void);
-void update_saved_window_size(const std::string& control,S32 delta_width, S32 delta_height);
-
 //
 // Globals
 //
@@ -487,8 +481,6 @@ extern LLVector3        gDebugRaycastNormal;
 extern LLVector3        gDebugRaycastBinormal;
 extern S32				gDebugRaycastFaceHit;
 
-extern S32 CHAT_BAR_HEIGHT; 
-
 extern BOOL			gDisplayCameraPos;
 extern BOOL			gDisplayWindInfo;
 extern BOOL			gDisplayFOV;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f1934933b5422f12ded92fb1ddc253dc2c332134..79866dc5d2bdda90cef4d3b719979e0afb5ae4aa 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -38,9 +38,9 @@
 #include <ctype.h>
 
 #include "llaudioengine.h"
-#include "llcachename.h"
 #include "noise.h"
 #include "sound_ids.h"
+#include "raytrace.h"
 
 #include "llagent.h" //  Get state values from here
 #include "llagentcamera.h"
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 37a974be284ebe0e34107552189a247ef688ae3d..46025b46bea9887daa7d2adb9b96cf176e172f96 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -50,6 +50,7 @@
 #include "pipeline.h"
 #include "llspatialpartition.h"
 #include "llnotificationsutil.h"
+#include "raytrace.h"
 
 extern LLPipeline gPipeline;
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index a207d3e050d3f7ff417d8af42b1f7c79f4534995..ee54a938ba75f554dc193f4e6347960b43ce1331 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -63,6 +63,8 @@
 #include "llmediadataclient.h"
 #include "llagent.h"
 #include "llviewermediafocus.h"
+#include "lldatapacker.h"
+#include "llvocache.h"
 
 const S32 MIN_QUIET_FRAMES_COALESCE = 30;
 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 4b3a9a4dc37b8c00a5b9303ec166004da00e1970..67bb965f99e913ed6f88e50344b5dad9e5871559 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -33,6 +33,7 @@
 #include "pipeline.h"
 #include "llsky.h"
 
+#include "lldiriterator.h"
 #include "llfloaterreg.h"
 #include "llsliderctrl.h"
 #include "llspinctrl.h"
@@ -87,11 +88,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
 	std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", ""));
 	LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL;
 			
-	bool found = true;			
+	bool found = true;
+	LLDirIterator app_settings_iter(path_name, "*.xml");
 	while(found) 
 	{
 		std::string name;
-		found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name);
+		found = app_settings_iter.next(name);
 		if(found)
 		{
 
@@ -113,11 +115,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
 	std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));
 	LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL;
 			
-	found = true;			
+	found = true;
+	LLDirIterator user_settings_iter(path_name2, "*.xml");
 	while(found) 
 	{
 		std::string name;
-		found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name);
+		found = user_settings_iter.next(name);
 		if(found)
 		{
 			name=name.erase(name.length()-4);
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index e5f52dfc979b5ef4cd09c8366d6b5263d541b9ba..848efcbb49e5f8e28f3bd393df7767dd003b27ee 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -31,6 +31,7 @@
 #include "pipeline.h"
 #include "llsky.h"
 
+#include "lldiriterator.h"
 #include "llfloaterreg.h"
 #include "llsliderctrl.h"
 #include "llspinctrl.h"
@@ -100,11 +101,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
 	std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", ""));
 	LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL;
 			
-	bool found = true;			
+	bool found = true;
+	LLDirIterator app_settings_iter(path_name, "*.xml");
 	while(found) 
 	{
 		std::string name;
-		found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name);
+		found = app_settings_iter.next(name);
 		if(found)
 		{
 
@@ -126,11 +128,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
 	std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));
 	LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL;
 			
-	found = true;			
+	found = true;
+	LLDirIterator user_settings_iter(path_name2, "*.xml");
 	while(found) 
 	{
 		std::string name;
-		found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name);
+		found = user_settings_iter.next(name);
 		if(found)
 		{
 			name=name.erase(name.length()-4);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 8f500414745079de5f68f0cb4f63c98827b81f5a..fd42058c8ab8a6c3ca283d80211c1cc02696c4e2 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -50,6 +50,7 @@
 #include "llviewerstats.h"
 #include "llvlcomposition.h"
 #include "llvoavatar.h"
+#include "llvocache.h"
 #include "llvowater.h"
 #include "message.h"
 #include "pipeline.h"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 85182c1c28b1bef114034e2f06ee3d7731ccac39..d0603cb30ee19b85953330b38d5beb0abb5907dd 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -1856,26 +1856,26 @@ even though the user gets a free copy.
             <spinner
              follows="left|top"
              height="19"
-             increment="0.025"
+             increment="0.02"
              initial_value="0"
              label="B"
              label_width="10"
              layout="topleft"
              left_delta="0"
-             max_val="0.95"
+             max_val="0.98"
              name="Path Limit Begin"
              top_pad="3"
              width="68" />
             <spinner
              follows="left|top"
              height="19"
-             increment="0.025"
+             increment="0.02"
              initial_value="1"
              label="E"
              label_width="10"
              layout="topleft"
              left_pad="10"
-             min_val="0.05"
+             min_val="0.02"
              name="Path Limit End"
              top_delta="0"
              width="68" />
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 06614dd218cc6a03a38d73224872e31b58563a72..d0dd63924942567ebbbd9184615e8f6227e76d2e 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6820,7 +6820,7 @@ Deed to group failed.
    name="ReleaseLandThrottled"
    type="notifytip">
 The parcel [PARCEL_NAME] can not be abandoned at this time.
-   tag>fail</tag>
+   <tag>fail</tag>
   </notification>
 	
   <notification
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index 75126e74c569a16fc8c1017a027667723e219bc6..5a913c4c9da18d37d6bc4fbef1f96afa4b26af76 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -3588,6 +3588,9 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE].
 	<string name="conference-title-incoming">
 		Conferencia con [AGENT_NAME]
 	</string>
+	<string name="inventory_item_offered-im">
+		Ofrecido el item del inventario
+	</string>
 	<string name="no_session_message">
 		(La sesión de MI no existe)
 	</string>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 6466f42c7559990388d9a0379f2cae9f588c32b8..1dbbcafb0e91170d297f4f6959c25bdd18a8407a 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -3587,6 +3587,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 	<string name="conference-title-incoming">
 		Conversa com [AGENT_NAME]
 	</string>
+	<string name="inventory_item_offered-im">
+		Oferta de item de inventário
+	</string>
 	<string name="no_session_message">
 		(Sessão de MI inexistente)
 	</string>
diff --git a/indra/newview/skins/default/xui/zh/panel_login.xml b/indra/newview/skins/default/xui/zh/panel_login.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d094ff731741ae089b9e10922afa20fd86dfbde
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_login.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_login">	
+	<layout_stack name="login_widgets">
+		<layout_panel name="login">
+			<text name="username_text">
+				使用者名稱:
+			</text>			
+			<text name="password_text">
+				密碼:
+			</text>
+			<check_box label="記住密碼" name="remember_check"/>
+			<button label="登入" name="connect_btn"/>
+			<text name="mode_selection_text">
+				模式:
+			</text>
+			<combo_box name="mode_combo" tool_tip="選擇一個登入模式">
+				<combo_box.item label="基礎" name="Basic"/>
+				<combo_box.item label="進階" name="Advanced"/>
+			</combo_box>
+			<text name="start_location_text">
+				開始地點:
+			</text>
+			<combo_box name="start_location_combo">
+				<combo_box.item label="上一次的地點" name="MyLastLocation"/>
+				<combo_box.item label="我的家" name="MyHome"/>
+				<combo_box.item label="&lt;輸入區域名&gt;" name="Typeregionname"/>
+			</combo_box>
+		</layout_panel>
+		<layout_panel name="links">
+			<text name="create_new_account_text">
+				註冊
+			</text>
+			<text name="forgot_password_text">
+				忘記使用者名稱或密碼?
+			</text>
+			<text name="login_help">
+				如何登入?
+			</text>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
index 9a6e08ee840e3adb99a024f3b74561dae119961e..ed66066b0ad840f97dc044d79c2b9396b0dac239 100644
--- a/indra/newview/tests/llremoteparcelrequest_test.cpp
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -35,7 +35,6 @@
 #include "llurlentry.h"
 
 namespace {
-	LLControlGroup s_saved_settings("dummy_settings");
 	const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111");
 }
 
@@ -64,13 +63,12 @@ LLMessageSystem * gMessageSystem;
 char const* const _PREHASH_AgentID = 0;   // never dereferenced during this test
 char const* const _PREHASH_AgentData = 0; // never dereferenced during this test
 LLAgent gAgent;
-LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { }
+LLAgent::LLAgent() : mAgentAccess(NULL) { }
 LLAgent::~LLAgent() { }
 void LLAgent::sendReliableMessage(void) { }
 LLUUID gAgentSessionID;
 LLUUID gAgentID;
 LLUIColor::LLUIColor(void) { }
-LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }
 LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
 LLControlGroup::~LLControlGroup(void) { }
 void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { }
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
index b425b50c8bd36a2be38d959b586c880bdb867ceb..710881d81124587d8dcb5512a030732880b87c8b 100644
--- a/indra/newview/tests/llviewerhelputil_test.cpp
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -73,11 +73,9 @@ static void substitute_string(std::string &input, const std::string &search, con
 }
 
 #include "../llagent.h"
-LLAgent::LLAgent() : mAgentAccess(gSavedSettings) { }
+LLAgent::LLAgent() : mAgentAccess(NULL) { }
 LLAgent::~LLAgent() { }
 bool LLAgent::isGodlike() const { return FALSE; }
-LLAgentAccess::LLAgentAccess(LLControlGroup& settings) : mSavedSettings(settings) { }
-LLUIColor::LLUIColor() {}
 
 LLAgent gAgent;
 
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
index 88ab5a22845fe1b774dce553b4eb3c049d918ea6..e19d5724f172b5bdc552d2243007611b285076e6 100644
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -59,12 +59,6 @@ class LLDir_Mock : public LLDir
 		return 0;
 	}
 
-	BOOL getNextFileInDir(const std::string &dirname, 
-						  const std::string &mask, 
-						  std::string &fname) 
-	{
-		return false;
-	}
 	void getRandomFileInDir(const std::string &dirname, 
 							const std::string &mask, 
 							std::string &fname) {}