From 507ccd52a9d398c76896e38db867716bc2acd7f9 Mon Sep 17 00:00:00 2001
From: Lynx Linden <lynx@lindenlab.com>
Date: Thu, 14 Jan 2010 11:57:03 +0000
Subject: [PATCH] EXT-3624: Support "_blank" href target types.

Support href links in web views that have a target attribute set to
"_blank". This will open the link in the user's preferred browser
(internal or external, as defined in Prefs). This change relies on the
new llqtwebkit package that has just been pushed.

Also updated the hardcoded Qt version number in the About floater.
---
 indra/llplugin/llpluginclassmedia.cpp         | 28 ++++++++++++
 indra/llplugin/llpluginclassmedia.h           | 12 +++++
 .../webkit/media_plugin_webkit.cpp            |  1 +
 indra/newview/llfloaterabout.cpp              |  2 +-
 indra/newview/llmediactrl.cpp                 | 45 ++++++++++++-------
 indra/newview/llmediactrl.h                   |  1 -
 6 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index ed8d10a88c4..2c9fb35588f 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -37,6 +37,8 @@
 #include "llpluginclassmedia.h"
 #include "llpluginmessageclasses.h"
 
+#include "llqtwebkit.h"
+
 static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
 
 static int nextPowerOf2( int value )
@@ -134,6 +136,9 @@ void LLPluginClassMedia::reset()
 	mHistoryForwardAvailable = false;
 	mStatusText.clear();
 	mProgressPercent = 0;	
+	mClickURL.clear();
+	mClickTarget.clear();
+	mClickTargetType = TARGET_NONE;
 	
 	// media_time class
 	mCurrentTime = 0.0f;
@@ -669,6 +674,26 @@ void LLPluginClassMedia::paste()
 	sendMessage(message);
 }
 
+LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type)
+{
+	// convert a LinkTargetType value from llqtwebkit to an ETargetType
+	// so that we don't expose the llqtwebkit header in viewer code
+	switch (target_type)
+	{
+	case LinkTargetType::LTT_TARGET_NONE:
+		return LLPluginClassMedia::TARGET_NONE;
+
+	case LinkTargetType::LTT_TARGET_BLANK:
+		return LLPluginClassMedia::TARGET_BLANK;
+
+	case LinkTargetType::LTT_TARGET_EXTERNAL:
+		return LLPluginClassMedia::TARGET_EXTERNAL;
+
+	default:
+		return LLPluginClassMedia::TARGET_OTHER;
+	}
+}
+
 /* virtual */ 
 void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 {
@@ -921,12 +946,15 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 		{
 			mClickURL = message.getValue("uri");
 			mClickTarget = message.getValue("target");
+			U32 target_type = message.getValueU32("target_type");
+			mClickTargetType = ::getTargetTypeFromLLQtWebkit(target_type);
 			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
 		}
 		else if(message_name == "click_nofollow")
 		{
 			mClickURL = message.getValue("uri");
 			mClickTarget.clear();
+			mClickTargetType = TARGET_NONE;
 			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
 		}
 		else
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 5a1928ab1df..ebb90995766 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -214,6 +214,17 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
 	std::string getClickTarget() const { return mClickTarget; };
 
+	typedef enum 
+	{
+		TARGET_NONE,        // empty href target string
+		TARGET_BLANK,       // target to open link in user's preferred browser
+		TARGET_EXTERNAL,    // target to open link in external browser
+		TARGET_OTHER        // nonempty and unsupported target type
+	}ETargetType;
+
+	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+	ETargetType getClickTargetType() const { return mClickTargetType; };
+
 	std::string getMediaName() const { return mMediaName; };
 	std::string getMediaDescription() const { return mMediaDescription; };
 
@@ -344,6 +355,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	std::string		mLocation;
 	std::string		mClickURL;
 	std::string		mClickTarget;
+	ETargetType     mClickTargetType;
 	
 	/////////////////////////////////////////
 	// media_time class
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index a0336f6156c..084cdd9561a 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -429,6 +429,7 @@ class MediaPluginWebKit :
 		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href");
 		message.setValue("uri", event.getStringValue());
 		message.setValue("target", event.getStringValue2());
+		message.setValueU32("target_type", event.getLinkType());
 		sendMessage(message);
 	}
 	
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index aa343b2f697..ef69f39ad2d 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -269,7 +269,7 @@ LLSD LLFloaterAbout::getInfo()
 	info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : LLTrans::getString("NotConnected");
 
 	// TODO: Implement media plugin version query
-	info["QT_WEBKIT_VERSION"] = "4.5.2 (version number hard-coded)";
+	info["QT_WEBKIT_VERSION"] = "4.6 (version number hard-coded)";
 
 	if (gPacketsIn > 0)
 	{
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 6b0f9b709d1..87ebce1d347 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -84,7 +84,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
 	mHomePageUrl( "" ),
 	mIgnoreUIScale( true ),
 	mAlwaysRefresh( false ),
-	mExternalUrl( "" ),
 	mMediaSource( 0 ),
 	mTakeFocusOnClick( true ),
 	mCurrentNavUrl( "" ),
@@ -877,9 +876,27 @@ bool LLMediaCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if ( 0 == option )
 	{
-		// open in external browser because we don't support 
-		// creation of our own secondary browser windows
-		LLWeb::loadURLExternal( notification["payload"]["external_url"].asString() );
+		LLSD payload = notification["payload"];
+		std::string url = payload["url"].asString();
+		S32 target_type = payload["target_type"].asInteger();
+
+		switch (target_type)
+		{
+		case LLPluginClassMedia::TARGET_EXTERNAL:
+			// load target in an external browser
+			LLWeb::loadURLExternal(url);
+			break;
+
+		case LLPluginClassMedia::TARGET_BLANK:
+			// load target in the user's preferred browser
+			LLWeb::loadURL(url);
+			break;
+
+		default:
+			// unsupported link target - shouldn't happen
+			LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL;
+			break;
+		}
 	}
 	return false;
 }
@@ -993,20 +1010,18 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
 void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self )
 {
 	// retrieve the event parameters
-	std::string target = self->getClickTarget();
 	std::string url = self->getClickURL();
+	U32 target_type = self->getClickTargetType();
 	
-	// if there is a value for the target
-	if ( !target.empty() )
+	// is there is a target specified for the link?
+	if (target_type == LLPluginClassMedia::TARGET_EXTERNAL ||
+		target_type == LLPluginClassMedia::TARGET_BLANK)
 	{
-		if ( target == "_external" )		
-		{
-			mExternalUrl = url;
-			LLSD payload;
-			payload["external_url"] = mExternalUrl;
-			LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget);
-			return;
-		}
+		LLSD payload;
+		payload["url"] = url;
+		payload["target_type"] = LLSD::Integer(target_type);
+		LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget);
+		return;
 	}
 
 	const std::string protocol1( "http://" );
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 8f9e6e71797..b0aca3cfa46 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -182,7 +182,6 @@ class LLMediaCtrl :
 		bool mOpenLinksInInternalBrowser;
 		bool mTrusted;
 		std::string mHomePageUrl;
-		std::string mExternalUrl;
 		std::string mCurrentNavUrl;
 		bool mIgnoreUIScale;
 		bool mAlwaysRefresh;
-- 
GitLab