diff --git a/.gitignore b/.gitignore
index 2d32e94c782df03ab0c3fdf58e0e07d1b43a32fa..a73a85e84f83e108a493f448dcb5546f860c45d1 100755
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,7 @@ indra/web/doc/asset-upload/plugins/verify-texture
 installed.xml
 libraries
 tarfile_tmp
+trivial_change_force_build
 web/config.*
 web/locale.*
 web/secondlife.com.*
\ No newline at end of file
diff --git a/README.md b/README.md
index 781501178ae8b43056f209efbe460ee3bc866c0e..e4078770f3ce5ac1cc48f23ca44f8e3bd977bb9f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
 Second Life Viewer
 ====================
-
 This project manages the source code for the
 [Second Life](https://www.secondlife.com) Viewer.
 
diff --git a/autobuild.xml b/autobuild.xml
index 9041b8488ffd59f571d6f0771a8b6133370359e2..0f71472d1f9500cccb3cc8f638914643b415555f 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -580,9 +580,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>23aeaf23e7db2484a1850017141860dd</string>
+              <string>350866eec6be17ffc265904b91dcfe6b</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34069/283470/dullahan-1.1.1320_3.3626.1895.g7001d56-darwin64-525361.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60900/572290/dullahan-1.7.0.202005311125_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-543086.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -592,9 +592,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>71fa66203326aca918796e874976c080</string>
+              <string>aa4faf9ef9057362d63f8d57092506b3</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34070/283477/dullahan-1.1.1320_3.3626.1895.g7001d56-windows-525361.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60902/572301/dullahan-1.7.0.202005311828_81.3.10_gb223419_chromium-81.0.4044.138-windows-543086.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -604,16 +604,16 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>c7162e4805f50a3609f5dc63d0cf2bc0</string>
+              <string>6e29ea2ccdad80dcf1b5dc974932c1f6</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34071/283480/dullahan-1.1.1320_3.3626.1895.g7001d56-windows64-525361.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60901/572302/dullahan-1.7.0.202005311828_81.3.10_gb223419_chromium-81.0.4044.138-windows64-543086.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>1.1.1320_3.3626.1895.g7001d56</string>
+        <string>1.7.0.202005311828_81.3.10_gb223419_chromium-81.0.4044.138</string>
       </map>
       <key>elfio</key>
       <map>
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 85197d1272713a88e34f0058443a133241bf0705..58069afdf919553effc193bb10e52c0f9ef5e85c 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -1138,6 +1138,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 			mDebugMessageLevel = message.getValue("message_level");
 			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE);
 		}
+		else if (message_name == "tooltip_text")
+		{
+			mHoverText = message.getValue("tooltip");
+		}
 		else
 		{
 			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index cff21b13c476d4ae6e625e18e1e3d5ce8bb920ce..bc967c9bcaf487db130af3123e201b7bd04699f3 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -62,6 +62,7 @@ class MediaPluginCEF :
 	void onConsoleMessageCallback(std::string message, std::string source, int line);
 	void onStatusMessageCallback(std::string value);
 	void onTitleChangeCallback(std::string title);
+	void onTooltipCallback(std::string text);
 	void onLoadStartCallback();
 	void onRequestExitCallback();
 	void onLoadEndCallback(int httpStatusCode);
@@ -71,6 +72,7 @@ class MediaPluginCEF :
 	bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password);
 	void onCursorChangedCallback(dullahan::ECursorType type);
 	const std::vector<std::string> onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, const std::string dialog_accept_filter, bool& use_default);
+	bool onJSDialogCallback(const std::string origin_url, const std::string message_text, const std::string default_prompt_text);
 
 	void postDebugMessage(const std::string& msg);
 	void authResponse(LLPluginMessage &message);
@@ -87,6 +89,8 @@ class MediaPluginCEF :
 	bool mPluginsEnabled;
 	bool mJavascriptEnabled;
 	bool mDisableGPU;
+	bool mDisableNetworkService;
+	bool mUseMockKeyChain;
 	std::string mUserAgentSubtring;
 	std::string mAuthUsername;
 	std::string mAuthPassword;
@@ -95,7 +99,6 @@ class MediaPluginCEF :
 	bool mCanCopy;
 	bool mCanPaste;
 	std::string mCachePath;
-	std::string mCookiePath;
 	std::string mCefLogFile;
 	bool mCefLogVerbose;
 	std::vector<std::string> mPickedFiles;
@@ -119,6 +122,8 @@ MediaPluginBase(host_send_func, host_user_data)
 	mPluginsEnabled = false;
 	mJavascriptEnabled = true;
 	mDisableGPU = false;
+	mDisableNetworkService = true;
+	mUseMockKeyChain = true;
 	mUserAgentSubtring = "";
 	mAuthUsername = "";
 	mAuthPassword = "";
@@ -127,7 +132,6 @@ MediaPluginBase(host_send_func, host_user_data)
 	mCanCopy = false;
 	mCanPaste = false;
 	mCachePath = "";
-	mCookiePath = "";
 	mCefLogFile = "";
 	mCefLogVerbose = false;
 	mPickedFiles.clear();
@@ -208,6 +212,12 @@ void MediaPluginCEF::onTitleChangeCallback(std::string title)
 	sendMessage(message);
 }
 
+void MediaPluginCEF::onTooltipCallback(std::string text)
+{
+    LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "tooltip_text");
+    message.setValue("tooltip", text);
+    sendMessage(message);
+}
 ////////////////////////////////////////////////////////////////////////////////
 //
 void MediaPluginCEF::onLoadStartCallback()
@@ -355,6 +365,14 @@ const std::vector<std::string> MediaPluginCEF::onFileDialog(dullahan::EFileDialo
 	return std::vector<std::string>();
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginCEF::onJSDialogCallback(const std::string origin_url, const std::string message_text, const std::string default_prompt_text)
+{
+	// return true indicates we suppress the JavaScript alert UI entirely
+	return true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 //
 void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type)
@@ -431,6 +449,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 			{
 				mCEFLib->update();
 
+				mVolumeCatcher.pump();
+
 				// this seems bad but unless the state changes (it won't until we figure out
 				// how to get CEF to tell us if copy/cut/paste is available) then this function
 				// will return immediately
@@ -491,6 +511,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 				mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
 				mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1));
 				mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
+				mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1));
 				mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
 				mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1));
 				mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
@@ -500,15 +521,19 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 				mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
 				mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1));
 				mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this));
-
+				mCEFLib->setOnJSDialogCallback(std::bind(&MediaPluginCEF::onJSDialogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+				
 				dullahan::dullahan_settings settings;
 				settings.accept_language_list = mHostLanguage;
 				settings.background_color = 0xffffffff;
 				settings.cache_enabled = true;
 				settings.cache_path = mCachePath;
-				settings.cookie_store_path = mCookiePath;
 				settings.cookies_enabled = mCookiesEnabled;
 				settings.disable_gpu = mDisableGPU;
+#if LL_DARWIN
+				settings.disable_network_service = mDisableNetworkService;
+				settings.use_mock_keychain = mUseMockKeyChain;
+#endif
 				settings.flash_enabled = mPluginsEnabled;
 				settings.flip_mouse_y = false;
 				settings.flip_pixels_y = true;
@@ -561,7 +586,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 				std::string user_data_path_cookies = message_in.getValue("cookies_path");
 
 				mCachePath = user_data_path_cache + "cef_cache";
-				mCookiePath = user_data_path_cookies + "cef_cookies";
 				mCefLogFile = message_in.getValue("cef_log_file");
 				mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log");
 			}
@@ -661,8 +685,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 			else if (message_name == "scroll_event")
 			{
 				// Mouse coordinates for cef to be able to scroll 'containers'
-				//S32 x = message_in.getValueS32("x");
-				//S32 y = message_in.getValueS32("y");
+				S32 x = message_in.getValueS32("x");
+				S32 y = message_in.getValueS32("y");
+
 				// Wheel's clicks
 				S32 delta_x = message_in.getValueS32("clicks_x");
 				S32 delta_y = message_in.getValueS32("clicks_y");
@@ -670,8 +695,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 				delta_x *= -scaling_factor;
 				delta_y *= -scaling_factor;
 
-				// mCEFLib->mouseWheel(x, y, delta_x, delta_y);
-				mCEFLib->mouseWheel(delta_x, delta_y);
+				mCEFLib->mouseWheel(x, y, delta_x, delta_y);
 			}
 			else if (message_name == "text_event")
 			{
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 49df80bfeb472e079a3463bbb30059ae0d903a05..7d765dabde896468b3d25cfa8abe88f4386e816f 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.4
+6.4.5
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index e8f01f7a6038a9ec0729d349a5caa2de70ba1b78..dfc3c7b89da852cd3dd1f3cabe37eff899794db5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -8434,7 +8434,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>0.125</real>
+    <real>0.02</real>
   </map>
   <key>MediaRollOffMin</key>
   <map>
@@ -8445,7 +8445,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>10.0</real>
+    <real>40.0</real>
   </map>
   <key>MediaRollOffMax</key>
   <map>
@@ -8456,7 +8456,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>30.0</real>
+    <real>80.0</real>
   </map>
   <key>RecentItemsSortOrder</key>
     <map>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 6836ec7479c1c51742e995190f08897ae901b9fe..a56475d544c5e11ca5406efe90c5d17987e2f5e1 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -129,7 +129,7 @@
 #include "llcoros.h"
 #include "llexception.h"
 #if !LL_LINUX
-#include "cef/dullahan.h"
+#include "cef/dullahan_version.h"
 #include "vlc/libvlc_version.h"
 #endif // LL_LINUX
 
@@ -3221,12 +3221,16 @@ LLSD LLAppViewer::getViewerInfo() const
 	cef_ver_codec << ".";
 	cef_ver_codec << DULLAHAN_VERSION_MINOR;
 	cef_ver_codec << ".";
+	cef_ver_codec << DULLAHAN_VERSION_POINT;
+	cef_ver_codec << ".";
 	cef_ver_codec << DULLAHAN_VERSION_BUILD;
 
-	cef_ver_codec << " / CEF: ";
+	cef_ver_codec << std::endl;
+	cef_ver_codec << "  CEF: ";
 	cef_ver_codec << CEF_VERSION;
 
-	cef_ver_codec << " / Chromium: ";
+	cef_ver_codec << std::endl;
+	cef_ver_codec << "  Chromium: ";
 	cef_ver_codec << CHROME_VERSION_MAJOR;
 	cef_ver_codec << ".";
 	cef_ver_codec << CHROME_VERSION_MINOR;
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 6e61584d33f4d70ceb9cb4572d86de5608b0c6d0..55c84815aa860e190b18761b9150485f61744f0c 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -829,8 +829,32 @@ void LLPanelPrimMediaControls::draw()
 
 BOOL LLPanelPrimMediaControls::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
-	mInactivityTimer.start();
-	return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+    mInactivityTimer.start();
+    BOOL res = FALSE;
+
+    // Unlike other mouse events, we need to handle scroll here otherwise
+    // it will be intercepted by camera and won't reach toolpie
+    if (LLViewerMediaFocus::getInstance()->isHoveringOverFocused())
+    {
+        // either let toolpie handle this or expose mHoverPick.mUVCoords in some way
+        res = LLToolPie::getInstance()->handleScrollWheel(x, y, clicks);
+    }
+
+    return res;
+}
+
+BOOL LLPanelPrimMediaControls::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+    mInactivityTimer.start();
+    BOOL res = FALSE;
+
+    if (LLViewerMediaFocus::getInstance()->isHoveringOverFocused())
+    {
+        // either let toolpie handle this or expose mHoverPick.mUVCoords in some way
+        res = LLToolPie::getInstance()->handleScrollHWheel(x, y, clicks);
+    }
+
+    return res;
 }
 
 BOOL LLPanelPrimMediaControls::handleMouseDown(S32 x, S32 y, MASK mask)
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 21d52360744d7e53c0f4847bccb14efb3029a5b7..d4301aaf7ccbddb157114cba9e39ef30d4830d65 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -48,6 +48,7 @@ class LLPanelPrimMediaControls : public LLPanel
 	/*virtual*/ BOOL postBuild();
 	virtual void draw();
 	virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+	virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
 
 	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index aeb8bdc496dd4d3535f83a1165bf4ee310267b27..f499c34ca4b11e05b839a2aec479d14cfe74f733 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -203,14 +203,31 @@ BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
 	return LLTool::handleRightMouseUp(x, y, mask);
 }
 
+BOOL LLToolPie::handleScrollWheelAny(S32 x, S32 y, S32 clicks_x, S32 clicks_y)
+{
+    BOOL res = FALSE;
+    // mHoverPick should have updated on its own and we should have a face
+    // in LLViewerMediaFocus in case of media, so just reuse mHoverPick
+    if (mHoverPick.mUVCoords.mV[VX] >= 0.f && mHoverPick.mUVCoords.mV[VY] >= 0.f)
+    {
+        res = LLViewerMediaFocus::getInstance()->handleScrollWheel(mHoverPick.mUVCoords, clicks_x, clicks_y);
+    }
+    else
+    {
+        // this won't provide correct coordinates in case of object selection
+        res = LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks_x, clicks_y);
+    }
+    return res;
+}
+
 BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
-	return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+    return handleScrollWheelAny(x, y, 0, clicks);
 }
 
 BOOL LLToolPie::handleScrollHWheel(S32 x, S32 y, S32 clicks)
 {
-    return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+    return handleScrollWheelAny(x, y, clicks, 0);
 }
 
 // True if you selected an object.
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index fe0acfe47305e6c1cdb7eba830fb8316cc1f547b..2d6c22f4251fcb24a9283886dbd7d500f96a01f0 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -49,6 +49,7 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 	virtual BOOL		handleRightMouseUp(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleHover(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask);
+	BOOL				handleScrollWheelAny(S32 x, S32 y, S32 clicks_x, S32 clicks_y);
 	virtual BOOL		handleScrollWheel(S32 x, S32 y, S32 clicks);
 	virtual BOOL		handleScrollHWheel(S32 x, S32 y, S32 clicks);
 	virtual BOOL		handleToolTip(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 99b54f66d35e0c014b0bde0b9c41087520c21388..ed5dff1600fa769b50dc03da1713dec0b181e07b 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -2293,6 +2293,18 @@ void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
 	}
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::scrollWheel(const LLVector2& texture_coords, S32 scroll_x, S32 scroll_y, MASK mask)
+{
+    if (mMediaSource)
+    {
+        S32 x, y;
+        scaleTextureCoords(texture_coords, &x, &y);
+
+        scrollWheel(x, y, scroll_x, scroll_y, mask);
+    }
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask)
 {
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 9467a138f03733227dcbcf4b401b1d6fb32cbfe4..512c5a827992dca4d376b82f96362210b61fa408 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -235,6 +235,7 @@ class LLViewerMediaImpl
 	void mouseMove(const LLVector2& texture_coords, MASK mask);
     void mouseDoubleClick(const LLVector2& texture_coords, MASK mask);
     void mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button = 0);
+	void scrollWheel(const LLVector2& texture_coords, S32 scroll_x, S32 scroll_y, MASK mask);
 	void scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask);
 	void mouseCapture();
 	
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index 69ab0a71af459ecc9abe6e44ddd16faac300ddb4..71ae7bfbc3bccecbc0a60df8106729edd0b7d2ec 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -371,13 +371,26 @@ BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_pa
 		media_impl->handleUnicodeCharHere(uni_char);
 	return true;
 }
-BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
+
+BOOL LLViewerMediaFocus::handleScrollWheel(const LLVector2& texture_coords, S32 clicks_x, S32 clicks_y)
+{
+    BOOL retval = FALSE;
+    LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+    if (media_impl && media_impl->hasMedia())
+    {
+        media_impl->scrollWheel(texture_coords, clicks_x, clicks_y, gKeyboard->currentMask(TRUE));
+        retval = TRUE;
+    }
+    return retval;
+}
+
+BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks_x, S32 clicks_y)
 {
 	BOOL retval = FALSE;
 	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
 	if(media_impl && media_impl->hasMedia())
 	{
-		media_impl->scrollWheel(x, y, 0, clicks, gKeyboard->currentMask(TRUE));
+		media_impl->scrollWheel(x, y, clicks_x, clicks_y, gKeyboard->currentMask(TRUE));
 		retval = TRUE;
 	}
 	return retval;
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index 763a6c16881fb27d3f77fd37bea867de64a24364..fa469c36e3a1f5c81361951538816730c1103eee 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -58,7 +58,8 @@ class LLViewerMediaFocus :
 	/*virtual*/ BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent);
 	/*virtual*/ BOOL	handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
 	/*virtual*/ BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
-	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+	BOOL handleScrollWheel(const LLVector2& texture_coords, S32 clicks_x, S32 clicks_y);
+	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks_x, S32 clicks_y);
 
 	void update();
 	
@@ -67,7 +68,8 @@ class LLViewerMediaFocus :
 
 	bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face);
 	bool isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face);
-	
+	bool isHoveringOverFocused() { return mFocusedObjectID == mHoverObjectID && mFocusedObjectFace == mHoverObjectFace; };
+
 	// These look up (by uuid) and return the values that were set with setFocusFace.  They will return null if the objects have been destroyed.
 	LLViewerMediaImpl* getFocusedMediaImpl();
 	LLViewerObject* getFocusedObject();
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index b1b5275f826bcb510df5c3cf8f019e23468eb120..0cdd447fcd26593ecf592e1c4c80c5d2640ae5ee 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -102,6 +102,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
 			if(mMediaImpl.isNull())
 
 			{
+				play(parcel);
 				return;
 			}
 
@@ -158,6 +159,12 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
 	if (!gSavedSettings.getBOOL("AudioStreamingMedia"))
 		return;
 
+	// This test appears all over the code and really should be facotred out into a single 
+	// call that returns true/false (with option ask dialog) but that is outside of scope
+	// for this work so we'll just directly.
+	if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 0 )
+		return;
+
 	std::string media_url = parcel->getMediaURL();
 	std::string media_current_url = parcel->getMediaCurrentURL();
 	std::string mime_type = parcel->getMediaType();
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 4d6d75659f048e6db96a5ca06a2272c363a6a34f..b385717dbe9216195ef23d11d294e4db11f1c317 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -594,13 +594,11 @@ def construct(self):
             config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release'
             with self.prefix(src=os.path.join(pkgdir, 'bin', config)):
                 self.path("chrome_elf.dll")
-                self.path("d3dcompiler_43.dll")
                 self.path("d3dcompiler_47.dll")
                 self.path("libcef.dll")
                 self.path("libEGL.dll")
                 self.path("libGLESv2.dll")
                 self.path("dullahan_host.exe")
-                self.path("natives_blob.bin")
                 self.path("snapshot_blob.bin")
                 self.path("v8_context_snapshot.bin")
 
@@ -795,6 +793,7 @@ def package_finish(self):
         for exe in (
             self.final_exe(),
             "SLVersionChecker.exe",
+            "llplugin/dullahan_host.exe",
             ):
             self.sign(exe)
             
@@ -828,13 +827,13 @@ def package_finish(self):
 
     def sign(self, exe):
         sign_py = os.environ.get('SIGN', r'C:\buildscripts\code-signing\sign.py')
-        python  = os.environ.get('PYTHON', 'python')
+        python  = os.environ.get('PYTHON', sys.executable)
         if os.path.exists(sign_py):
             dst_path = self.dst_path_of(exe)
             print "about to run signing of: ", dst_path
             self.run_command([python, sign_py, dst_path])
         else:
-            print "Skipping code signing of %s: %s not found" % (exe, sign_py)
+            print "Skipping code signing of %s %s: %s not found" % (self.dst_path_of(exe), exe, sign_py)
 
     def escape_slashes(self, path):
         return path.replace('\\', '\\\\\\\\')
@@ -1105,46 +1104,55 @@ def path_optional(src, dst):
                     # $viewer_app/Contents/Frameworks/Chromium Embedded Framework.framework
                     SLPlugin_framework = self.relsymlinkf(CEF_framework, catch=False)
 
-                    # copy DullahanHelper.app
-                    self.path2basename(relpkgdir, 'DullahanHelper.app')
-
-                    # and fix that up with a Frameworks/CEF symlink too
-                    with self.prefix(dst=os.path.join(
-                        'DullahanHelper.app', 'Contents', 'Frameworks')):
-                        # from Dullahan Helper.app/Contents/Frameworks/Chromium Embedded
-                        # Framework.framework back to
-                        # SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework
-                        # Since SLPlugin_framework is itself a
-                        # symlink, don't let relsymlinkf() resolve --
-                        # explicitly call relpath(symlink=True) and
-                        # create that symlink here.
-                        DullahanHelper_framework = \
-                            self.symlinkf(self.relpath(SLPlugin_framework, symlink=True),
-                                          catch=False)
-
-                    # change_command includes install_name_tool, the
-                    # -change subcommand and the old framework rpath
-                    # stamped into the executable. To use it with
-                    # run_command(), we must still append the new
-                    # framework path and the pathname of the
-                    # executable to change.
-                    change_command = [
-                        'install_name_tool', '-change',
-                        '@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework']
-
-                    with self.prefix(dst=os.path.join(
-                        'DullahanHelper.app', 'Contents', 'MacOS')):
-                        # Now self.get_dst_prefix() is, at runtime,
-                        # @executable_path. Locate the helper app
-                        # framework (which is a symlink) from here.
-                        newpath = os.path.join(
-                            '@executable_path',
-                            self.relpath(DullahanHelper_framework, symlink=True),
-                            frameworkname)
-                        # and restamp the DullahanHelper executable
-                        self.run_command(
-                            change_command +
-                            [newpath, self.dst_path_of('DullahanHelper')])
+                    # for all the multiple CEF/Dullahan (as of CEF 76) helper app bundles we need:
+                    for helper in (
+                        "DullahanHelper",
+                        "DullahanHelper (GPU)",
+                        "DullahanHelper (Renderer)",
+                        "DullahanHelper (Plugin)",
+                    ):
+                        # app is the directory name of the app bundle, with app/Contents/MacOS/helper as the executable
+                        app = helper + ".app"
+
+                        # copy DullahanHelper.app
+                        self.path2basename(relpkgdir, app)
+
+                        # and fix that up with a Frameworks/CEF symlink too
+                        with self.prefix(dst=os.path.join(
+                                app, 'Contents', 'Frameworks')):
+                            # from Dullahan Helper *.app/Contents/Frameworks/Chromium Embedded
+                            # Framework.framework back to
+                            # SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework
+                            # Since SLPlugin_framework is itself a
+                            # symlink, don't let relsymlinkf() resolve --
+                            # explicitly call relpath(symlink=True) and
+                            # create that symlink here.
+                            helper_framework = \
+                            self.symlinkf(self.relpath(SLPlugin_framework, symlink=True), catch=False)
+
+                        # change_command includes install_name_tool, the
+                        # -change subcommand and the old framework rpath
+                        # stamped into the executable. To use it with
+                        # run_command(), we must still append the new
+                        # framework path and the pathname of the
+                        # executable to change.
+                        change_command = [
+                            'install_name_tool', '-change',
+                            '@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework']
+
+                        with self.prefix(dst=os.path.join(
+                                app, 'Contents', 'MacOS')):
+                            # Now self.get_dst_prefix() is, at runtime,
+                            # @executable_path. Locate the helper app
+                            # framework (which is a symlink) from here.
+                            newpath = os.path.join(
+                                '@executable_path',
+                                    self.relpath(helper_framework, symlink=True),
+                                frameworkname)
+                                # and restamp the Dullahan Helper executable itself
+                            self.run_command(
+                                change_command +
+                                    [newpath, self.dst_path_of(helper)])
 
                 # SLPlugin plugins
                 with self.prefix(dst="llplugin"):