From b286a9091b66c816f12e9a98e5ae092549261904 Mon Sep 17 00:00:00 2001
From: callum <none@none>
Date: Fri, 25 Mar 2011 13:56:14 -0700
Subject: [PATCH] SOCIAL-688 FIX Multiple SLurls error given in minimal skin
 when clicking links in web profile Also fixes SOCIAL-521 and SOCIAL-428

---
 indra/llplugin/llpluginclassmedia.cpp         |  2 ++
 indra/llplugin/llpluginclassmedia.h           |  4 +++
 .../webkit/media_plugin_webkit.cpp            |  5 ++++
 indra/newview/llagentlistener.cpp             |  4 +--
 indra/newview/llcommanddispatcherlistener.cpp |  2 +-
 indra/newview/llcommandhandler.cpp            | 15 +++++++++--
 indra/newview/llcommandhandler.h              |  1 +
 indra/newview/llstartup.cpp                   |  2 +-
 indra/newview/llurldispatcher.cpp             | 25 ++++++++++++-------
 indra/newview/llurldispatcher.h               |  3 +++
 indra/newview/llurldispatcherlistener.cpp     |  2 +-
 indra/newview/llviewermedia.cpp               |  3 ++-
 indra/newview/llviewerregion.cpp              |  2 +-
 indra/newview/llviewerwindow.cpp              |  4 +--
 indra/newview/llworldmapview.cpp              |  2 +-
 15 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 57f91a57ca5..21032165366 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -144,6 +144,7 @@ void LLPluginClassMedia::reset()
 	mStatusText.clear();
 	mProgressPercent = 0;	
 	mClickURL.clear();
+	mClickNavType.clear();
 	mClickTarget.clear();
 	mClickUUID.clear();
 	mStatusCode = 0;
@@ -1025,6 +1026,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 		else if(message_name == "click_nofollow")
 		{
 			mClickURL = message.getValue("uri");
+			mClickNavType = message.getValue("nav_type");
 			mClickTarget.clear();
 			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
 		}
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index a940633b889..cf8d8b26b9a 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -226,6 +226,9 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
 	std::string getClickURL() const { return mClickURL; };
 
+	// This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+	std::string getClickNavType() const { return mClickNavType; };
+
 	// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
 	std::string getClickTarget() const { return mClickTarget; };
 
@@ -380,6 +383,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	int				mProgressPercent;
 	std::string		mLocation;
 	std::string		mClickURL;
+	std::string		mClickNavType;
 	std::string		mClickTarget;
 	std::string		mClickUUID;
 	S32				mGeometryX;
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index c1bc9adec0d..61548a1ab4b 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -528,6 +528,11 @@ class MediaPluginWebKit :
 	{
 		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow");
 		message.setValue("uri", event.getEventUri());
+#if LLQTWEBKIT_API_VERSION >= 7
+		message.setValue("nav_type", event.getNavigationType());
+#else
+		message.setValue("nav_type", "clicked");
+#endif
 		sendMessage(message);
 	}
 	
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
index d520debc31f..e6f1c046752 100644
--- a/indra/newview/llagentlistener.cpp
+++ b/indra/newview/llagentlistener.cpp
@@ -64,7 +64,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
 		params.append(event_data["x"]);
 		params.append(event_data["y"]);
 		params.append(event_data["z"]);
-		LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, true);
+		LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, "clicked", true);
 		// *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
 		// should we just compose LLCommandHandler and LLDispatchListener?
 	}
@@ -74,7 +74,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
 								  LLVector3(event_data["x"].asReal(), 
 											event_data["y"].asReal(), 
 											event_data["z"].asReal())).getSLURLString();
-		LLURLDispatcher::dispatch(url, NULL, false);
+		LLURLDispatcher::dispatch(url, "clicked", NULL, false);
 	}
 }
 
diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp
index 5744d055a91..586f45fd8f4 100644
--- a/indra/newview/llcommanddispatcherlistener.cpp
+++ b/indra/newview/llcommanddispatcherlistener.cpp
@@ -65,7 +65,7 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const
         trusted_browser = params["trusted"].asBoolean();
     }
     LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL,
-                                  trusted_browser);
+                                  "clicked", trusted_browser);
 }
 
 void LLCommandDispatcherListener::enumerate(const LLSD& params) const
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 1b6ba02aacd..bb1fb41fae1 100755
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -35,7 +35,7 @@
 // system includes
 #include <boost/tokenizer.hpp>
 
-#define THROTTLE_PERIOD    5    // required secs between throttled commands
+#define THROTTLE_PERIOD    20    // required secs between throttled commands
 
 static LLCommandDispatcherListener sCommandDispatcherListener;
 
@@ -59,6 +59,7 @@ class LLCommandHandlerRegistry
 				  const LLSD& params,
 				  const LLSD& query_map,
 				  LLMediaCtrl* web,
+				  const std::string& nav_type,
 				  bool trusted_browser);
 
 private:
@@ -91,6 +92,7 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
 										const LLSD& params,
 										const LLSD& query_map,
 										LLMediaCtrl* web,
+										const std::string& nav_type,
 										bool trusted_browser)
 {
 	static bool slurl_blocked = false;
@@ -120,6 +122,14 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
 			return true;
 
 		case LLCommandHandler::UNTRUSTED_THROTTLE:
+			// if users actually click on a link, we don't need to throttle it
+			// (throttling mechanism is used to prevent an avalanche of clicks via
+			// javascript
+			if ( nav_type == "clicked" )
+			{
+				break;
+			}
+
 			cur_time = LLTimer::getElapsedSeconds();
 			if (cur_time < last_throttle_time + THROTTLE_PERIOD)
 			{
@@ -166,10 +176,11 @@ bool LLCommandDispatcher::dispatch(const std::string& cmd,
 								   const LLSD& params,
 								   const LLSD& query_map,
 								   LLMediaCtrl* web,
+								   const std::string& nav_type,
 								   bool trusted_browser)
 {
 	return LLCommandHandlerRegistry::instance().dispatch(
-		cmd, params, query_map, web, trusted_browser);
+		cmd, params, query_map, web, nav_type, trusted_browser);
 }
 
 static std::string lookup(LLCommandHandler::EUntrustedAccess value);
diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h
index 1e65b6de239..1e0895565af 100644
--- a/indra/newview/llcommandhandler.h
+++ b/indra/newview/llcommandhandler.h
@@ -95,6 +95,7 @@ class LLCommandDispatcher
 						 const LLSD& params,
 						 const LLSD& query_map,
 						 LLMediaCtrl* web,
+						 const std::string& nav_type,
 						 bool trusted_browser);
 		// Execute a command registered via the above mechanism,
 		// passing string parameters.
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 8fccb35886c..bfa8cf09fd1 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2717,7 +2717,7 @@ bool LLStartUp::dispatchURL()
 			|| (dx*dx > SLOP*SLOP)
 			|| (dy*dy > SLOP*SLOP) )
 		{
-			LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), 
+			LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), "clicked",
 						  NULL, false);
 		}
 		return true;
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index ebbb045f0a3..ed4d278e906 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -53,6 +53,7 @@ class LLURLDispatcherImpl
 {
 public:
 	static bool dispatch(const LLSLURL& slurl,
+						 const std::string& nav_type,
 						 LLMediaCtrl* web,
 						 bool trusted_browser);
 		// returns true if handled or explicitly blocked.
@@ -61,6 +62,7 @@ class LLURLDispatcherImpl
 
 private:
 	static bool dispatchCore(const LLSLURL& slurl, 
+							 const std::string& nav_type,
 							 bool right_mouse,
 							 LLMediaCtrl* web,
 							 bool trusted_browser);
@@ -71,6 +73,7 @@ class LLURLDispatcherImpl
 		// Returns true if handled.
 
 	static bool dispatchApp(const LLSLURL& slurl,
+							const std::string& nav_type,
 							bool right_mouse,
 							LLMediaCtrl* web,
 							bool trusted_browser);
@@ -78,7 +81,7 @@ class LLURLDispatcherImpl
 		// by showing panel in Search floater.
 		// Returns true if handled or explicitly blocked.
 
-	static bool dispatchRegion(const LLSLURL& slurl, bool right_mouse);
+	static bool dispatchRegion(const LLSLURL& slurl, const std::string& nav_type, bool right_mouse);
 		// handles secondlife://Ahern/123/45/67/
 		// Returns true if handled.
 
@@ -97,6 +100,7 @@ class LLURLDispatcherImpl
 
 // static
 bool LLURLDispatcherImpl::dispatchCore(const LLSLURL& slurl,
+									   const std::string& nav_type,
 									   bool right_mouse,
 									   LLMediaCtrl* web,
 									   bool trusted_browser)
@@ -105,9 +109,9 @@ bool LLURLDispatcherImpl::dispatchCore(const LLSLURL& slurl,
 	switch(slurl.getType())
 	{
 		case LLSLURL::APP: 
-			return dispatchApp(slurl, right_mouse, web, trusted_browser);
+			return dispatchApp(slurl, nav_type, right_mouse, web, trusted_browser);
 		case LLSLURL::LOCATION:
-			return dispatchRegion(slurl, right_mouse);
+			return dispatchRegion(slurl, nav_type, right_mouse);
 		default:
 			return false;
 	}
@@ -122,11 +126,12 @@ bool LLURLDispatcherImpl::dispatchCore(const LLSLURL& slurl,
 
 // static
 bool LLURLDispatcherImpl::dispatch(const LLSLURL& slurl,
+								   const std::string& nav_type,
 								   LLMediaCtrl* web,
 								   bool trusted_browser)
 {
 	const bool right_click = false;
-	return dispatchCore(slurl, right_click, web, trusted_browser);
+	return dispatchCore(slurl, nav_type, right_click, web, trusted_browser);
 }
 
 // static
@@ -135,11 +140,12 @@ bool LLURLDispatcherImpl::dispatchRightClick(const LLSLURL& slurl)
 	const bool right_click = true;
 	LLMediaCtrl* web = NULL;
 	const bool trusted_browser = false;
-	return dispatchCore(slurl, right_click, web, trusted_browser);
+	return dispatchCore(slurl, "clicked", right_click, web, trusted_browser);
 }
 
 // static
 bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl, 
+									  const std::string& nav_type,
 									  bool right_mouse,
 									  LLMediaCtrl* web,
 									  bool trusted_browser)
@@ -147,7 +153,7 @@ bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl,
 	llinfos << "cmd: " << slurl.getAppCmd() << " path: " << slurl.getAppPath() << " query: " << slurl.getAppQuery() << llendl;
 	const LLSD& query_map = LLURI::queryMap(slurl.getAppQuery());
 	bool handled = LLCommandDispatcher::dispatch(
-			slurl.getAppCmd(), slurl.getAppPath(), query_map, web, trusted_browser);
+			slurl.getAppCmd(), slurl.getAppPath(), query_map, web, nav_type, trusted_browser);
 
 	// alert if we didn't handle this secondlife:///app/ SLURL
 	// (but still return true because it is a valid app SLURL)
@@ -159,7 +165,7 @@ bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl,
 }
 
 // static
-bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, bool right_mouse)
+bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, const std::string& nav_type, bool right_mouse)
 {
   if(slurl.getType() != LLSLURL::LOCATION)
     {
@@ -287,10 +293,11 @@ LLTeleportHandler gTeleportHandler;
 
 // static
 bool LLURLDispatcher::dispatch(const std::string& slurl,
+							   const std::string& nav_type,
 							   LLMediaCtrl* web,
 							   bool trusted_browser)
 {
-	return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), web, trusted_browser);
+	return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), nav_type, web, trusted_browser);
 }
 
 // static
@@ -310,7 +317,7 @@ bool LLURLDispatcher::dispatchFromTextEditor(const std::string& slurl)
 	// *TODO: Make this trust model more refined.  JC
 	const bool trusted_browser = true;
 	LLMediaCtrl* web = NULL;
-	return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), web, trusted_browser);
+	return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), "clicked", web, trusted_browser);
 }
 
 
diff --git a/indra/newview/llurldispatcher.h b/indra/newview/llurldispatcher.h
index b07db4da3f4..6309a97af53 100644
--- a/indra/newview/llurldispatcher.h
+++ b/indra/newview/llurldispatcher.h
@@ -33,6 +33,7 @@ class LLURLDispatcher
 public:
 	
 	static bool dispatch(const std::string& slurl,
+						 const std::string& nav_type,
 						 LLMediaCtrl* web,
 						 bool trusted_browser);	
 		// At startup time and on clicks in internal web browsers,
@@ -41,6 +42,8 @@ class LLURLDispatcher
 		//   secondlife://RegionName/123/45/67/
 		//   secondlife:///app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show
 		//   sl://app/foo/bar
+		// @param nav_type
+		//   type of navigation type (see LLQtWebKit::LLWebPage::acceptNavigationRequest)
 		// @param web
 		//	 Pointer to LLMediaCtrl sending URL, can be NULL
 		// @param trusted_browser
diff --git a/indra/newview/llurldispatcherlistener.cpp b/indra/newview/llurldispatcherlistener.cpp
index d0441d7bfaa..c7b9afafefc 100644
--- a/indra/newview/llurldispatcherlistener.cpp
+++ b/indra/newview/llurldispatcherlistener.cpp
@@ -61,7 +61,7 @@ void LLURLDispatcherListener::dispatch(const LLSD& params) const
         // But for testing, allow a caller to specify untrusted.
         trusted_browser = params["trusted"].asBoolean();
     }
-    LLURLDispatcher::dispatch(params["url"], NULL, trusted_browser);
+    LLURLDispatcher::dispatch(params["url"], "clicked", NULL, trusted_browser);
 }
 
 void LLURLDispatcherListener::dispatchRightClick(const LLSD& params) const
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index c2d630ece2f..037e22584f3 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -2984,7 +2984,8 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 		{
 			LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL; 
 			std::string url = plugin->getClickURL();
-			LLURLDispatcher::dispatch(url, NULL, mTrustedBrowser);
+			std::string nav_type = plugin->getClickNavType();
+			LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser);
 		}
 		break;
 		case MEDIA_EVENT_CLICK_LINK_HREF:
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index e1d3e8a0b32..6ae143d2993 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -111,7 +111,7 @@ class LLRegionHandler : public LLCommandHandler
 		}
 
 		// Process the SLapp as if it was a secondlife://{PLACE} SLurl
-		LLURLDispatcher::dispatch(url, web, true);
+		LLURLDispatcher::dispatch(url, "clicked", web, true);
 		return true;
 	}
 };
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 014d64176a1..cd19d0c5cd8 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -915,7 +915,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
 					{
 						if (drop)
 						{
-							LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), NULL, true );
+							LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), "clicked", NULL, true );
 							return LLWindowCallbacks::DND_MOVE;
 						}
 						return LLWindowCallbacks::DND_COPY;
@@ -1306,7 +1306,7 @@ void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
 		std::string url = (const char*)data;
 		LLMediaCtrl* web = NULL;
 		const bool trusted_browser = false;
-		if (LLURLDispatcher::dispatch(url, web, trusted_browser))
+		if (LLURLDispatcher::dispatch(url, "clicked", web, trusted_browser))
 		{
 			// bring window to foreground, as it has just been "launched" from a URL
 			mWindow->bringToFront();
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 8ef3a3b8393..8cdb615686c 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -1745,7 +1745,7 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )
 				// Invoke the event details floater if someone is clicking on an event.
 				LLSD params(LLSD::emptyArray());
 				params.append(event_id);
-				LLCommandDispatcher::dispatch("event", params, LLSD(), NULL, true);
+				LLCommandDispatcher::dispatch("event", params, LLSD(), NULL, "clicked", true);
 				break;
 			}
 		case MAP_ITEM_LAND_FOR_SALE:
-- 
GitLab