From 5219e6c455c92d789c25909d02bf094886fad3d9 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Tue, 17 Apr 2018 19:25:28 +0300
Subject: MAINT-8325 Fixed The Save Local dialog disconnects the viewer if you
 do not choose the save directory files within the first minute

---
 indra/llplugin/llpluginclassmedia.h     |  2 +
 indra/newview/llfilepicker.cpp          | 77 +++++++++++++++++++++++----------
 indra/newview/llfilepicker.h            |  4 +-
 indra/newview/llfloatermodelpreview.cpp | 12 ++++-
 indra/newview/llfloatermodelpreview.h   |  2 +-
 indra/newview/llviewermedia.cpp         | 75 ++++++++++++++++++--------------
 indra/newview/llviewermedia.h           |  4 +-
 indra/newview/llviewermenufile.cpp      | 33 ++++++++++----
 indra/newview/llviewermenufile.h        | 18 +++++---
 9 files changed, 150 insertions(+), 77 deletions(-)

diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 3b3075c6bd..4f52afb317 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -317,6 +317,8 @@ public:
 	// "init_history" message 
 	void initializeUrlHistory(const LLSD& url_history);
 
+	boost::shared_ptr<LLPluginClassMedia> getSharedPrt() { return boost::dynamic_pointer_cast<LLPluginClassMedia>(shared_from_this()); } // due to enable_shared_from_this
+
 protected:
 
 	LLPluginClassMediaOwner *mOwner;
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 125a823e58..0f22b6200f 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -283,7 +283,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 	return success;
 }
 
-BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
+BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
 {
 	if( mLocked )
 	{
@@ -310,9 +310,13 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
 	setupFilter(filter);
 
 	reset();
-	
-	// Modal, so pause agent
-	send_agent_pause();
+
+	if (blocking)
+	{
+		// Modal, so pause agent
+		send_agent_pause();
+	}
+
 	// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
 	success = GetOpenFileName(&mOFN); // pauses until ok or cancel.
 	if( success )
@@ -345,14 +349,18 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
 			}
 		}
 	}
-	send_agent_resume();
+
+	if (blocking)
+	{
+		send_agent_resume();
+	}
 
 	// Account for the fact that the app has been stalled.
 	LLFrameTimer::updateFrameTime();
 	return success;
 }
 
-BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
+BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking)
 {
 	if( mLocked )
 	{
@@ -540,8 +548,12 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 
 	reset();
 
-	// Modal, so pause agent
-	send_agent_pause();
+	if (blocking)
+	{
+		// Modal, so pause agent
+		send_agent_pause();
+	}
+
 	{
 		// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
 		try
@@ -559,7 +571,11 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 		}
 		gKeyboard->resetKeys();
 	}
-	send_agent_resume();
+
+	if (blocking)
+	{
+		send_agent_resume();
+	}
 
 	// Account for the fact that the app has been stalled.
 	LLFrameTimer::updateFrameTime();
@@ -809,7 +825,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
         mPickOptions |= F_NAV_SUPPORT;
 	}
 	
-	if (blocking)
+	if (blocking) // always true for linux/mac
 	{
 		// Modal, so pause agent
 		send_agent_pause();
@@ -834,7 +850,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 	return success;
 }
 
-BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
+BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
 {
 	if( mLocked )
 		return FALSE;
@@ -852,13 +868,20 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
     mPickOptions |= F_FILE;
 
     mPickOptions |= F_MULTIPLE;
-	// Modal, so pause agent
-	send_agent_pause();
-    
+
+	if (blocking) // always true for linux/mac
+	{
+		// Modal, so pause agent
+		send_agent_pause();
+	}
+
 	success = doNavChooseDialog(filter);
-    
-    send_agent_resume();
-    
+
+	if (blocking)
+	{
+		send_agent_resume();
+	}
+
 	if (success)
 	{
 		if (!getFileCount())
@@ -872,7 +895,7 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
 	return success;
 }
 
-BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
+BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking)
 {
 
 	if( mLocked )
@@ -889,8 +912,11 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 	
     mPickOptions &= ~F_MULTIPLE;
 
-	// Modal, so pause agent
-	send_agent_pause();
+	if (blocking)
+	{
+		// Modal, so pause agent
+		send_agent_pause();
+	}
 
     success = doNavSaveDialog(filter, filename);
 
@@ -900,7 +926,10 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
 			success = false;
 	}
 
-	send_agent_resume();
+	if (blocking)
+	{
+		send_agent_resume();
+	}
 
 	// Account for the fact that the app has been stalled.
 	LLFrameTimer::updateFrameTime();
@@ -1354,7 +1383,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
 	return rtn;
 }
 
-BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
+BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
 {
 	BOOL rtn = FALSE;
 
@@ -1438,7 +1467,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
 	return TRUE;
 }
 
-BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
+BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
 {
 	// if local file browsing is turned off, return without opening dialog
 	// (Even though this is a stub, I think we still should not return anything at all)
@@ -1467,7 +1496,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
 	return FALSE;
 }
 
-BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
+BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
 {
 	reset();
 	return FALSE;
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index b6e67375cd..7914067976 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -113,9 +113,9 @@ public:
 	};
 
 	// open the dialog. This is a modal operation
-	BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null );
+	BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null, bool blocking = true);
 	BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL, bool blocking = true  );
-	BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL );
+	BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
 
 	// Get the filename(s) found. getFirstFile() sets the pointer to
 	// the start of the structure and allows the start of iteration.
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index da84a6b8f8..7a2ab37a0d 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -218,9 +218,17 @@ LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
 		mLOD = lod;
 	}
 
-void LLMeshFilePicker::notify(const std::string& filename)
+void LLMeshFilePicker::notify(const std::vector<std::string>& filenames)
 {
-	mMP->loadModel(mFile, mLOD);
+	if (filenames.size() > 0)
+	{
+		mMP->loadModel(filenames[0], mLOD);
+	}
+	else
+	{
+		//closes floater
+		mMP->loadModel(std::string(), mLOD);
+	}
 }
 
 void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 0b2b7db2b6..53b03c6069 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -219,7 +219,7 @@ class LLMeshFilePicker : public LLFilePickerThread
 {
 public:
 	LLMeshFilePicker(LLModelPreview* mp, S32 lod);
-	virtual void notify(const std::string& filename);
+	virtual void notify(const std::vector<std::string>& filenames);
 
 private:
 	LLModelPreview* mMP;
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 75108b3ef0..4334cbfda3 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -55,6 +55,7 @@
 #include "llversioninfo.h"
 #include "llviewermediafocus.h"
 #include "llviewercontrol.h"
+#include "llviewermenufile.h" // LLFilePickerThread
 #include "llviewernetwork.h"
 #include "llviewerparcelmedia.h"
 #include "llviewerparcelmgr.h"
@@ -82,6 +83,43 @@
 /*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel";
 
 
+class LLMediaFilePicker : public LLFilePickerThread // deletes itself when done
+{
+public:
+    LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple)
+        : LLFilePickerThread(filter, get_multiple),
+        mPlugin(plugin->getSharedPrt())
+    {
+    }
+
+    LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ESaveFilter filter, const std::string &proposed_name)
+        : LLFilePickerThread(filter, proposed_name),
+        mPlugin(plugin->getSharedPrt())
+    {
+    }
+
+    virtual void notify(const std::vector<std::string>& filenames)
+    {
+        mPlugin->sendPickFileResponse(mResponses);
+        mPlugin = NULL;
+    }
+
+private:
+    boost::shared_ptr<LLPluginClassMedia> mPlugin;
+};
+
+void init_threaded_picker_load_dialog(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple)
+{
+    (new LLMediaFilePicker(plugin, filter, get_multiple))->getFile(); // will delete itself
+}
+
+void init_threaded_picker_save_dialog(LLPluginClassMedia* plugin, LLFilePicker::ESaveFilter filter, std::string &proposed_name)
+{
+    (new LLMediaFilePicker(plugin, filter, proposed_name))->getFile(); // will delete itself
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 // Move this to its own file.
 
 LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter()
@@ -1647,8 +1685,7 @@ void LLViewerMediaImpl::destroyMediaSource()
 	if(mMediaSource)
 	{
 		mMediaSource->setDeleteOK(true) ;
-		delete mMediaSource;
-		mMediaSource = NULL;
+		mMediaSource = NULL; // shared pointer
 	}
 }
 
@@ -1840,7 +1877,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
 			media_source->clear_cache();
 		}
 
-		mMediaSource = media_source;
+		mMediaSource.reset(media_source);
 		mMediaSource->setDeleteOK(false) ;
 		updateVolume();
 
@@ -3274,37 +3311,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 
 		case LLViewerMediaObserver::MEDIA_EVENT_PICK_FILE_REQUEST:
 		{
-			LLFilePicker& picker = LLFilePicker::instance();
-			std::vector<std::string> responses;
-
-			bool pick_multiple_files = plugin->getIsMultipleFilePick();
-			if (pick_multiple_files == false)
-			{
-				picker.getOpenFile(LLFilePicker::FFLOAD_ALL);
-
-				std::string filename = picker.getFirstFile();
-				responses.push_back(filename);
-			}
-			else
-			{
-				if (picker.getMultipleOpenFiles())
-				{
-					std::string filename = picker.getFirstFile();
-
-					responses.push_back(filename);
-
-					while (!filename.empty())
-					{
-						filename = picker.getNextFile();
+			LL_DEBUGS("Media") << "Media event - file pick requested." <<  LL_ENDL;
 
-						if (!filename.empty())
-						{
-							responses.push_back(filename);
-						}
-					}
-				}
-			}
-			plugin->sendPickFileResponse(responses);
+			init_threaded_picker_load_dialog(plugin, LLFilePicker::FFLOAD_ALL, plugin->getIsMultipleFilePick());
 		}
 		break;
 
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 6e18c4fecb..c52960dfcf 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -202,7 +202,7 @@ public:
 	bool initializeMedia(const std::string& mime_type);
 	bool initializePlugin(const std::string& media_type);
 	void loadURI();
-	LLPluginClassMedia* getMediaPlugin() { return mMediaSource; }
+	LLPluginClassMedia* getMediaPlugin() { return mMediaSource.get(); }
 	void setSize(int width, int height);
 
 	void showNotification(LLNotificationPtr notify);
@@ -417,7 +417,7 @@ private:
 	
 private:
 	// a single media url with some data and an impl.
-	LLPluginClassMedia* mMediaSource;
+	boost::shared_ptr<LLPluginClassMedia> mMediaSource;
 	F64		mZoomFactor;
 	LLUUID mTextureId;
 	bool  mMovieImageHasMips;
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index e4525609c2..8160a3a139 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -135,18 +135,35 @@ void LLFilePickerThread::getFile()
 //virtual 
 void LLFilePickerThread::run()
 {
-	LLFilePicker picker;
 #if LL_WINDOWS
-	if (picker.getOpenFile(mFilter, false))
+	bool blocking = false;
+#else
+	bool blocking = true; // modal
+#endif
+
+	LLFilePicker picker;
+
+	if (mIsSaveDialog)
 	{
-		mFile = picker.getFirstFile();
+		if (picker.getSaveFile(mSaveFilter, mProposedName, blocking))
+		{
+			mResponses.push_back(picker.getFirstFile());
+		}
 	}
-#else
-	if (picker.getOpenFile(mFilter, true))
+	else
 	{
-		mFile = picker.getFirstFile();
+		bool result = mIsGetMultiple ? picker.getMultipleOpenFiles(mLoadFilter, blocking) : picker.getOpenFile(mLoadFilter, blocking);
+		if (result)
+		{
+			std::string filename = picker.getFirstFile(); // consider copying mFiles directly
+			do
+			{
+				mResponses.push_back(filename);
+				filename = picker.getNextFile();
+			}
+			while (mIsGetMultiple && !filename.empty());
+		}
 	}
-#endif
 
 	{
 		LLMutexLock lock(sMutex);
@@ -179,7 +196,7 @@ void LLFilePickerThread::clearDead()
 		while (!sDeadQ.empty())
 		{
 			LLFilePickerThread* thread = sDeadQ.front();
-			thread->notify(thread->mFile);
+			thread->notify(thread->mResponses);
 			delete thread;
 			sDeadQ.pop();
 		}
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 6941b4dc0e..3e23940c3f 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -81,21 +81,29 @@ public:
 	static void cleanupClass();
 	static void clearDead();
 
-	std::string mFile; 
+	std::vector<std::string> mResponses;
+	std::string mProposedName;
 
-	LLFilePicker::ELoadFilter mFilter;
+	LLFilePicker::ELoadFilter mLoadFilter;
+	LLFilePicker::ESaveFilter mSaveFilter;
+	bool mIsSaveDialog;
+	bool mIsGetMultiple;
 
-	LLFilePickerThread(LLFilePicker::ELoadFilter filter)
-		: LLThread("file picker"), mFilter(filter)
+	LLFilePickerThread(LLFilePicker::ELoadFilter filter, bool get_multiple = false)
+		: LLThread("file picker"), mLoadFilter(filter), mIsSaveDialog(false), mIsGetMultiple(get_multiple)
 	{
+	}
 
+	LLFilePickerThread(LLFilePicker::ESaveFilter filter, const std::string &proposed_name)
+		: LLThread("file picker"), mSaveFilter(filter), mIsSaveDialog(true), mProposedName(proposed_name)
+	{
 	}
 
 	void getFile();
 
 	virtual void run();
 
-	virtual void notify(const std::string& filename) = 0;
+	virtual void notify(const std::vector<std::string>& filenames) = 0;
 };
 
 
-- 
cgit v1.2.3