diff options
72 files changed, 2133 insertions, 486 deletions
| diff --git a/autobuild.xml b/autobuild.xml index e9928908be..2d49fb17c0 100755 --- a/autobuild.xml +++ b/autobuild.xml @@ -1484,11 +1484,11 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>29a1f64df46094eda0d681821a98d17e</string> +              <string>db992d58c46c80df7d4d31f8a4784b98</string>                <key>hash_algorithm</key>                <string>md5</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/Darwin/installer/llceflib-1.5.3.311349-darwin-311349.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/Darwin/installer/llceflib-1.5.3.317959-darwin-317959.tar.bz2</string>              </map>              <key>name</key>              <string>darwin</string> @@ -1498,18 +1498,18 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>827b7c339a2cd401d9d23f9ee02cb83f</string> +              <string>bb3818628131a99cd789febfad9dc2c2</string>                <key>hash_algorithm</key>                <string>md5</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/CYGWIN/installer/llceflib-1.5.3.311349-windows-311349.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/CYGWIN/installer/llceflib-1.5.3.317959-windows-317959.tar.bz2</string>              </map>              <key>name</key>              <string>windows</string>            </map>          </map>          <key>version</key> -        <string>1.5.3.311349</string> +        <string>1.5.3.317959</string>        </map>        <key>llphysicsextensions_source</key>        <map> @@ -2135,6 +2135,46 @@          <key>version</key>          <string>0.8.0.1</string>        </map> +      <key>vlc-bin</key> +      <map> +        <key>copyright</key> +        <string>Copyright (C) 1998-2016 VLC authors and VideoLAN</string> +        <key>license</key> +        <string>GPL2</string> +        <key>license_file</key> +        <string>LICENSES/vlc.txt</string> +        <key>name</key> +        <string>vlc-bin</string> +        <key>platforms</key> +        <map> +          <key>linux</key> +          <map> +            <key>archive</key> +            <map> +              <key>hash</key> +              <string>2f410640df3f9812d1abff02a414cfa8</string> +              <key>url</key> +              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2</string> +            </map> +            <key>name</key> +            <string>linux</string> +          </map> +          <key>windows</key> +          <map> +            <key>archive</key> +            <map> +              <key>hash</key> +              <string>04cff37070a5f65f3652b4ddcec7183f</string> +              <key>url</key> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/317935/arch/CYGWIN/installer/vlc_bin-2.2.4.317935-windows-317935.tar.bz2</string> +            </map> +            <key>name</key> +            <string>windows</string> +          </map> +        </map> +        <key>version</key> +        <string>2.2.4.317935</string> +      </map>        <key>xmlrpc-epi</key>        <map>          <key>copyright</key> diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 6dc8e3dfbf..13a31cbce7 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -24,7 +24,6 @@ set(cmake_SOURCE_FILES      DirectX.cmake      DragDrop.cmake      EXPAT.cmake -##  ExamplePlugin.cmake      FindAPR.cmake      FindAutobuild.cmake      FindBerkeleyDB.cmake @@ -100,6 +99,7 @@ set(cmake_SOURCE_FILES      Variables.cmake      ViewerMiscLibs.cmake      VisualLeakDetector.cmake +    LibVLCPlugin.cmake      XmlRpcEpi.cmake      ZLIB.cmake      ) diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index ba07a80f05..80af7ff2ab 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -18,7 +18,7 @@ else (USESYSTEMLIBS)      use_prebuilt_binary(SDL)      set (SDL_FOUND TRUE)      set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux) -    set (SDL_LIBRARY SDL directfb fusion direct) +    set (SDL_LIBRARY SDL directfb fusion direct X11)    endif (LINUX)  endif (USESYSTEMLIBS) diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake new file mode 100644 index 0000000000..4472676fb4 --- /dev/null +++ b/indra/cmake/LibVLCPlugin.cmake @@ -0,0 +1,27 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (USESYSTEMLIBS) +    set(LIBVLCPLUGIN OFF CACHE BOOL +        "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") +else (USESYSTEMLIBS) +    use_prebuilt_binary(vlc-bin) +    set(LIBVLCPLUGIN ON CACHE BOOL +        "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") +        set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc) +endif (USESYSTEMLIBS) + +if (WINDOWS) +    set(VLC_PLUGIN_LIBRARIES +        libvlc.lib +        libvlccore.lib +    ) +elseif (DARWIN) +elseif (LINUX) +    # Specify a full path to make sure we get a static link +    set(VLC_PLUGIN_LIBRARIES +        ${LIBS_PREBUILT_DIR}/lib/libvlc.a +        ${LIBS_PREBUILT_DIR}/lib/libvlccore.a +    ) +endif (WINDOWS) diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt index 32aa08a2b7..9f9ca6c39c 100644 --- a/indra/edit-me-to-trigger-new-build.txt +++ b/indra/edit-me-to-trigger-new-build.txt @@ -1,3 +1,4 @@  2014-02-25 10:34 + diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 44f45144e5..410a5819b3 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES      lleventfilter.cpp      llevents.cpp      lleventtimer.cpp +    llexception.cpp      llfasttimer.cpp      llfile.cpp      llfindlocale.cpp @@ -316,7 +317,7 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") -  LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")                           +  LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") @@ -329,6 +330,11 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}") +## llexception_test.cpp isn't a regression test, and doesn't need to be run +## every build. It's to help a developer make implementation choices about +## throwing and catching exceptions. +##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}") +    # *TODO - reenable these once tcmalloc libs no longer break the build.    #ADD_BUILD_TEST(llallocator llcommon)    #ADD_BUILD_TEST(llallocator_heap_profile llcommon) diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index d16bf0160b..8e516d8beb 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -38,6 +38,7 @@  #include "llevents.h"  #include "llerror.h"  #include "stringize.h" +#include "llexception.h"  // do nothing, when we need nothing done  void LLCoros::no_cleanup(CoroData*) {} @@ -131,9 +132,9 @@ bool LLCoros::cleanup(const LLSD&)              if ((previousCount < 5) || !(previousCount % 50))              {                  if (previousCount < 5) -                    LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL; +                    LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;                  else -                    LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL; +                    LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;              }              // The erase() call will invalidate its passed iterator value -- @@ -185,9 +186,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const              if ((previousCount < 5) || !(previousCount % 50))              {                  if (previousCount < 5) -                    LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL; +                    LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;                  else -                    LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL; +                    LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;              } @@ -223,7 +224,7 @@ std::string LLCoros::getName() const  void LLCoros::setStackSize(S32 stacksize)  { -    LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL; +    LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;      mStackSize = stacksize;  } @@ -235,7 +236,23 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla      // capture the 'self' param in CoroData      data->mSelf = &self;      // run the code the caller actually wants in the coroutine -    callable(); +    try +    { +        callable(); +    } +    catch (const LLContinueError&) +    { +        // Any uncaught exception derived from LLContinueError will be caught +        // here and logged. This coroutine will terminate but the rest of the +        // viewer will carry on. +        LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName)); +    } +    catch (...) +    { +        // Any OTHER kind of uncaught exception will cause the viewer to +        // crash, hopefully informatively. +        CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName)); +    }      // This cleanup isn't perfectly symmetrical with the way we initially set      // data->mPrev, but this is our last chance to reset mCurrentCoro.      sCurrentCoro.reset(data->mPrev); diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp index 87a699ff14..0d5757effd 100644 --- a/indra/llcommon/lldependencies.cpp +++ b/indra/llcommon/lldependencies.cpp @@ -39,8 +39,8 @@  #include <boost/graph/adjacency_list.hpp>  #include <boost/graph/topological_sort.hpp>  #include <boost/graph/exception.hpp> -#include <boost/throw_exception.hpp>  // other Linden headers +#include "llexception.h"  LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const  { @@ -77,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const          // Omit independent nodes: display only those that might contribute to          // the cycle.          describe(out, false); -        BOOST_THROW_EXCEPTION(Cycle(out.str())); +        LLTHROW(Cycle(out.str()));      }      // A peculiarity of boost::topological_sort() is that it emits results in      // REVERSE topological order: to get the result you want, you must diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 3beef65723..7cbe4334b3 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -174,7 +174,8 @@ namespace LLError  			// not really a level  			// used to indicate that no messages should be logged  	}; -	 +	// If you change ELevel, please update llvlog() macro below. +  	/*	Macro support  		The classes CallSite and Log are used by the logging macros below.  		They are not intended for general use. @@ -305,24 +306,38 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;  /////////////////////////////////  // Error Logging Macros -// See top of file for common usage.	 +// See top of file for common usage.  ///////////////////////////////// -// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements -// without braces: -// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL - -#define lllog(level, once, ...)																	          \ -	do {                                                                                                  \ -		const char* tags[] = {"", ##__VA_ARGS__};													      \ -		::size_t tag_count = LL_ARRAY_SIZE(tags) - 1;													  \ -		static LLError::CallSite _site(                                                                   \ -		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\ -		if (LL_UNLIKELY(_site.shouldLog()))			                                                      \ -		{                                                                                                 \ -			std::ostringstream* _out = LLError::Log::out();                                               \ +// Instead of using LL_DEBUGS(), LL_INFOS() et al., it may be tempting to +// directly code the lllog() macro so you can pass in the LLError::ELevel as a +// variable. DON'T DO IT! The reason is that the first time control passes +// through lllog(), it initializes a local static LLError::CallSite with that +// *first* ELevel value. All subsequent visits will decide whether or not to +// emit output based on the *first* ELevel value bound into that static +// CallSite instance. Use LL_VLOGS() instead. lllog() assumes its ELevel +// argument never varies. + +// this macro uses a one-shot do statement to avoid parsing errors when +// writing control flow statements without braces: +// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL; + +#define lllog(level, once, ...)                                         \ +	do {                                                                \ +		const char* tags[] = {"", ##__VA_ARGS__};                       \ +		static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \ +		lllog_test_() + +#define lllog_test_()                                       \ +		if (LL_UNLIKELY(_site.shouldLog()))                 \ +		{                                                   \ +			std::ostringstream* _out = LLError::Log::out(); \  			(*_out) +#define lllog_site_args_(level, once, tags)                 \ +	level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG),    \ +	__FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1 +  //Use this construct if you need to do computation in the middle of a  //message:  //	 @@ -363,4 +378,46 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;  #define LL_INFOS_ONCE(...)	lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)  #define LL_WARNS_ONCE(...)	lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__) +// Use this if you need to pass LLError::ELevel as a variable. +#define LL_VLOGS(level, ...)      llvlog(level, false, ##__VA_ARGS__) +#define LL_VLOGS_ONCE(level, ...) llvlog(level, true,  ##__VA_ARGS__) + +// The problem with using lllog() with a variable level is that the first time +// through, it initializes a static CallSite instance with whatever level you +// pass. That first level is bound into the CallSite; the level parameter is +// never again examined. One approach to variable level would be to +// dynamically construct a CallSite instance every call -- which could get +// expensive, depending on context. So instead, initialize a static CallSite +// for each level value we support, then dynamically select the CallSite +// instance for the passed level value. +// Compare implementation to lllog() above. +#define llvlog(level, once, ...)                                        \ +	do {                                                                \ +		const char* tags[] = {"", ##__VA_ARGS__};                       \ +		/* Need a static CallSite instance per expected ELevel value. */ \ +		/* Since we intend to index this array with the ELevel, */      \ +		/* _sites[0] should be ELevel(0), and so on -- avoid using */   \ +		/* ELevel symbolic names when initializing -- except for */     \ +		/* the last entry, which handles anything beyond the end. */    \ +		/* (Commented ELevel value names are from 2016-09-01.) */       \ +		/* Passing an ELevel past the end of this array is itself */    \ +		/* a fatal error, so ensure the last is LEVEL_ERROR. */         \ +		static LLError::CallSite _sites[] =                             \ +		{                                                               \ +			/* LEVEL_DEBUG */                                           \ +			LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \ +			/* LEVEL_INFO */                                            \ +			LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \ +			/* LEVEL_WARN */                                            \ +			LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \ +			/* LEVEL_ERROR */                                           \ +			LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \ +		};                                                              \ +		/* Clamp the passed 'level' to at most last entry */            \ +		std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \ +						  (LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \ +		/* selected CallSite *must* be named _site for LL_ENDL */       \ +		LLError::CallSite& _site(_sites[which]);                        \ +		lllog_test_() +  #endif // LL_LLERROR_H diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index f444530a17..56367b8f54 100644 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -34,12 +34,12 @@  #include <map>  // std headers  // external library headers -#include <boost/throw_exception.hpp>  // other Linden headers  #include "llsdserialize.h"  #include "llerror.h"  #include "llcoros.h"  #include "llmake.h" +#include "llexception.h"  #include "lleventfilter.h" @@ -352,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)      // returning it, deliver it via exception.      if (result.second)      { -        BOOST_THROW_EXCEPTION(LLErrorEvent(desc, result.first)); +        LLTHROW(LLErrorEvent(desc, result.first));      }      // That way, our caller knows a simple return must be from the reply      // pump (pump 0). diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 50919edb8e..19d700a3b0 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -45,7 +45,6 @@  #include <cctype>  // external library headers  #include <boost/range/iterator_range.hpp> -#include <boost/throw_exception.hpp>  #if LL_WINDOWS  #pragma warning (push)  #pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no @@ -58,6 +57,7 @@  #include "stringize.h"  #include "llerror.h"  #include "llsdutil.h" +#include "llexception.h"  #if LL_MSVC  #pragma warning (disable : 4702)  #endif @@ -175,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string      // Unless we're permitted to tweak it, that's Bad.      if (! tweak)      { -        BOOST_THROW_EXCEPTION(LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'")); +        LLTHROW(LLEventPump::DupPumpName("Duplicate LLEventPump name '" + name + "'"));      }      // The passed name isn't unique, but we're permitted to tweak it. Find the      // first decimal-integer suffix not already taken. The insert() attempt @@ -327,9 +327,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL      // is only when the existing connection object is still connected.      if (found != mConnections.end() && found->second.connected())      { -        BOOST_THROW_EXCEPTION( -            DupListenerName(std::string("Attempt to register duplicate listener name '") + name + -                            "' on " + typeid(*this).name() + " '" + getName() + "'")); +        LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name + +                                "' on " + typeid(*this).name() + " '" + getName() + "'"));      }      // Okay, name is unique, try to reconcile its dependencies. Specify a new      // "node" value that we never use for an mSignal placement; we'll fix it @@ -355,9 +354,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL          // unsortable. If we leave the new node in mDeps, it will continue          // to screw up all future attempts to sort()! Pull it out.          mDeps.remove(name); -        BOOST_THROW_EXCEPTION( -            Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + -                  " '" + getName() + "' would cause cycle: " + e.what())); +        LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() + +                      " '" + getName() + "' would cause cycle: " + e.what()));      }      // Walk the list to verify that we haven't changed the order.      float previous = 0.0, myprev = 0.0; @@ -421,7 +419,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL              // NOW remove the offending listener node.              mDeps.remove(name);              // Having constructed a description of the order change, inform caller. -            BOOST_THROW_EXCEPTION(OrderChange(out.str())); +            LLTHROW(OrderChange(out.str()));          }          // This node becomes the previous one.          previous = dmi->second; @@ -611,7 +609,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const  {      if (! mListener)      { -        BOOST_THROW_EXCEPTION(Empty("attempting to call uninitialized")); +        LLTHROW(Empty("attempting to call uninitialized"));      }      return (*mListener)(event);  } diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 8ff337911d..1526128725 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -95,12 +95,32 @@ struct LLStopWhenHandled      result_type operator()(InputIterator first, InputIterator last) const      {          for (InputIterator si = first; si != last; ++si) -		{ -            if (*si) -			{ -                return true; -			} -		} +        { +            try +            { +                if (*si) +                { +                    return true; +                } +            } +            catch (const LLContinueError&) +            { +                // We catch LLContinueError here because an LLContinueError- +                // based exception means the viewer as a whole should carry on +                // to the best of our ability. Therefore subsequent listeners +                // on the same LLEventPump should still receive this event. + +                // The iterator passed to a boost::signals2 Combiner is very +                // clever, but provides no contextual information. We would +                // very much like to be able to log the name of the LLEventPump +                // plus the name of this particular listener, but alas. +                LOG_UNHANDLED_EXCEPTION("LLEventPump"); +            } +            // We do NOT catch (...) here because we might as well let it +            // propagate out to the generic handler. If we were able to log +            // context information here, that would be great, but we can't, so +            // there's no point. +        }          return false;      }  }; diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp new file mode 100644 index 0000000000..b32ec2c9c9 --- /dev/null +++ b/indra/llcommon/llexception.cpp @@ -0,0 +1,55 @@ +/** + * @file   llexception.cpp + * @author Nat Goodspeed + * @date   2016-08-12 + * @brief  Implementation for llexception. + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llexception.h" +// STL headers +// std headers +#include <typeinfo> +// external library headers +#include <boost/exception/diagnostic_information.hpp> +// other Linden headers +#include "llerror.h" +#include "llerrorcontrol.h" + +namespace { +// used by crash_on_unhandled_exception_() and log_unhandled_exception_() +void log_unhandled_exception_(LLError::ELevel level, +                              const char* file, int line, const char* pretty_function, +                              const std::string& context) +{ +    // log same message but allow caller-specified severity level +    LL_VLOGS(level, "LLException") << LLError::abbreviateFile(file) +        << "(" << line << "): Unhandled exception caught in " << pretty_function; +    if (! context.empty()) +    { +        LL_CONT << ": " << context; +    } +    LL_CONT << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL; +} +} + +void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function, +                                   const std::string& context) +{ +    // LL_ERRS() terminates and propagates message into crash dump. +    log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function, context); +} + +void log_unhandled_exception_(const char* file, int line, const char* pretty_function, +                              const std::string& context) +{ +    // Use LL_WARNS() because we seriously do not expect this to happen +    // routinely, but we DO expect to return from this function. +    log_unhandled_exception_(LLError::LEVEL_WARN, file, line, pretty_function, context); +} diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h index 3ac2f4762f..dfcb7c192f 100644 --- a/indra/llcommon/llexception.h +++ b/indra/llcommon/llexception.h @@ -14,22 +14,24 @@  #include <stdexcept>  #include <boost/exception/exception.hpp> +#include <boost/throw_exception.hpp> +#include <boost/current_function.hpp> + +// "Found someone who can comfort me +//  But there are always exceptions..." +//  - Empty Pages, Traffic, from John Barleycorn (1970) +//    https://www.youtube.com/watch?v=dRH0CGVK7ic  /**   * LLException is intended as the common base class from which all - * viewer-specific exceptions are derived. It is itself a subclass of - * boost::exception; use catch (const boost::exception& e) clause to log the - * string from boost::diagnostic_information(e). - * - * Since it is also derived from std::exception, a generic catch (const - * std::exception&) should also work, though what() is unlikely to be as - * informative as boost::diagnostic_information(). + * viewer-specific exceptions are derived. Rationale for why it's derived from + * both std::exception and boost::exception is explained in + * tests/llexception_test.cpp.   * - * Please use BOOST_THROW_EXCEPTION() - * http://www.boost.org/doc/libs/release/libs/exception/doc/BOOST_THROW_EXCEPTION.html - * to throw viewer exceptions whenever possible. This enriches the exception's - * diagnostic_information() with the source file, line and containing function - * of the BOOST_THROW_EXCEPTION() macro. + * boost::current_exception_diagnostic_information() is quite wonderful: if + * all we need to do with an exception is log it, in most places we should + * catch (...) and log boost::current_exception_diagnostic_information(). + * See CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() below.   *   * There may be circumstances in which it would be valuable to distinguish an   * exception explicitly thrown by viewer code from an exception thrown by @@ -60,4 +62,24 @@ struct LLContinueError: public LLException      {}  }; +/** + * Please use LLTHROW() to throw viewer exceptions whenever possible. This + * enriches the exception's diagnostic_information() with the source file, + * line and containing function of the LLTHROW() macro. + */ +// Currently we implement that using BOOST_THROW_EXCEPTION(). Wrap it in +// LLTHROW() in case we ever want to revisit that implementation decision. +#define LLTHROW(x) BOOST_THROW_EXCEPTION(x) + +/// Call this macro from a catch (...) clause +#define CRASH_ON_UNHANDLED_EXCEPTION(CONTEXT) \ +     crash_on_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT) +void crash_on_unhandled_exception_(const char*, int, const char*, const std::string&); + +/// Call this from a catch (const LLContinueError&) clause, or from a catch +/// (...) clause in which you do NOT want the viewer to crash. +#define LOG_UNHANDLED_EXCEPTION(CONTEXT) \ +     log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT) +void log_unhandled_exception_(const char*, int, const char*, const std::string&); +  #endif /* ! defined(LL_LLEXCEPTION_H) */ diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 2370253078..f56e5596f5 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -296,7 +296,16 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)  {  #if LL_FAST_TIMER_ON  	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance(); -	if (!cur_timer_data) return; +	if (!cur_timer_data) +	{ +		// How likely is it that +		// LLThreadLocalSingletonPointer<T>::getInstance() will return NULL? +		// Even without researching, what we can say is that if we exit +		// without setting mStartTime at all, gcc 4.7 produces (fatal) +		// warnings about a possibly-uninitialized data member. +		mStartTime = 0; +		return; +	}  	TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();  	accumulator.mActiveCount++;  	// keep current parent as long as it is active when we are diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index a8bb9bc53a..c87d2a3e58 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -21,7 +21,6 @@  #include <boost/bind.hpp>  #include <boost/scoped_ptr.hpp>  #include <boost/tokenizer.hpp> -#include <boost/throw_exception.hpp>  // other Linden headers  #include "llerror.h"  #include "llstring.h" @@ -34,6 +33,7 @@  #include "lltimer.h"  #include "lluuid.h"  #include "llleaplistener.h" +#include "llexception.h"  #if LL_MSVC  #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally @@ -70,7 +70,7 @@ public:          // Rule out empty vector          if (plugin.empty())          { -            BOOST_THROW_EXCEPTION(Error("no plugin command")); +            LLTHROW(Error("no plugin command"));          }          // Don't leave desc empty either, but in this case, if we weren't @@ -113,7 +113,7 @@ public:          // If that didn't work, no point in keeping this LLLeap object.          if (! mChild)          { -            BOOST_THROW_EXCEPTION(Error(STRINGIZE("failed to run " << mDesc))); +            LLTHROW(Error(STRINGIZE("failed to run " << mDesc)));          }          // Okay, launch apparently worked. Change our mDonePump listener. diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 0fb257aab1..575edddc43 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -110,11 +110,15 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)  	#if defined(LL_WINDOWS)  		return _aligned_malloc(size, align);  	#else +        char* aligned = NULL;  		void* mem = malloc( size + (align - 1) + sizeof(void*) ); -		char* aligned = ((char*)mem) + sizeof(void*); -		aligned += align - ((uintptr_t)aligned & (align - 1)); +        if (mem) +        { +            aligned = ((char*)mem) + sizeof(void*); +            aligned += align - ((uintptr_t)aligned & (align - 1)); -		((void**)aligned)[-1] = mem; +            ((void**)aligned)[-1] = mem; +        }  		return aligned;  	#endif  	} diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index ca19c94736..8c321d06b9 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -34,12 +34,12 @@  #include "llapr.h"  #include "apr_signal.h"  #include "llevents.h" +#include "llexception.h"  #include <boost/foreach.hpp>  #include <boost/bind.hpp>  #include <boost/asio/streambuf.hpp>  #include <boost/asio/buffers_iterator.hpp> -#include <boost/throw_exception.hpp>  #include <iostream>  #include <stdexcept>  #include <limits> @@ -531,9 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):  	if (! params.validateBlock(true))  	{ -		BOOST_THROW_EXCEPTION( -			LLProcessError(STRINGIZE("not launched: failed parameter validation\n" -									 << LLSDNotationStreamer(params)))); +		LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n" +										 << LLSDNotationStreamer(params))));  	}  	mPostend = params.postend; @@ -598,11 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params):  		}  		else  		{ -			BOOST_THROW_EXCEPTION( -				LLProcessError(STRINGIZE("For " << params.executable() -										 << ": unsupported FileParam for " << which -										 << ": type='" << fparam.type() -										 << "', name='" << fparam.name() << "'"))); +			LLTHROW(LLProcessError(STRINGIZE("For " << params.executable() +											 << ": unsupported FileParam for " << which +											 << ": type='" << fparam.type() +											 << "', name='" << fparam.name() << "'")));  		}  	}  	// By default, pass APR_NO_PIPE for unspecified slots. @@ -681,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):  	if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,  										   gAPRPoolp)))  	{ -		BOOST_THROW_EXCEPTION(LLProcessError(STRINGIZE(params << " failed"))); +		LLTHROW(LLProcessError(STRINGIZE(params << " failed")));  	}  	// arrange to call status_callback() @@ -1066,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot)  	PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);  	if (! wp)  	{ -		BOOST_THROW_EXCEPTION(NoPipe(error)); +		LLTHROW(NoPipe(error));  	}  	return *wp;  } diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp index a004618e96..491f920c0f 100644 --- a/indra/llcommon/llthreadsafequeue.cpp +++ b/indra/llcommon/llthreadsafequeue.cpp @@ -26,8 +26,8 @@  #include "linden_common.h"  #include <apr_pools.h>  #include <apr_queue.h> -#include <boost/throw_exception.hpp>  #include "llthreadsafequeue.h" +#include "llexception.h" @@ -42,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po  {  	if(mOwnsPool) {  		apr_status_t status = apr_pool_create(&mPool, 0); -		if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate pool")); +		if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));  	} else {  		; // No op.  	}  	apr_status_t status = apr_queue_create(&mQueue, capacity, mPool); -	if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate queue")); +	if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));  } @@ -69,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element)  	apr_status_t status = apr_queue_push(mQueue, element);  	if(status == APR_EINTR) { -		BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt()); +		LLTHROW(LLThreadSafeQueueInterrupt());  	} else if(status != APR_SUCCESS) { -		BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("push failed")); +		LLTHROW(LLThreadSafeQueueError("push failed"));  	} else {  		; // Success.  	} @@ -89,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void)  	apr_status_t status = apr_queue_pop(mQueue, &element);  	if(status == APR_EINTR) { -		BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt()); +		LLTHROW(LLThreadSafeQueueInterrupt());  	} else if(status != APR_SUCCESS) { -		BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("pop failed")); +		LLTHROW(LLThreadSafeQueueError("pop failed"));  	} else {  		return element;  	} diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index 785cf47926..d4af2c6b01 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data )  unsigned int ret = 0;  for( int ix = 0; ix < 5; ++ix ) {  char * s = strchr( encodeTable, fiveChars[ ix ] ); -if( s == 0 ) BOOST_THROW_EXCEPTION(bad_input_data()); +if( s == 0 ) LLTHROW(bad_input_data());  ret = ret * 85 + (s-encodeTable);  }  return ret; diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index f51279e817..8bace8ac41 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -237,8 +237,21 @@ namespace tut  	void ErrorTestObject::test<4>()  		// file abbreviation  	{ -		std::string thisFile = __FILE__; -		std::string abbreviateFile = LLError::abbreviateFile(thisFile); +		std::string prev, abbreviateFile = __FILE__; +        do +        { +            prev = abbreviateFile; +            abbreviateFile = LLError::abbreviateFile(abbreviateFile); +            // __FILE__ is assumed to end with +            // indra/llcommon/tests/llerror_test.cpp. This test used to call +            // abbreviateFile() exactly once, then check below whether it +            // still contained the string 'indra'. That fails if the FIRST +            // part of the pathname also contains indra! Certain developer +            // machine images put local directory trees under +            // /ngi-persist/indra, which is where we observe the problem. So +            // now, keep calling abbreviateFile() until it returns its +            // argument unchanged, THEN check. +        } while (abbreviateFile != prev);  		ensure_ends_with("file name abbreviation",  			abbreviateFile, diff --git a/indra/llcommon/tests/llexception_test.cpp b/indra/llcommon/tests/llexception_test.cpp new file mode 100644 index 0000000000..6bee1943c2 --- /dev/null +++ b/indra/llcommon/tests/llexception_test.cpp @@ -0,0 +1,308 @@ +/** + * @file   llexception_test.cpp + * @author Nat Goodspeed + * @date   2016-08-12 + * @brief  Tests for throwing exceptions. + * + * This isn't a regression test: it doesn't need to be run every build, which + * is why the corresponding line in llcommon/CMakeLists.txt is commented out. + * Rather it's a head-to-head test of what kind of exception information we + * can collect from various combinations of exception base classes, type of + * throw verb and sequences of catch clauses. + * + * This "test" makes no ensure() calls: its output goes to stdout for human + * examination. + * + * As of 2016-08-12 with Boost 1.57, we come to the following conclusions. + * These should probably be re-examined from time to time as we update Boost. + * + * - It is indisputably beneficial to use BOOST_THROW_EXCEPTION() rather than + *   plain throw. The macro annotates the exception object with the filename, + *   line number and function name from which the exception was thrown. + * + * - That being the case, deriving only from boost::exception isn't an option. + *   Every exception object passed to BOOST_THROW_EXCEPTION() must be derived + *   directly or indirectly from std::exception. The only question is whether + *   to also derive from boost::exception. We decided to derive LLException + *   from both, as it makes message output slightly cleaner, but this is a + *   trivial reason: if a strong reason emerges to prefer single inheritance, + *   dropping the boost::exception base class shouldn't be a problem. + * + * - (As you will have guessed, ridiculous things like a char* or int or a + *   class derived from neither boost::exception nor std::exception can only + *   be caught by that specific type or (...), and + *   boost::current_exception_diagnostic_information() simply throws up its + *   hands and confesses utter ignorance. Stay away from such nonsense.) + * + * - But if you derive from std::exception, to nat's surprise, + *   boost::current_exception_diagnostic_information() gives as much + *   information about exceptions in a catch (...) clause as you can get from + *   a specific catch (const std::exception&) clause, notably the concrete + *   exception class and the what() string. So instead of a sequence like + * + *   try { ... } + *   catch (const boost::exception& e) { ... boost-flavored logging ... } + *   catch (const std::exception& e)   { ... std::exception logging ... } + *   catch (...)                       { ... generic logging ... } + * + *   we should be able to get away with only a catch (...) clause that logs + *   boost::current_exception_diagnostic_information(). + * + * - Going further: boost::current_exception_diagnostic_information() provides + *   just as much information even within a std::set_terminate() handler. So + *   it might not even be strictly necessary to include a catch (...) clause + *   since the viewer does use std::set_terminate(). + * + * - (We might consider adding a catch (int) clause because Kakadu internally + *   throws ints, and who knows if one of those might leak out. If it does, + *   boost::current_exception_diagnostic_information() can do nothing with it. + *   A catch (int) clause could at least log the value and rethrow.) + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llexception.h" +// STL headers +// std headers +#include <typeinfo> +// external library headers +#include <boost/throw_exception.hpp> +// other Linden headers +#include "../test/lltut.h" + +// helper for display output +// usage: std::cout << center(some string value, fill char, width) << std::endl; +// (assumes it's the only thing on that particular line) +struct center +{ +    center(const std::string& label, char fill, std::size_t width): +        mLabel(label), +        mFill(fill), +        mWidth(width) +    {} + +    // Use friend declaration not because we need to grant access, but because +    // it lets us declare a free operator like a member function. +    friend std::ostream& operator<<(std::ostream& out, const center& ctr) +    { +        std::size_t padded = ctr.mLabel.length() + 2; +        std::size_t left  = (ctr.mWidth - padded) / 2; +        std::size_t right = ctr.mWidth - left - padded; +        return out << std::string(left, ctr.mFill) << ' ' << ctr.mLabel << ' ' +                   << std::string(right, ctr.mFill); +    } + +    std::string mLabel; +    char mFill; +    std::size_t mWidth; +}; + +/***************************************************************************** +*   Four kinds of exceptions: derived from boost::exception, from +*   std::exception, from both, from neither +*****************************************************************************/ +// Interestingly, we can't use this variant with BOOST_THROW_EXCEPTION() +// (which we want) -- we reach a failure topped by this comment: +//  //All boost exceptions are required to derive from std::exception, +//  //to ensure compatibility with BOOST_NO_EXCEPTIONS. +struct FromBoost: public boost::exception +{ +    FromBoost(const std::string& what): mWhat(what) {} +    ~FromBoost() throw() {} +    std::string what() const { return mWhat; } +    std::string mWhat; +}; + +struct FromStd: public std::runtime_error +{ +    FromStd(const std::string& what): std::runtime_error(what) {} +}; + +struct FromBoth: public boost::exception, public std::runtime_error +{ +    FromBoth(const std::string& what): std::runtime_error(what) {} +}; + +// Same deal with FromNeither: can't use with BOOST_THROW_EXCEPTION(). +struct FromNeither +{ +    FromNeither(const std::string& what): mWhat(what) {} +    std::string what() const { return mWhat; } +    std::string mWhat; +}; + +/***************************************************************************** +*   Two kinds of throws: plain throw and BOOST_THROW_EXCEPTION() +*****************************************************************************/ +template <typename EXC> +void plain_throw(const std::string& what) +{ +    throw EXC(what); +} + +template <typename EXC> +void boost_throw(const std::string& what) +{ +    BOOST_THROW_EXCEPTION(EXC(what)); +} + +// Okay, for completeness, functions that throw non-class values. We wouldn't +// even deign to consider these if we hadn't found examples in our own source +// code! (Note that Kakadu's internal exception support is still based on +// throwing ints.) +void throw_char_ptr(const std::string& what) +{ +    throw what.c_str(); // umm... +} + +void throw_int(const std::string& what) +{ +    throw int(what.length()); +} + +/***************************************************************************** +*   Three sequences of catch clauses: +*   boost::exception then ..., +*   std::exception then ..., +*   or just ... +*****************************************************************************/ +void catch_boost_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ +    try +    { +        thrower(what); +    } +    catch (const boost::exception& e) +    { +        std::cout << "catch (const boost::exception& e)" << std::endl; +        std::cout << "e is " << typeid(e).name() << std::endl; +        std::cout << "boost::diagnostic_information(e):\n'" +                  << boost::diagnostic_information(e) << "'" << std::endl; +        // no way to report e.what() +    } +    catch (...) +    { +        std::cout << "catch (...)" << std::endl; +        std::cout << "boost::current_exception_diagnostic_information():\n'" +                  << boost::current_exception_diagnostic_information() << "'" +                  << std::endl; +    } +} + +void catch_std_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ +    try +    { +        thrower(what); +    } +    catch (const std::exception& e) +    { +        std::cout << "catch (const std::exception& e)" << std::endl; +        std::cout << "e is " << typeid(e).name() << std::endl; +        std::cout << "boost::diagnostic_information(e):\n'" +                  << boost::diagnostic_information(e) << "'" << std::endl; +        std::cout << "e.what: '" +                  << e.what() << "'" << std::endl; +    } +    catch (...) +    { +        std::cout << "catch (...)" << std::endl; +        std::cout << "boost::current_exception_diagnostic_information():\n'" +                  << boost::current_exception_diagnostic_information() << "'" +                  << std::endl; +    } +} + +void catch_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ +    try +    { +        thrower(what); +    } +    catch (...) +    { +        std::cout << "catch (...)" << std::endl; +        std::cout << "boost::current_exception_diagnostic_information():\n'" +                  << boost::current_exception_diagnostic_information() << "'" +                  << std::endl; +    } +} + +/***************************************************************************** +*   Try a particular kind of throw against each of three catch sequences +*****************************************************************************/ +void catch_several(void (*thrower)(const std::string&), const std::string& what) +{ +    std::cout << std::string(20, '-') << "catch_boost_dotdotdot(" << what << ")" << std::endl; +    catch_boost_dotdotdot(thrower, "catch_boost_dotdotdot(" + what + ")"); + +    std::cout << std::string(20, '-') << "catch_std_dotdotdot(" << what << ")" << std::endl; +    catch_std_dotdotdot(thrower, "catch_std_dotdotdot(" + what + ")"); + +    std::cout << std::string(20, '-') << "catch_dotdotdot(" << what << ")" << std::endl; +    catch_dotdotdot(thrower, "catch_dotdotdot(" + what + ")"); +} + +/***************************************************************************** +*   For a particular kind of exception, try both kinds of throw against all +*   three catch sequences +*****************************************************************************/ +template <typename EXC> +void catch_both_several(const std::string& what) +{ +    std::cout << std::string(20, '*') << "plain_throw<" << what << ">" << std::endl; +    catch_several(plain_throw<EXC>, "plain_throw<" + what + ">"); + +    std::cout << std::string(20, '*') << "boost_throw<" << what << ">" << std::endl; +    catch_several(boost_throw<EXC>, "boost_throw<" + what + ">"); +} + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    struct llexception_data +    { +    }; +    typedef test_group<llexception_data> llexception_group; +    typedef llexception_group::object object; +    llexception_group llexceptiongrp("llexception"); + +    template<> template<> +    void object::test<1>() +    { +        set_test_name("throwing exceptions"); + +        // For each kind of exception, try both kinds of throw against all +        // three catch sequences +        std::size_t margin = 72; +        std::cout << center("FromStd", '=', margin) << std::endl; +        catch_both_several<FromStd>("FromStd"); + +        std::cout << center("FromBoth", '=', margin) << std::endl; +        catch_both_several<FromBoth>("FromBoth"); + +        std::cout << center("FromBoost", '=', margin) << std::endl; +        // can't throw with BOOST_THROW_EXCEPTION(), just use catch_several() +        catch_several(plain_throw<FromBoost>, "plain_throw<FromBoost>"); + +        std::cout << center("FromNeither", '=', margin) << std::endl; +        // can't throw this with BOOST_THROW_EXCEPTION() either +        catch_several(plain_throw<FromNeither>, "plain_throw<FromNeither>"); + +        std::cout << center("const char*", '=', margin) << std::endl; +        // We don't expect BOOST_THROW_EXCEPTION() to throw anything so daft +        // as a const char* or an int, so don't bother with +        // catch_both_several() -- just catch_several(). +        catch_several(throw_char_ptr, "throw_char_ptr"); + +        std::cout << center("int", '=', margin) << std::endl; +        catch_several(throw_int, "throw_int"); +    } +} // namespace tut diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index fa16fd6915..9a4bbbd630 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -40,7 +40,6 @@  #include <boost/bind.hpp>  #include <boost/noncopyable.hpp>  #include <boost/shared_ptr.hpp> -#include <boost/throw_exception.hpp>  #include <list>  #include <string> @@ -79,7 +78,7 @@ struct WrapLLErrs          error = message;          // Also throw an appropriate exception since calling code is likely to          // assume that control won't continue beyond LL_ERRS. -        BOOST_THROW_EXCEPTION(FatalException(message)); +        LLTHROW(FatalException(message));      }      std::string error; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 91fa8c6ad1..f331c533fd 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1401,7 +1401,12 @@ void LLImageRaw::copyScaled( LLImageRaw* src )  bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )  { -	llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) ); +    S32 components = getComponents(); +	if (! ((1 == components) || (3 == components) || (4 == components) )) +    { +        LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL; +        return false; +    }  	S32 old_width = getWidth();  	S32 old_height = getHeight(); @@ -1415,67 +1420,53 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )  	if (scale_image_data)  	{ -		/* -		S32 temp_data_size = old_width * new_height * getComponents(); -		llassert_always(temp_data_size > 0); -		std::vector<U8> temp_buffer(temp_data_size); - -		// Vertical -		for( S32 col = 0; col < old_width; col++ ) -		{ -			copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width ); -		} - -		deleteData(); +		S32 new_data_size = new_width * new_height * components; -		U8* new_buffer = allocateDataSize(new_width, new_height, getComponents()); +		if (new_data_size > 0) +        { +            U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);  +            if(NULL == new_data)  +            { +                return false;  +            } -		// Horizontal -		for( S32 row = 0; row < new_height; row++ ) -		{ -			copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 ); -		} -		*/ - -		S32 new_data_size = new_width * new_height * getComponents(); -		llassert_always(new_data_size > 0); - -		U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);  -		if(NULL == new_data)  -		{ -			return false;  +            bilinear_scale(getData(), old_width, old_height, components, old_width*components, new_data, new_width, new_height, components, new_width*components); +            setDataAndSize(new_data, new_width, new_height, components);   		} - -		bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents()); -		setDataAndSize(new_data, new_width, new_height, getComponents());   	}  	else  	{  		// copy	out	existing image data -		S32	temp_data_size = old_width * old_height	* getComponents(); +		S32	temp_data_size = old_width * old_height	* components;  		std::vector<U8> temp_buffer(temp_data_size);  		memcpy(&temp_buffer[0],	getData(), temp_data_size);  		// allocate	new	image data,	will delete	old	data -		U8*	new_buffer = allocateDataSize(new_width, new_height, getComponents()); - -		for( S32 row = 0; row <	new_height;	row++ ) -		{ -			if (row	< old_height) -			{ -				memcpy(new_buffer +	(new_width * row * getComponents()), &temp_buffer[0] + (old_width *	row	* getComponents()),	getComponents()	* llmin(old_width, new_width)); -				if (old_width <	new_width) -				{ -					// pad out rest	of row with	black -					memset(new_buffer +	(getComponents() * ((new_width * row) +	old_width)), 0,	getComponents()	* (new_width - old_width)); -				} -			} -			else -			{ -				// pad remaining rows with black -				memset(new_buffer +	(new_width * row * getComponents()), 0,	new_width *	getComponents()); -			} -		} +		U8*	new_buffer = allocateDataSize(new_width, new_height, components); + +        if (!new_buffer) +        { +            LL_WARNS() << "Failed to allocate new image data buffer" << LL_ENDL; +            return false; +        } +         +        for( S32 row = 0; row <	new_height;	row++ ) +        { +            if (row	< old_height) +            { +                memcpy(new_buffer +	(new_width * row * components), &temp_buffer[0] + (old_width *	row	* components),	components * llmin(old_width, new_width)); +                if (old_width <	new_width) +                { +                    // pad out rest	of row with	black +                    memset(new_buffer +	(components * ((new_width * row) +	old_width)), 0,	components * (new_width - old_width)); +                } +            } +            else +            { +                // pad remaining rows with black +                memset(new_buffer +	(new_width * row * components), 0,	new_width *	components); +            } +        }  	}  	return true ; diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index 0b7d4c717f..da289ea889 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -32,12 +32,12 @@  #include "llpngwrapper.h"  #include "llexception.h" -#include <boost/throw_exception.hpp>  namespace { -struct PngError: public LLException +// Failure to load an image shouldn't crash the whole viewer. +struct PngError: public LLContinueError  { -    PngError(png_const_charp msg): LLException(msg) {} +    PngError(png_const_charp msg): LLContinueError(msg) {}  };  } // anonymous namespace @@ -88,7 +88,7 @@ BOOL LLPngWrapper::isValidPng(U8* src)  // occurs. We throw PngError and let our try/catch block clean up.  void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg)  { -	BOOST_THROW_EXCEPTION(PngError(msg)); +	LLTHROW(PngError(msg));  }  // Called by the libpng library when reading (decoding) the PNG file. We @@ -138,7 +138,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf  			this, &errorHandler, NULL);  		if (mReadPngPtr == NULL)  		{ -			BOOST_THROW_EXCEPTION(PngError("Problem creating png read structure")); +			LLTHROW(PngError("Problem creating png read structure"));  		}  		// Allocate/initialize the memory for image information. @@ -297,14 +297,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)  		if (mColorType == -1)  		{ -			BOOST_THROW_EXCEPTION(PngError("Unsupported image: unexpected number of channels")); +			LLTHROW(PngError("Unsupported image: unexpected number of channels"));  		}  		mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,  			NULL, &errorHandler, NULL);  		if (!mWritePngPtr)  		{ -			BOOST_THROW_EXCEPTION(PngError("Problem creating png write structure")); +			LLTHROW(PngError("Problem creating png write structure"));  		}  		mWriteInfoPtr = png_create_info_struct(mWritePngPtr); diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 2847f347c2..aa405362e8 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -1,4 +1,4 @@ - /**  +/**    * @file llimagej2ckdu.cpp   * @brief This is an implementation of JPEG2000 encode/decode using Kakadu   * @@ -31,19 +31,66 @@  #include "llpointer.h"  #include "llmath.h"  #include "llkdumem.h" +#include "stringize.h"  #include "kdu_block_coding.h"  #include "llexception.h" -#include <boost/throw_exception.hpp> +#include <boost/exception/diagnostic_information.hpp> +#include <sstream> +#include <iomanip>  namespace { -struct KDUError: public LLException +// Failure to load an image shouldn't crash the whole viewer. +struct KDUError: public LLContinueError  { -    KDUError(const std::string& msg): LLException(msg) {} +    KDUError(const std::string& msg): LLContinueError(msg) {}  }; + +// KDU defines int error codes as hex values, so we should log them in hex +// so we can grep KDU headers for the hex. However those hex values +// generally "happen" to encode big-endian multibyte character sequences, +// e.g. KDU_ERROR_EXCEPTION is 0x6b647545: 'kduE' +// But beware because KDU_NULL_EXCEPTION is simply 0 -- which doesn't +// preclude somebody from throwing it. +std::string report_kdu_exception(kdu_exception mb) +{ +    std::ostringstream out; +    // always report mb in hex +    out << "kdu_exception " << std::hex << mb; + +    // Also display as many chars as are encoded in the kdu_exception +    // value. Make a char array; reserve 1 extra byte for nul terminator. +    char bytes[sizeof(kdu_exception) + 1]; +    // Back up through 'bytes' +    char *bptr = bytes + sizeof(bytes); +    *(--bptr) = '\0'; +    while (mb) +    { +        // store low-order byte of mb in next-left char +        *(--bptr) = char(mb & 0xFF); +        // then shift mb right by one byte +        mb >>= 8; +    } +    // did that produce any characters? +    if (*bptr) +    { +        out << " (" << bptr << ')'; +    } + +    return out.str(); +}  } // anonymous namespace +// stream kdu_dims to std::ostream +// Turns out this must NOT be in the anonymous namespace! +inline +std::ostream& operator<<(std::ostream& out, const kdu_dims& dims) +{ +	return out << "(" << dims.pos.x << "," << dims.pos.y << ")," +				  "[" << dims.size.x << "x" << dims.size.y << "]"; +} +  class kdc_flow_control {  public: @@ -175,9 +222,15 @@ struct LLKDUMessageError : public LLKDUMessage  		// terminating handler→flush call."  		// So throwing an exception here isn't arbitrary: we MUST throw an  		// exception if we want to recover from a KDU error. +		// Because this confused me: the above quote specifically refers to +		// the kdu_error class, which is constructed internally within KDU at +		// the point where a fatal error is discovered and reported. It is NOT +		// talking about the kdu_message subclass passed to +		// kdu_customize_errors(). Destroying this static object at program +		// shutdown will NOT engage the behavior described above.  		if (end_of_message)   		{ -		BOOST_THROW_EXCEPTION(KDUError("LLKDUMessageError::flush()")); +			LLTHROW(KDUError("LLKDUMessageError::flush()"));  		}  	}  }; @@ -206,6 +259,10 @@ LLImageJ2CKDU::~LLImageJ2CKDU()  // Stuff for new simple decode  void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision); +// This is called by the real (private) initDecode() (keep_codestream true) +// and getMetadata() methods (keep_codestream false). As far as nat can tell, +// mode is always MODE_FAST. It was called by findDiscardLevelsBoundaries() +// as well, when that still existed, with keep_codestream true and MODE_FAST.  void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode)  {  	S32 data_size = base.getDataSize(); @@ -216,6 +273,12 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod  	//  	mCodeStreamp.reset(); +	// It's not clear to nat under what circumstances we would reuse a +	// pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of +	// two U32s and a pointer, so it's not as if it would be a huge overhead +	// to allocate a new one every time. +	// Also -- why is base.getData() tested specifically here? If that returns +	// NULL, shouldn't we bail out of the whole method?  	if (!mInputp && base.getData())  	{  		// The compressed data has been loaded @@ -272,13 +335,19 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod  	S32 components = mCodeStreamp->get_num_components(); -	if (components >= 3) -	{ // Check that components have consistent dimensions (for PPM file) -		kdu_dims dims1; mCodeStreamp->get_dims(1,dims1); -		kdu_dims dims2; mCodeStreamp->get_dims(2,dims2); -		if ((dims1 != dims) || (dims2 != dims)) +	// Check that components have consistent dimensions (for PPM file) +	for (int idx = 1; idx < components; ++idx) +	{ +		kdu_dims other_dims; +		mCodeStreamp->get_dims(idx, other_dims); +		if (other_dims != dims)  		{ -			LL_ERRS() << "Components don't have matching dimensions!" << LL_ENDL; +			// This method is only called from methods that catch KDUError. +			// We want to fail the image load, not crash the viewer. +			LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions " +									 << other_dims +									 << " do not match component 0 dimensions " +									 << dims << "!")));  		}  	} @@ -305,6 +374,9 @@ void LLImageJ2CKDU::cleanupCodeStream()  	mTileIndicesp.reset();  } +// This is the protected virtual method called by LLImageJ2C::initDecode(). +// However, as far as nat can tell, LLImageJ2C::initDecode() is called only by +// llimage_libtest.cpp's load_image() function. No detectable production use.  bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)  {  	return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region); @@ -337,6 +409,9 @@ bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc  	return true;  } +// This is the real (private) initDecode() called both by the protected +// initDecode() method and by decodeImpl(). As far as nat can tell, only the +// decodeImpl() usage matters for production.  bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)  {  	base.resetLastError(); @@ -399,9 +474,19 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco  		base.setLastError(msg.what());  		return false;  	} +	catch (kdu_exception kdu_value) +	{ +		// KDU internally throws kdu_exception. It's possible that such an +		// exception might leak out into our code. Catch kdu_exception +		// specially because boost::current_exception_diagnostic_information() +		// could do nothing with it. +		base.setLastError(report_kdu_exception(kdu_value)); +		return false; +	}  	catch (...)  	{ -		base.setLastError("Unknown J2C error"); +		base.setLastError("Unknown J2C error: " + +						  boost::current_exception_diagnostic_information());  		return false;  	} @@ -497,9 +582,21 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco  				cleanupCodeStream();  				return true; // done  			} +			catch (kdu_exception kdu_value) +			{ +				// KDU internally throws kdu_exception. It's possible that such an +				// exception might leak out into our code. Catch kdu_exception +				// specially because boost::current_exception_diagnostic_information() +				// could do nothing with it. +				base.setLastError(report_kdu_exception(kdu_value)); +				base.decodeFailed(); +				cleanupCodeStream(); +				return true; // done +			}  			catch (...)  			{ -				base.setLastError( "Unknown J2C error" ); +				base.setLastError("Unknown J2C error: " + +								  boost::current_exception_diagnostic_information());  				base.decodeFailed();  				cleanupCodeStream();  				return true; // done @@ -688,9 +785,19 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co  		base.setLastError(msg.what());  		return false;  	} +	catch (kdu_exception kdu_value) +	{ +		// KDU internally throws kdu_exception. It's possible that such an +		// exception might leak out into our code. Catch kdu_exception +		// specially because boost::current_exception_diagnostic_information() +		// could do nothing with it. +		base.setLastError(report_kdu_exception(kdu_value)); +		return false; +	}  	catch( ... )  	{ -		base.setLastError( "Unknown J2C error" ); +		base.setLastError("Unknown J2C error: " + +						  boost::current_exception_diagnostic_information());  		return false;  	} @@ -712,9 +819,19 @@ bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)  		base.setLastError(msg.what());  		return false;  	} +	catch (kdu_exception kdu_value) +	{ +		// KDU internally throws kdu_exception. It's possible that such an +		// exception might leak out into our code. Catch kdu_exception +		// specially because boost::current_exception_diagnostic_information() +		// could do nothing with it. +		base.setLastError(report_kdu_exception(kdu_value)); +		return false; +	}  	catch (...)  	{ -		base.setLastError( "Unknown J2C error" ); +		base.setLastError("Unknown J2C error: " + +						  boost::current_exception_diagnostic_information());  		return false;  	}  } diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 1ca5f58ae2..004db546b7 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -43,6 +43,8 @@  #include "llcoros.h"  #include "lleventcoro.h"  #include "llcorehttputil.h" +#include "llexception.h" +#include "stringize.h"  #include <map>  #include <set> @@ -231,13 +233,12 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU          LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);      } -    catch (std::exception e) -    { -        LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL; -    }      catch (...)      { -        LL_WARNS() << "Caught unknown exception." << LL_ENDL; +        LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName() +                                          << "('" << url << "', " << agentIds.size() +                                          << " Agent Ids)")); +        throw;      }  } diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index d4c0788b7d..74cdff2b00 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -27,6 +27,8 @@  #include "linden_common.h"   #include "llcoproceduremanager.h" +#include "llexception.h" +#include "stringize.h"  #include <boost/assign.hpp>  //========================================================================= @@ -388,14 +390,14 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap              {                  coproc->mProc(httpAdapter, coproc->mId);              } -            catch (std::exception &e) -            { -                LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << -                    " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; -            }              catch (...)              { -                LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL; +                LOG_UNHANDLED_EXCEPTION(STRINGIZE("Coprocedure('" << coproc->mName +                                                  << "', id=" << coproc->mId.asString() +                                                  << ") in pool '" << mPoolName << "'")); +                // must NOT omit this or we deplete the pool +                mActiveCoprocs.erase(itActive); +                throw;              }              LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index 48ce258ba2..04b34a296c 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -32,7 +32,6 @@  #include "llstl.h"  #include "llhttpconstants.h"  #include "llexception.h" -#include <boost/throw_exception.hpp>  const std::string CONTEXT_HEADERS("headers");  const std::string CONTEXT_PATH("path"); @@ -103,19 +102,19 @@ namespace {  // virtual  LLSD LLHTTPNode::simpleGet() const  { -	BOOST_THROW_EXCEPTION(NotImplemented()); +	LLTHROW(NotImplemented());  }  // virtual  LLSD LLHTTPNode::simplePut(const LLSD& input) const  { -	BOOST_THROW_EXCEPTION(NotImplemented()); +	LLTHROW(NotImplemented());  }  // virtual  LLSD LLHTTPNode::simplePost(const LLSD& input) const  { -	BOOST_THROW_EXCEPTION(NotImplemented()); +	LLTHROW(NotImplemented());  } @@ -175,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons  // virtual  LLSD LLHTTPNode::simpleDel(const LLSD&) const  { -	BOOST_THROW_EXCEPTION(NotImplemented()); +	LLTHROW(NotImplemented());  }  // virtual diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 5dff56b44f..7c8f27bbd2 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -38,7 +38,6 @@  #include <map>  #include <string>  #include <boost/lexical_cast.hpp> -#include <boost/throw_exception.hpp>  struct CommtestError: public LLException  { @@ -69,7 +68,7 @@ static int query_port(const std::string& var)      const char* cport = getenv(var.c_str());      if (! cport)      { -        BOOST_THROW_EXCEPTION(CommtestError(STRINGIZE("missing environment variable" << var))); +        LLTHROW(CommtestError(STRINGIZE("missing environment variable" << var)));      }      // This will throw, too, if the value of PORT isn't numeric.      int port(boost::lexical_cast<int>(cport)); diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 6aaecf9bac..5eb739393f 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -35,7 +35,6 @@  #include "llpumpio.h"  #include "llhttpclient.h"  #include "llexception.h" -#include <boost/throw_exception.hpp>  /*****************************************************************************  *   NetworkIO @@ -53,7 +52,7 @@ public:          ll_init_apr();          if (! gAPRPoolp)          { -            BOOST_THROW_EXCEPTION(LLException("Can't initialize APR")); +            LLTHROW(LLException("Can't initialize APR"));          }          // Create IO Pump to use for HTTP Requests. @@ -61,7 +60,7 @@ public:          LLHTTPClient::setPump(*mServicePump);          if (ll_init_ares() == NULL || !gAres->isInitialized())          { -            BOOST_THROW_EXCEPTION(LLException("Can't start DNS resolver")); +            LLTHROW(LLException("Can't start DNS resolver"));          }          // You can interrupt pump() without waiting the full timeout duration diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index b30bc1aed6..58c1186a3e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -349,8 +349,8 @@ void LLGLSLShader::unloadInternal()          for (GLsizei i = 0; i < count; i++)          {              glDetachObjectARB(mProgramObject, obj[i]); -            glDeleteObjectARB(obj[i]); -        } +                glDeleteObjectARB(obj[i]); +            }          glDeleteObjectARB(mProgramObject); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index b297223c2e..55f0791174 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -520,7 +520,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&  		if (!filename.empty())  		{              LL_CONT << "From " << filename << ":\n"; -        } +		}          LL_CONT << log << LL_ENDL;  	}   } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 62c3f401bf..fd7406b653 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -812,7 +812,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)  LLView*	LLView::childFromPoint(S32 x, S32 y, bool recur)  {  	if (!getVisible()) -		return false; +		return NULL;  	BOOST_FOREACH(LLView* viewp, mChildList)  	{ diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 24eb3947b4..9055e0111a 100644 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -4,15 +4,18 @@ add_subdirectory(base)  if (LINUX)      add_subdirectory(gstreamer010) +    add_subdirectory(libvlc)  endif (LINUX) -if (WINDOWS OR DARWIN) +if (DARWIN)      add_subdirectory(quicktime)      add_subdirectory(cef) -endif (WINDOWS OR DARWIN) +endif (DARWIN)  if (WINDOWS) +    add_subdirectory(cef)      add_subdirectory(winmmshim) +    add_subdirectory(libvlc)  endif (WINDOWS)  ### add_subdirectory(example) diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 8d9d1dd975..28a8a5886a 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -100,6 +100,12 @@ private:  	LLCEFLib* mLLCEFLib;      VolumeCatcher mVolumeCatcher; + +	U8 *mPopupBuffer; +	U32 mPopupW; +	U32 mPopupH; +	U32 mPopupX; +	U32 mPopupY;  };  //////////////////////////////////////////////////////////////////////////////// @@ -127,12 +133,19 @@ MediaPluginBase(host_send_func, host_user_data)  	mCookiePath = "";  	mPickedFile = "";  	mLLCEFLib = new LLCEFLib(); + +	mPopupBuffer = NULL; +	mPopupW = 0; +	mPopupH = 0; +	mPopupX = 0; +	mPopupY = 0;  }  ////////////////////////////////////////////////////////////////////////////////  //  MediaPluginCEF::~MediaPluginCEF()  { +	delete[] mPopupBuffer;  }  //////////////////////////////////////////////////////////////////////////////// @@ -155,20 +168,28 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg)  //  void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup)  { -	if (mPixels && pixels) +	if( is_popup ) +	{ +		delete mPopupBuffer; +		mPopupBuffer = NULL; +		mPopupH = 0; +		mPopupW = 0; +		mPopupX = 0; +		mPopupY = 0; +	} + +	if( mPixels && pixels )  	{  		if (is_popup)  		{ -			for (int line = 0; line < height; ++line) +			if( width > 0 && height> 0 )  			{ -				int inverted_y = mHeight - y - height; -				int src = line * width * mDepth; -				int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth; - -				if (dst + width * mDepth < mWidth * mHeight * mDepth) -				{ -					memcpy(mPixels + dst, pixels + src, width * mDepth); -				} +				mPopupBuffer = new U8[ width * height * mDepth ]; +				memcpy( mPopupBuffer, pixels, width * height * mDepth ); +				mPopupH = height; +				mPopupW = width; +				mPopupX = x; +				mPopupY = mHeight - y - height;  			}  		}  		else @@ -177,6 +198,23 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y,  			{  				memcpy(mPixels, pixels, mWidth * mHeight * mDepth);  			} +			if( mPopupBuffer && mPopupH && mPopupW ) +			{ +				U32 bufferSize = mWidth * mHeight * mDepth; +				U32 popupStride = mPopupW * mDepth; +				U32 bufferStride = mWidth * mDepth; +				int dstY = mPopupY; + +				int src = 0; +				int dst = dstY  * mWidth * mDepth + mPopupX * mDepth; + +				for( int line = 0; dst + popupStride < bufferSize && line < mPopupH; ++line ) +				{ +					memcpy( mPixels + dst, mPopupBuffer + src, popupStride ); +					src += popupStride; +					dst += bufferStride; +				} +			}  		}  		setDirty(0, 0, mWidth, mHeight); @@ -559,6 +597,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)  				S32 x = message_in.getValueS32("x");  				S32 y = message_in.getValueS32("y"); +				y = mHeight - y; +  				// only even send left mouse button events to LLCEFLib  				// (partially prompted by crash in OS X CEF when sending right button events)  				// we catch the right click in viewer and display our own context menu anyway diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt new file mode 100644 index 0000000000..535d29125b --- /dev/null +++ b/indra/media_plugins/libvlc/CMakeLists.txt @@ -0,0 +1,86 @@ +# -*- cmake -*- + +project(media_plugin_libvlc) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(OpenGL) + +include(LibVLCPlugin) + +include_directories( +    ${LLPLUGIN_INCLUDE_DIRS} +    ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} +    ${LLCOMMON_INCLUDE_DIRS} +    ${LLMATH_INCLUDE_DIRS} +    ${LLIMAGE_INCLUDE_DIRS} +    ${LLRENDER_INCLUDE_DIRS} +    ${LLWINDOW_INCLUDE_DIRS} +    ${VLC_INCLUDE_DIR} +) +include_directories(SYSTEM +    ${LLCOMMON_SYSTEM_INCLUDE_DIRS} +    ) + + +### media_plugin_libvlc + +if(NOT WORD_SIZE EQUAL 32) +  if(WINDOWS) +    add_definitions(/FIXED:NO) +  else(WINDOWS) # not windows therefore gcc LINUX and DARWIN +    add_definitions(-fPIC) +  endif(WINDOWS) +endif(NOT WORD_SIZE EQUAL 32) + +set(media_plugin_libvlc_SOURCE_FILES +    media_plugin_libvlc.cpp +    ) + +add_library(media_plugin_libvlc +    SHARED +    ${media_plugin_libvlc_SOURCE_FILES} +) + +target_link_libraries(media_plugin_libvlc +  ${LLPLUGIN_LIBRARIES} +  ${MEDIA_PLUGIN_BASE_LIBRARIES} +  ${LLCOMMON_LIBRARIES} +  ${VLC_PLUGIN_LIBRARIES} +  ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_libvlc +  ${LLPLUGIN_LIBRARIES} +  ${MEDIA_PLUGIN_BASE_LIBRARIES} +  ${LLCOMMON_LIBRARIES} +) + +if (WINDOWS) +  set_target_properties( +    media_plugin_libvlc +    PROPERTIES +    LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT" +    ) +endif (WINDOWS) + +if (DARWIN) +  # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name +  set_target_properties( +    media_plugin_libvlc +    PROPERTIES +    PREFIX "" +    BUILD_WITH_INSTALL_RPATH 1 +    INSTALL_NAME_DIR "@executable_path" +    LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" +  ) + +endif (DARWIN) diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp new file mode 100644 index 0000000000..0bd323eb58 --- /dev/null +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -0,0 +1,618 @@ +/** +* @file media_plugin_libvlc.cpp +* @brief LibVLC plugin for LLMedia API plugin system +* +* @cond +* $LicenseInfo:firstyear=2008&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$ +* @endcond +*/ + +#include "linden_common.h" + +#include "llgl.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include "vlc/vlc.h" +#include "vlc/libvlc_version.h" + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginLibVLC : +	public MediaPluginBase +{ +public: +	MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); +	~MediaPluginLibVLC(); + +	/*virtual*/ void receiveMessage(const char* message_string); + +private: +	bool init(); + +	void initVLC(); +	void playMedia(); +	void resetVLC(); +	void setVolume(const F64 volume); +	void updateTitle(const char* title); + +	static void* lock(void* data, void** p_pixels); +	static void unlock(void* data, void* id, void* const* raw_pixels); +	static void display(void* data, void* id); + +	/*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */; + +	static void eventCallbacks(const libvlc_event_t* event, void* ptr); + +	libvlc_instance_t* mLibVLC; +	libvlc_media_t* mLibVLCMedia; +	libvlc_media_player_t* mLibVLCMediaPlayer; + +	struct mLibVLCContext +	{ +		unsigned char* texture_pixels; +		libvlc_media_player_t* mp; +		MediaPluginLibVLC* parent; +	}; +	struct mLibVLCContext mLibVLCCallbackContext; + +	std::string mURL; +	F64 mCurVolume; + +	bool mIsLooping; + +	float mCurTime; +	float mDuration; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginLibVLC::MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : +MediaPluginBase(host_send_func, host_user_data) +{ +	mTextureWidth = 0; +	mTextureHeight = 0; +	mWidth = 0; +	mHeight = 0; +	mDepth = 4; +	mPixels = 0; + +	mLibVLC = 0; +	mLibVLCMedia = 0; +	mLibVLCMediaPlayer = 0; + +	mCurVolume = 0.0; + +	mIsLooping = false; + +	mCurTime = 0.0; +	mDuration = 0.0; + +	mURL = std::string(); + +	setStatus(STATUS_NONE); +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginLibVLC::~MediaPluginLibVLC() +{ +} + +///////////////////////////////////////////////////////////////////////////////// +// +void* MediaPluginLibVLC::lock(void* data, void** p_pixels) +{ +	struct mLibVLCContext* context = (mLibVLCContext*)data; + +	*p_pixels = context->texture_pixels; + +	return NULL; +} + +///////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels) +{ +	// nothing to do here for the moment +	// we *could* modify pixels here to, for example, Y flip, but this is done with +	// a VLC video filter transform.  +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::display(void* data, void* id) +{ +	struct mLibVLCContext* context = (mLibVLCContext*)data; + +	context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::initVLC() +{ +	char const* vlc_argv[] = +	{ +		"--no-xlib", +		"--video-filter=transform{type=vflip}",  // MAINT-6578 Y flip textures in plugin vs client +	}; + +	int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); +	mLibVLC = libvlc_new(vlc_argc, vlc_argv); + +	if (!mLibVLC) +	{ +		// for the moment, if this fails, the plugin will fail and  +		// the media sub-system will tell the viewer something went wrong. +	} +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::resetVLC() +{ +	libvlc_media_player_stop(mLibVLCMediaPlayer); +	libvlc_media_player_release(mLibVLCMediaPlayer); +	libvlc_release(mLibVLC); +} + +//////////////////////////////////////////////////////////////////////////////// +// *virtual* +void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom) +{ +	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + +	message.setValueS32("left", left); +	message.setValueS32("top", top); +	message.setValueS32("right", right); +	message.setValueS32("bottom", bottom); + +	message.setValueReal("current_time", mCurTime); +	message.setValueReal("duration", mDuration); +	message.setValueReal("current_rate", 1.0f); + +	sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) +{ +	MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr; +	if (parent == 0) +	{ +		return; +	} + +	switch (event->type) +	{ +	case libvlc_MediaPlayerOpening: +		parent->setStatus(STATUS_LOADING); +		break; + +	case libvlc_MediaPlayerPlaying: +		parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f; +		parent->setStatus(STATUS_PLAYING); +		break; + +	case libvlc_MediaPlayerPaused: +		parent->setStatus(STATUS_PAUSED); +		break; + +	case libvlc_MediaPlayerStopped: +		parent->setStatus(STATUS_DONE); +		break; + +	case libvlc_MediaPlayerEndReached: +		parent->setStatus(STATUS_DONE); +		break; + +	case libvlc_MediaPlayerEncounteredError: +		parent->setStatus(STATUS_ERROR); +		break; + +	case libvlc_MediaPlayerTimeChanged: +		parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f; +		break; + +	case libvlc_MediaPlayerPositionChanged: +		break; + +	case libvlc_MediaPlayerLengthChanged: +		parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f; +		break; + +	case libvlc_MediaPlayerTitleChanged: +	{ +		char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title); +		if (title) +		{ +			parent->updateTitle(title); +		} +	} +	break; +	} +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::playMedia() +{ +	if (mURL.length() == 0) +	{ +		return; +	} + +	if (mLibVLCMediaPlayer) +	{ +		// stop listening to events while we reset things +		libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer); +		if (em) +		{ +			libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL); +			libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL); +		}; + +		libvlc_media_player_stop(mLibVLCMediaPlayer); +		libvlc_media_player_release(mLibVLCMediaPlayer); + +		mLibVLCMediaPlayer = 0; +	} + +	if (mLibVLCMedia) +	{ +		libvlc_media_release(mLibVLCMedia); + +		mLibVLCMedia = 0; +	} + +	mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str()); +	if (!mLibVLCMedia) +	{ +		mLibVLCMediaPlayer = 0; +		setStatus(STATUS_ERROR); +		return; +	} + +	mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia); +	if (!mLibVLCMediaPlayer) +	{ +		setStatus(STATUS_ERROR); +		return; +	} + +	// listen to events +	libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer); +	if (em) +	{ +		libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this); +		libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this); +	} + +	mLibVLCCallbackContext.parent = this; +	mLibVLCCallbackContext.texture_pixels = mPixels; +	mLibVLCCallbackContext.mp = mLibVLCMediaPlayer; + +	// Send a "navigate begin" event. +	// This is really a browser message but the QuickTime plugin did it and  +	// the media system relies on this message to update internal state so we must send it too +	// Note: see "navigate_complete" message below too +	// https://jira.secondlife.com/browse/MAINT-6528 +	LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); +	message_begin.setValue("uri", mURL); +	message_begin.setValueBoolean("history_back_available", false); +	message_begin.setValueBoolean("history_forward_available", false); +	sendMessage(message_begin); + +	// volume level gets set before VLC is initialized (thanks media system) so we have to record +	// it in mCurVolume and set it again here so that volume levels are correctly initialized +	setVolume(mCurVolume); + +	setStatus(STATUS_LOADED); + +	libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext); +	libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); + +	// note this relies on the "set_loop" message arriving before the "start" (play) one +	// but that appears to always be the case +	if (mIsLooping) +	{ +		libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1"); +	} + +	libvlc_media_player_play(mLibVLCMediaPlayer); + +	// send a "location_changed" message - this informs the media system +	// that a new URL is the 'current' one and is used extensively. +	// Again, this is really a browser message but we will use it here. +	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); +	message.setValue("uri", mURL); +	sendMessage(message); + +	// Send a "navigate complete" event. +	// This is really a browser message but the QuickTime plugin did it and  +	// the media system relies on this message to update internal state so we must send it too +	// Note: see "navigate_begin" message above too +	// https://jira.secondlife.com/browse/MAINT-6528 +	LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); +	message_complete.setValue("uri", mURL); +	message_complete.setValueS32("result_code", 200); +	message_complete.setValue("result_string", "OK"); +	sendMessage(message_complete); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::updateTitle(const char* title) +{ +	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); +	message.setValue("name", title); +	sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::setVolume(const F64 volume) +{ +	mCurVolume = volume; + +	if (mLibVLCMediaPlayer) +	{ +		int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, (int)(volume * 100)); +		if (result != 0) +		{ +			// volume wasn't set but not much to be done here +		} +	} +	else +	{ +		// volume change was requested but VLC wasn't ready. +		// that's okay thought because we saved the value in mCurVolume and  +		// the next volume change after the VLC system is initilzied  will set it +	} +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::receiveMessage(const char* message_string) +{ +	LLPluginMessage message_in; + +	if (message_in.parse(message_string) >= 0) +	{ +		std::string message_class = message_in.getClass(); +		std::string message_name = message_in.getName(); +		if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) +		{ +			if (message_name == "init") +			{ +				initVLC(); + +				LLPluginMessage message("base", "init_response"); +				LLSD versions = LLSD::emptyMap(); +				versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; +				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; +				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; +				message.setValueLLSD("versions", versions); + +				std::ostringstream s; +				s << "LibVLC plugin "; +				s << LIBVLC_VERSION_MAJOR; +				s << "."; +				s << LIBVLC_VERSION_MINOR; +				s << "."; +				s << LIBVLC_VERSION_REVISION; + +				message.setValue("plugin_version", s.str()); +				sendMessage(message); +			} +			else if (message_name == "idle") +			{ +			} +			else if (message_name == "cleanup") +			{ +				resetVLC(); +			} +			else if (message_name == "shm_added") +			{ +				SharedSegmentInfo info; +				info.mAddress = message_in.getValuePointer("address"); +				info.mSize = (size_t)message_in.getValueS32("size"); +				std::string name = message_in.getValue("name"); + +				mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + +			} +			else if (message_name == "shm_remove") +			{ +				std::string name = message_in.getValue("name"); + +				SharedSegmentMap::iterator iter = mSharedSegments.find(name); +				if (iter != mSharedSegments.end()) +				{ +					if (mPixels == iter->second.mAddress) +					{ +						libvlc_media_player_stop(mLibVLCMediaPlayer); +						libvlc_media_player_release(mLibVLCMediaPlayer); +						mLibVLCMediaPlayer = 0; + +						mPixels = NULL; +						mTextureSegmentName.clear(); +					} +					mSharedSegments.erase(iter); +				} +				else +				{ +					//std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; +				} + +				// Send the response so it can be cleaned up. +				LLPluginMessage message("base", "shm_remove_response"); +				message.setValue("name", name); +				sendMessage(message); +			} +			else +			{ +				//std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; +			} +		} +		else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) +		{ +			if (message_name == "init") +			{ +				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); +				message.setValueS32("default_width", 1024); +				message.setValueS32("default_height", 1024); +				message.setValueS32("depth", mDepth); +				message.setValueU32("internalformat", GL_RGB); +				message.setValueU32("format", GL_BGRA_EXT); +				message.setValueU32("type", GL_UNSIGNED_BYTE); +				message.setValueBoolean("coords_opengl", true); +				sendMessage(message); +			} +			else if (message_name == "size_change") +			{ +				std::string name = message_in.getValue("name"); +				S32 width = message_in.getValueS32("width"); +				S32 height = message_in.getValueS32("height"); +				S32 texture_width = message_in.getValueS32("texture_width"); +				S32 texture_height = message_in.getValueS32("texture_height"); + +				if (!name.empty()) +				{ +					// Find the shared memory region with this name +					SharedSegmentMap::iterator iter = mSharedSegments.find(name); +					if (iter != mSharedSegments.end()) +					{ +						mPixels = (unsigned char*)iter->second.mAddress; +						mWidth = width; +						mHeight = height; +						mTextureWidth = texture_width; +						mTextureHeight = texture_height; + +						playMedia(); +					}; +				}; + +				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); +				message.setValue("name", name); +				message.setValueS32("width", width); +				message.setValueS32("height", height); +				message.setValueS32("texture_width", texture_width); +				message.setValueS32("texture_height", texture_height); +				sendMessage(message); +			} +			else if (message_name == "load_uri") +			{ +				mURL = message_in.getValue("uri"); +				playMedia(); +			} +		} +		else +			if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) +			{ +				if (message_name == "stop") +				{ +					if (mLibVLCMediaPlayer) +					{ +						libvlc_media_player_stop(mLibVLCMediaPlayer); +					} +				} +				else if (message_name == "start") +				{ +					if (mLibVLCMediaPlayer) +					{ +						libvlc_media_player_play(mLibVLCMediaPlayer); +					} +				} +				else if (message_name == "pause") +				{ +					if (mLibVLCMediaPlayer) +					{ +						libvlc_media_player_pause(mLibVLCMediaPlayer); +					} +				} +				else if (message_name == "seek") +				{ +					if (mDuration > 0) +					{ +						F64 normalized_offset = message_in.getValueReal("time") / mDuration; +						libvlc_media_player_set_position(mLibVLCMediaPlayer, normalized_offset); +					} +				} +				else if (message_name == "set_loop") +				{ +					mIsLooping = true; +				} +				else if (message_name == "set_volume") +				{ +					// volume comes in 0 -> 1.0 +					F64 volume = message_in.getValueReal("volume"); +					setVolume(volume); +				} +			} +	} +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginLibVLC::init() +{ +	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); +	message.setValue("name", "LibVLC Plugin"); +	sendMessage(message); + +	return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, +	void* host_user_data, +	LLPluginInstance::sendMessageFunction *plugin_send_func, +	void **plugin_user_data) +{ +	MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data); +	*plugin_send_func = MediaPluginLibVLC::staticReceiveMessage; +	*plugin_user_data = (void*)self; + +	return 0; +} diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt index c5615145be..58391007ff 100644..100755 --- a/indra/media_plugins/quicktime/CMakeLists.txt +++ b/indra/media_plugins/quicktime/CMakeLists.txt @@ -14,7 +14,6 @@ include(PluginAPI)  include(MediaPluginBase)  include(OpenGL)  include(QuickTimePlugin) -include(Boost)  include_directories(      ${LLPLUGIN_INCLUDE_DIRS} @@ -54,12 +53,17 @@ target_link_libraries(media_plugin_quicktime    ${PLUGIN_API_WINDOWS_LIBRARIES}  ) +add_dependencies(media_plugin_quicktime +  ${LLPLUGIN_LIBRARIES} +  ${MEDIA_PLUGIN_BASE_LIBRARIES} +  ${LLCOMMON_LIBRARIES} +) +  if (WINDOWS)    set_target_properties(      media_plugin_quicktime      PROPERTIES -    LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT" -    LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD" +    LINK_FLAGS "/MANIFEST:NO"      )  endif (WINDOWS) diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 7ef5a0fe44..b43598e4a5 100644..100755 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -837,9 +837,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)  			else if(message_name == "cleanup")  			{  				// TODO: clean up here -                LLPluginMessage message("base", "goodbye"); -                sendMessage(message); -            } +			}  			else if(message_name == "shm_added")  			{  				SharedSegmentInfo info; @@ -921,6 +919,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)  				#endif  				message.setValueS32("depth", mDepth);  				message.setValueU32("internalformat", GL_RGB); + +                // note this apparently only has an effect when media is opened in 2D browser.  +                // see https://jira.secondlife.com/browse/BUG-18252 - media flipped in 2D so flipping it back.  				message.setValueBoolean("coords_opengl", true);	// true == use OpenGL-style coordinates, false == (0,0) is upper left.  				message.setValueBoolean("allow_downsample", true);  				sendMessage(message); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dce0ea73cd..b505bd3316 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1750,6 +1750,7 @@ if (WINDOWS)        SLPlugin        media_plugin_quicktime        media_plugin_cef +      media_plugin_libvlc        winmm_shim        windows-crash-logger        ) @@ -1965,6 +1966,7 @@ if (LINUX)      linux-crash-logger      SLPlugin      media_plugin_gstreamer010 +    media_plugin_libvlc      llcommon      ) @@ -2072,7 +2074,7 @@ if (DARWIN)        ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py      ) -  add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger) +  add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_libvlc media_plugin_cef mac-crash-logger)    add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)    if (ENABLE_SIGNING) diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index a2cec7aff4..627a3f43a6 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -4.0.8 +4.1.1 diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index 92a5413adb..1dddf52961 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -31,6 +31,8 @@  #include "llcoros.h"  #include "lleventcoro.h"  #include "llcorehttputil.h" +#include "llexception.h" +#include "stringize.h"  #include <algorithm>  #include <iterator> @@ -154,13 +156,11 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,          } while (false);      } -    catch (std::exception e) -    { -        LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL; -    }      catch (...)      { -        LL_WARNS() << "Caught unknown exception." << LL_ENDL; +        LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName() +                                          << "('" << url << "')")); +        throw;      }      mPendingObjectQuota.clear(); diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index dbcae57de7..c1f898284a 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -30,6 +30,8 @@  #include "llappviewer.h"  #include "llviewercontrol.h" +#include "llexception.h" +#include "stringize.h"  #include <openssl/x509_vfy.h>  #include <openssl/ssl.h> @@ -551,6 +553,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,  	}  	catch (...)  	{ +		LOG_UNHANDLED_EXCEPTION(STRINGIZE("('" << url << "')"));  		// any other odd error, we just handle as a connect error.  		result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR);  	} diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b8d511804d..d31008f1c4 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -125,7 +125,10 @@  #include "llexception.h"  #if !LL_LINUX  #include "cef/llceflib.h" -#endif +#if LL_WINDOWS +#include "vlc/libvlc_version.h" +#endif // LL_WINDOWS +#endif // LL_LINUX  // Third party library includes  #include <boost/bind.hpp> @@ -923,7 +926,7 @@ bool LLAppViewer::init()  	// Provide the text fields with callbacks for opening Urls  	LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null)); -	LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null)); +	LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false));  	LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));  	LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor); @@ -1538,10 +1541,14 @@ bool LLAppViewer::frame()  			resumeMainloopTimeout();  			pingMainloopTimeout("Main:End"); -		}	 +		} +	} +	catch (const LLContinueError&) +	{ +		LOG_UNHANDLED_EXCEPTION("");  	}  	catch(std::bad_alloc) -	{			 +	{  		LLMemory::logMemoryInfo(TRUE) ;  		//stop memory leaking simulation @@ -1549,7 +1556,7 @@ bool LLAppViewer::frame()  			LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");  		if(mem_leak_instance)  		{ -			mem_leak_instance->stop() ;				 +			mem_leak_instance->stop() ;  			LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;  		}  		else @@ -1560,6 +1567,10 @@ bool LLAppViewer::frame()  			LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;  		}  	} +	catch (...) +	{ +		CRASH_ON_UNHANDLED_EXCEPTION(""); +	}  	if (LLApp::isExiting())  	{ @@ -1573,7 +1584,7 @@ bool LLAppViewer::frame()  			catch(std::bad_alloc)  			{  				LL_WARNS() << "Bad memory allocation when saveFinalSnapshot() is called!" << LL_ENDL ; -				 +  				//stop memory leaking simulation  				LLFloaterMemLeak* mem_leak_instance =  				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); @@ -1582,12 +1593,16 @@ bool LLAppViewer::frame()  					mem_leak_instance->stop() ;  				}  			} +			catch (...) +			{ +				CRASH_ON_UNHANDLED_EXCEPTION("saveFinalSnapshot()"); +			}  		} -		 +  		delete gServicePump; -		 +  		destroyMainloopTimeout(); -		 +  		LL_INFOS() << "Exiting main_loop" << LL_ENDL;  	} @@ -3315,6 +3330,19 @@ LLSD LLAppViewer::getViewerInfo() const  	info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION;  #else  	info["LLCEFLIB_VERSION"] = "Undefined"; + +#endif + +#if LL_WINDOWS +	std::ostringstream ver_codec; +	ver_codec << LIBVLC_VERSION_MAJOR; +	ver_codec << "."; +	ver_codec << LIBVLC_VERSION_MINOR; +	ver_codec << "."; +	ver_codec << LIBVLC_VERSION_REVISION; +	info["LIBVLC_VERSION"] = ver_codec.str(); +#else +	info["LIBVLC_VERSION"] = "Undefined";  #endif  	S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN); @@ -5519,7 +5547,7 @@ void LLAppViewer::forceErrorInfiniteLoop()  void LLAppViewer::forceErrorSoftwareException()  {     	LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; -    BOOST_THROW_EXCEPTION(LLException("User selected Force Software Exception")); +    LLTHROW(LLException("User selected Force Software Exception"));  }  void LLAppViewer::forceErrorDriverCrash() diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index a7f248ab5a..af0cd27fd5 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -328,33 +328,33 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,  		// app cleanup if there was a problem.  		//  #if WINDOWS_CRT_MEM_CHECKS -    LL_INFOS() << "CRT Checking memory:" << LL_ENDL; -	if (!_CrtCheckMemory()) -	{ -		LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL; -	} -	else -	{ -		LL_INFOS() << " No corruption detected." << LL_ENDL; -	} +		LL_INFOS() << "CRT Checking memory:" << LL_ENDL; +		if (!_CrtCheckMemory()) +		{ +			LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL; +		} +		else +		{ +			LL_INFOS() << " No corruption detected." << LL_ENDL; +		}  #endif -	 -	gGLActive = TRUE; -	viewer_app_ptr->cleanup(); -	 +		gGLActive = TRUE; + +		viewer_app_ptr->cleanup(); +  #if WINDOWS_CRT_MEM_CHECKS -    LL_INFOS() << "CRT Checking memory:" << LL_ENDL; -	if (!_CrtCheckMemory()) -	{ -		LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL; -	} -	else -	{ -		LL_INFOS() << " No corruption detected." << LL_ENDL; -	} +		LL_INFOS() << "CRT Checking memory:" << LL_ENDL; +		if (!_CrtCheckMemory()) +		{ +			LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL; +		} +		else +		{ +			LL_INFOS() << " No corruption detected." << LL_ENDL; +		}  #endif -	  +  	}  	delete viewer_app_ptr;  	viewer_app_ptr = NULL; diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 54f96b8872..90a5483dc9 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -43,7 +43,6 @@  #include <boost/bind.hpp>  #include <boost/tokenizer.hpp>  #include <boost/assign/list_of.hpp> -#include <boost/throw_exception.hpp>  #if _MSC_VER  #   pragma warning(pop) @@ -52,6 +51,7 @@  #include "llsdserialize.h"  #include "llerror.h"  #include "stringize.h" +#include "llexception.h"  #include <string>  #include <set>  #include <iostream> @@ -204,17 +204,17 @@ protected:      {          if(gPastLastOption)          { -            BOOST_THROW_EXCEPTION(LLCLPLastOption("Don't parse no more!")); +            LLTHROW(LLCLPLastOption("Don't parse no more!"));          }          // Error checks. Needed?          if (!value_store.empty() && !is_composing())           { -            BOOST_THROW_EXCEPTION(LLCLPError("Non composing value with multiple occurences.")); +            LLTHROW(LLCLPError("Non composing value with multiple occurences."));          }          if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens())          { -            BOOST_THROW_EXCEPTION(LLCLPError("Illegal number of tokens specified.")); +            LLTHROW(LLCLPError("Illegal number of tokens specified."));          }          if(value_store.empty()) @@ -468,7 +468,7 @@ onevalue(const std::string& option,      {          // What does it mean when the user specifies a command-line switch          // that requires a value, but omits the value? Complain. -        BOOST_THROW_EXCEPTION(LLCLPError(STRINGIZE("No value specified for --" << option << "!"))); +        LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!")));      }      else if (value.size() > 1)      { @@ -486,10 +486,9 @@ void badvalue(const std::string& option,      // If the user passes an unusable value for a command-line switch, it      // seems like a really bad idea to just ignore it, even with a log      // warning. -    BOOST_THROW_EXCEPTION( -        LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option -                             << "' for variable '" << varname << "' of type " << type -                             << ": '" << value << "'"))); +    LLTHROW(LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option +                                 << "' for variable '" << varname << "' of type " << type +                                 << ": '" << value << "'")));  }  template <typename T> diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 024e315632..dece3fc1ea 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -55,7 +55,8 @@ LLFloaterWebContent::_Params::_Params()  	preferred_media_size("preferred_media_size"),  	trusted_content("trusted_content", false),  	show_page_title("show_page_title", true), -    clean_browser("clean_browser", false) +	clean_browser("clean_browser", false), +	dev_mode("dev_mode", false)  {}  LLFloaterWebContent::LLFloaterWebContent( const Params& params ) @@ -74,14 +75,16 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params )  	mShowPageTitle(params.show_page_title),      mAllowNavigation(true),      mCurrentURL(""), -    mDisplayURL("") +    mDisplayURL(""), +    mDevelopMode(params.dev_mode) // if called from "Develop" Menu, set a flag and change things to be more useful for devs  {  	mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));  	mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));  	mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));  	mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));  	mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); -	mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this )); +	mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind(&LLFloaterWebContent::onPopExternal, this)); +	mCommitCallbackRegistrar.add( "WebContent.TestURL", boost::bind(&LLFloaterWebContent::onTestURL, this, _2));  }  BOOL LLFloaterWebContent::postBuild() @@ -195,8 +198,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)  						width + getRect().getWidth() - browser_rect.getWidth(),   						height + getRect().getHeight() - browser_rect.getHeight()); -	LL_DEBUGS() << "geometry change: " << geom << LL_ENDL; -	  	LLRect new_rect;  	getParent()->screenRectToLocal(geom, &new_rect);  	setShape(new_rect);	 @@ -205,8 +206,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)  // static  void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)  { -	LL_DEBUGS() << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << LL_ENDL; -  	if (!p.id.isProvided())  	{  		p.id = LLUUID::generateNewID().asString(); @@ -224,12 +223,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)  		// and close the least recently opened one if this will put us over the limit.  		LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class); -		LL_DEBUGS() << "total instance count is " << instances.size() << LL_ENDL; - -		for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) -		{ -			LL_DEBUGS() << "    " << (*iter)->getKey()["target"] << LL_ENDL; -		}  		if(instances.size() >= (size_t)browser_window_limit)  		{ @@ -241,16 +234,19 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)  void LLFloaterWebContent::open_media(const Params& p)  { -	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.  	LLViewerMedia::proxyWindowOpened(p.target(), p.id()); -	mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML); +	mWebBrowser->setHomePageUrl(p.url);  	mWebBrowser->setTarget(p.target); -	mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML, p.clean_browser); +	mWebBrowser->navigateTo(p.url);  	set_current_url(p.url);  	getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome);  	getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome); + +	// turn additional debug controls on but only for Develop mode (Develop menu open) +	getChild<LLLayoutPanel>("debug_controls")->setVisible(mDevelopMode); +  	bool address_entry_enabled = p.allow_address_entry && !p.trusted_content;      mAllowNavigation = p.allow_back_forward_navigation;  	getChildView("address")->setEnabled(address_entry_enabled); @@ -499,7 +495,7 @@ void LLFloaterWebContent::onEnterAddress()      LLStringUtil::trim(url);  	if ( url.length() > 0 )  	{ -		mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); +		mWebBrowser->navigateTo(url);  	};  } @@ -508,9 +504,18 @@ void LLFloaterWebContent::onPopExternal()  	// make sure there is at least something there.  	// (perhaps this test should be for minimum length of a URL)  	std::string url = mAddressCombo->getValue().asString(); -    LLStringUtil::trim(url); -	if ( url.length() > 0 ) +	LLStringUtil::trim(url); +	if (url.length() > 0) +	{ +		LLWeb::loadURLExternal(url); +	}; +} + +void LLFloaterWebContent::onTestURL(std::string url) +{ +	LLStringUtil::trim(url); +	if (url.length() > 0)  	{ -		LLWeb::loadURLExternal( url ); +		mWebBrowser->navigateTo(url);  	};  } diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 4291fd9f2c..0bf93504c2 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -58,7 +58,8 @@ public:                                  allow_back_forward_navigation,  								trusted_content,  								show_page_title, -                                clean_browser; +								clean_browser, +								dev_mode;  		Optional<LLRect>		preferred_media_size;  		_Params(); @@ -92,6 +93,7 @@ protected:  	void onClickStop();  	void onEnterAddress();  	void onPopExternal(); +	void onTestURL(std::string url);  	static void preCreate(Params& p);  	void open_media(const Params& ); @@ -113,6 +115,7 @@ protected:  	std::string		mUUID;  	bool			mShowPageTitle;      bool            mAllowNavigation; +	bool			mDevelopMode;  };  #endif  // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 763657ebad..0bcd8a9e63 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -95,7 +95,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :  	mVolumeSliderVisible(0),  	mWindowShade(NULL),  	mHideImmediately(false), -    mSecureURL(false) +    mSecureURL(false), +	mMediaPlaySliderCtrlMouseDownValue(0.0)  {  	mCommitCallbackRegistrar.add("MediaCtrl.Close",		boost::bind(&LLPanelPrimMediaControls::onClickClose, this));  	mCommitCallbackRegistrar.add("MediaCtrl.Back",		boost::bind(&LLPanelPrimMediaControls::onClickBack, this)); @@ -109,7 +110,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :  	mCommitCallbackRegistrar.add("MediaCtrl.Open",		boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));  	mCommitCallbackRegistrar.add("MediaCtrl.Zoom",		boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));  	mCommitCallbackRegistrar.add("MediaCtrl.CommitURL",	boost::bind(&LLPanelPrimMediaControls::onCommitURL, this)); -	mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress",		boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this)); +	mCommitCallbackRegistrar.add("MediaCtrl.MouseDown", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown, this)); +	mCommitCallbackRegistrar.add("MediaCtrl.MouseUp", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp, this));  	mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp",	boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));  	mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown",	boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));  	mCommitCallbackRegistrar.add("MediaCtrl.Volume",	boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this)); @@ -1246,26 +1248,38 @@ void LLPanelPrimMediaControls::setCurrentURL()  #endif	// USE_COMBO_BOX_FOR_MEDIA_URL  } -void LLPanelPrimMediaControls::onCommitSlider() + +void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown()  { -	focusOnTarget(); +	mMediaPlaySliderCtrlMouseDownValue = mMediaPlaySliderCtrl->getValue().asReal(); -	LLViewerMediaImpl* media_impl = getTargetMediaImpl(); -	if (media_impl)  +	mUpdateSlider = false; +} + +void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp() +{ +	F64 cur_value = mMediaPlaySliderCtrl->getValue().asReal(); + +	if (mMediaPlaySliderCtrlMouseDownValue != cur_value)  	{ -		// get slider value -		F64 slider_value = mMediaPlaySliderCtrl->getValue().asReal(); -		if(slider_value <= 0.0) -		{	 -			media_impl->stop(); -		} -		else  +		focusOnTarget(); + +		LLViewerMediaImpl* media_impl = getTargetMediaImpl(); +		if (media_impl)  		{ -			media_impl->seek(slider_value*mMovieDuration); -			//mUpdateSlider= false; +			if (cur_value <= 0.0) +			{ +				media_impl->stop(); +			} +			else +			{ +				media_impl->seek(cur_value * mMovieDuration); +			}  		} + +		mUpdateSlider = true;  	} -}		 +}  void LLPanelPrimMediaControls::onCommitVolumeUp()  { diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 6d2eb3430e..21d5236074 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -107,8 +107,10 @@ private:  	void updateZoom();  	void setCurrentURL(); -	void onCommitSlider(); -	 + +	void onMediaPlaySliderCtrlMouseDown(); +	void onMediaPlaySliderCtrlMouseUp(); +  	void onCommitVolumeUp();  	void onCommitVolumeDown();  	void onCommitVolumeSlider(); @@ -219,6 +221,8 @@ private:  	S32 mVolumeSliderVisible;  	LLNotificationPtr mActiveNotification; + +	F64 mMediaPlaySliderCtrlMouseDownValue;  };  #endif // LL_PANELPRIMMEDIACONTROLS_H diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index bcb9417820..72d7cf1e45 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -29,7 +29,8 @@  #include "llviewerprecompiledheaders.h"  #include "llsecapi.h"  #include "llsechandler_basic.h" -#include <boost/throw_exception.hpp> +#include "llexception.h" +#include "stringize.h"  #include <openssl/evp.h>  #include <openssl/err.h>  #include <map> @@ -70,7 +71,7 @@ void initializeSecHandler()  	}  	if (!exception_msg.empty())  // an exception was thrown.  	{ -		BOOST_THROW_EXCEPTION(LLProtectedDataException(exception_msg)); +		LLTHROW(LLProtectedDataException(exception_msg));  	}  } @@ -102,6 +103,7 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred)  LLSD LLCredential::getLoginParams()  {  	LLSD result = LLSD::emptyMap(); +	std::string username;  	try   	{  		if (mIdentifier["type"].asString() == "agent") @@ -110,17 +112,19 @@ LLSD LLCredential::getLoginParams()  			result["passwd"] = "$1$" + mAuthenticator["secret"].asString();  			result["first"] = mIdentifier["first_name"];  			result["last"] = mIdentifier["last_name"]; -		 +			username = result["first"].asString() + " " + result["last"].asString();  		}  		else if (mIdentifier["type"].asString() == "account")  		{  			result["username"] = mIdentifier["account_name"];  			result["passwd"] = mAuthenticator["secret"]; -										 +			username = result["username"].asString();  		}  	}  	catch (...)  	{ +		// nat 2016-08-18: not clear what exceptions the above COULD throw?! +		LOG_UNHANDLED_EXCEPTION(STRINGIZE("for '" << username << "'"));  		// we could have corrupt data, so simply return a null login param if so  		LL_WARNS("AppInit") << "Invalid credential" << LL_ENDL;  	} diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 39ce64ad0e..d6fb801cc0 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -35,7 +35,8 @@  #include "llfile.h"  #include "lldir.h"  #include "llviewercontrol.h" -#include <boost/throw_exception.hpp> +#include "llexception.h" +#include "stringize.h"  #include <vector>  #include <ios>  #include <openssl/ossl_typ.h> @@ -73,14 +74,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert)  	if(pem_bio == NULL)  	{  		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; -		BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); +		LLTHROW(LLInvalidCertificate(this));  	}  	mCert = NULL;  	PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);  	BIO_free(pem_bio);  	if (!mCert)  	{ -		BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); +		LLTHROW(LLInvalidCertificate(this));  	}  } @@ -89,7 +90,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert)  {  	if (!pCert || !pCert->cert_info)  	{ -		BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); +		LLTHROW(LLInvalidCertificate(this));  	}	  	mCert = X509_dup(pCert);  } @@ -618,7 +619,7 @@ void LLBasicCertificateStore::load_from_file(const std::string& filename)  				}  				catch (...)  				{ -					LL_WARNS("SECAPI") << "Failure creating certificate from the certificate store file." << LL_ENDL; +					LOG_UNHANDLED_EXCEPTION("creating certificate from the certificate store file");  				}  				X509_free(cert_x509);  				cert_x509 = NULL; @@ -874,22 +875,22 @@ void _validateCert(int validation_policy,  	// check basic properties exist in the cert  	if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))  	{ -		BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have a Subject Name"));				 +		LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name"));  	}  	if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))  	{ -		BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an Issuer Name"));				 +		LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name"));  	}  	// check basic properties exist in the cert  	if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))  	{ -		BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an expiration period"));				 +		LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period"));  	}  	if (!current_cert_info.has(CERT_SHA1_DIGEST))  	{ -		BOOST_THROW_EXCEPTION(LLCertException(cert, "No SHA1 digest")); +		LLTHROW(LLCertException(cert, "No SHA1 digest"));  	}  	if (validation_policy & VALIDATION_POLICY_TIME) @@ -904,7 +905,7 @@ void _validateCert(int validation_policy,  		if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||  		   (validation_date > current_cert_info[CERT_VALID_TO].asDate()))  		{ -			BOOST_THROW_EXCEPTION(LLCertValidationExpirationException(cert, validation_date)); +			LLTHROW(LLCertValidationExpirationException(cert, validation_date));  		}  	}  	if (validation_policy & VALIDATION_POLICY_SSL_KU) @@ -915,14 +916,14 @@ void _validateCert(int validation_policy,  			!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],   									  LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))  		{ -			BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert)); +			LLTHROW(LLCertKeyUsageValidationException(cert));  		}  		// only validate EKU if the cert has it  		if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&	     		   (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],   									LLSD((std::string)CERT_EKU_SERVER_AUTH))))  		{ -			BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert));			 +			LLTHROW(LLCertKeyUsageValidationException(cert));  		}  	}  	if (validation_policy & VALIDATION_POLICY_CA_KU) @@ -931,7 +932,7 @@ void _validateCert(int validation_policy,  			(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],   									   (std::string)CERT_KU_CERT_SIGN)))  			{ -				BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert));						 +				LLTHROW(LLCertKeyUsageValidationException(cert));  			}  	} @@ -943,13 +944,13 @@ void _validateCert(int validation_policy,  		if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||  		   !current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])  		{ -				BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert)); +				LLTHROW(LLCertBasicConstraintsValidationException(cert));  		}  		if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&  			((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&  			 (depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))  		{ -			BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert));					 +			LLTHROW(LLCertBasicConstraintsValidationException(cert));  		}  	}  } @@ -1019,7 +1020,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  	if(cert_chain->size() < 1)  	{ -		BOOST_THROW_EXCEPTION(LLCertException(NULL, "No certs in chain")); +		LLTHROW(LLCertException(NULL, "No certs in chain"));  	}  	iterator current_cert = cert_chain->begin();  	LLSD 	current_cert_info; @@ -1034,11 +1035,11 @@ void LLBasicCertificateStore::validate(int validation_policy,  		(*current_cert)->getLLSD(current_cert_info);  		if(!validation_params.has(CERT_HOSTNAME))  		{ -			BOOST_THROW_EXCEPTION(LLCertException((*current_cert), "No hostname passed in for validation"));			 +			LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation"));  		}  		if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))  		{ -			BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert)));				 +			LLTHROW(LLInvalidCertificate((*current_cert)));  		}  		LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() <<  @@ -1055,7 +1056,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  	X509* cert_x509 = (*current_cert)->getOpenSSLX509();  	if(!cert_x509)  	{ -		BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert)));			 +		LLTHROW(LLInvalidCertificate((*current_cert)));  	}  	std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);  	X509_free( cert_x509 ); @@ -1076,7 +1077,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  			if((validation_date < cache_entry->second.first) ||  			   (validation_date > cache_entry->second.second))  			{ -				BOOST_THROW_EXCEPTION(LLCertValidationExpirationException((*current_cert), validation_date)); +				LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date));  			}  		}  		// successfully found in cache @@ -1108,7 +1109,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  			if(!_verify_signature((*current_cert),  								  previous_cert))  			{ -			   BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(previous_cert)); +			   LLTHROW(LLCertValidationInvalidSignatureException(previous_cert));  			}  		}  		_validateCert(local_validation_policy, @@ -1157,7 +1158,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  			if(!_verify_signature((*found_store_cert),  								  (*current_cert)))  			{ -				BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(*current_cert)); +				LLTHROW(LLCertValidationInvalidSignatureException(*current_cert));  			}			  			// successfully validated.  			mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);		 @@ -1174,7 +1175,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  	if (validation_policy & VALIDATION_POLICY_TRUSTED)  	{  		// we reached the end without finding a trusted cert. -		BOOST_THROW_EXCEPTION(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1])); +		LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]));  	}  	mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);	 @@ -1262,7 +1263,7 @@ void LLSecAPIBasicHandler::_readProtectedData()  		protected_data_stream.read((char *)salt, STORE_SALT_SIZE);  		if (protected_data_stream.gcount() < STORE_SALT_SIZE)  		{ -			BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file too short.")); +			LLTHROW(LLProtectedDataException("Config file too short."));  		}  		cipher.decrypt(salt, STORE_SALT_SIZE);		 @@ -1302,7 +1303,7 @@ void LLSecAPIBasicHandler::_readProtectedData()  		if (parser->parse(parse_stream, mProtectedDataMap,   						  LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)  		{ -			BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file cannot be decrypted.")); +			LLTHROW(LLProtectedDataException("Config file cannot be decrypted."));  		}  	}  } @@ -1365,7 +1366,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()  	}  	catch (...)  	{ -		LL_WARNS() << "LLProtectedDataException(Error writing Protected Data Store)" << LL_ENDL; +		LOG_UNHANDLED_EXCEPTION("LLProtectedDataException(Error writing Protected Data Store)");  		// it's good practice to clean up any secure information on error  		// (even though this file isn't really secure.  Perhaps in the future  		// it may be, however. @@ -1373,39 +1374,39 @@ void LLSecAPIBasicHandler::_writeProtectedData()  		// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()  		// Decided throwing an exception here was overkill until we figure out why this happens -		//BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store")); +		//LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));  	} -    try -    { -        // move the temporary file to the specified file location. -        if(((   (LLFile::isfile(mProtectedDataFilename) != 0) -             && (LLFile::remove(mProtectedDataFilename) != 0))) -           || (LLFile::rename(tmp_filename, mProtectedDataFilename))) -        { -            LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL; -            LLFile::remove(tmp_filename); +	try +	{ +		// move the temporary file to the specified file location. +		if(((	(LLFile::isfile(mProtectedDataFilename) != 0) +			 && (LLFile::remove(mProtectedDataFilename) != 0))) +		   || (LLFile::rename(tmp_filename, mProtectedDataFilename))) +		{ +			LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL; +			LLFile::remove(tmp_filename); -            // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() -            // Decided throwing an exception here was overkill until we figure out why this happens -            //BOOST_THROW_EXCEPTION(LLProtectedDataException("Could not overwrite protected data store")); -        } +			// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() +			// Decided throwing an exception here was overkill until we figure out why this happens +			//LLTHROW(LLProtectedDataException("Could not overwrite protected data store")); +		}  	}  	catch (...)  	{ -		LL_WARNS() << "LLProtectedDataException(Error renaming '" << tmp_filename -                   << "' to '" << mProtectedDataFilename << "')" << LL_ENDL; +		LOG_UNHANDLED_EXCEPTION(STRINGIZE("renaming '" << tmp_filename << "' to '" +										  << mProtectedDataFilename << "'"));  		// it's good practice to clean up any secure information on error  		// (even though this file isn't really secure.  Perhaps in the future -		// it may be, however. +		// it may be, however).  		LLFile::remove(tmp_filename);  		//crash in LLSecAPIBasicHandler::_writeProtectedData()  		// Decided throwing an exception here was overkill until we figure out why this happens -		//BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store")); +		//LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));  	}  } -		 +  // instantiate a certificate from a pem string  LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert)  { diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 2d06b8599c..d28a7cc048 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -230,8 +230,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3  	const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f);  	F32 vec[3] = { -					fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f), -					fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f), +                    (F32)fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f), +                    (F32)fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),  					0.f  				};  	F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f5b06fbd19..697199df6b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7906,7 +7906,7 @@ void handle_web_browser_test(const LLSD& param)  void handle_web_content_test(const LLSD& param)  {  	std::string url = param.asString(); -	LLWeb::loadURLInternal(url); +	LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true);  }  void handle_show_url(const LLSD& param) diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index b37e41fb85..8026dc3ea8 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -104,10 +104,10 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std  // static  // Explicitly open a Web URL using the Web content floater -void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid) +void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode)  {  	LLFloaterWebContent::Params p; -	p.url(url).target(target).id(uuid); +	p.url(url).target(target).id(uuid).dev_mode(dev_mode);  	LLFloaterReg::showInstance("web_content", p);  } diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 7c90badbfe..7149ce9baf 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -57,7 +57,7 @@ public:  	static void loadURL(const std::string& url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null);  	// load content using built-in browser -	static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null); +	static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null, bool dev_mode = false);  	/// Returns escaped url (eg, " " to "%20") - used by all loadURL methods  	static std::string escapeURL(const std::string& url); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 11d3706821..cee47a591e 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -957,10 +957,10 @@ void LLWorld::updateWaterObjects()  	center_y = min_y + (wy >> 1);  	S32 add_boundary[4] = { -		512 - (max_x - region_x), -		512 - (max_y - region_y), -		512 - (region_x - min_x), -		512 - (region_y - min_y) }; +		(S32)(512 - (max_x - region_x)), +		(S32)(512 - (max_y - region_y)), +		(S32)(512 - (region_x - min_x)), +		(S32)(512 - (region_y - min_y)) };  	S32 dir;  	for (dir = 0; dir < 8; dir++) diff --git a/indra/newview/skins/default/textures/icons/Video_URL_Off.png b/indra/newview/skins/default/textures/icons/Video_URL_Off.pngBinary files differ new file mode 100644 index 0000000000..40e5df7d81 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Video_URL_Off.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 72037a84b3..01e8c16937 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -676,7 +676,10 @@ with the same filename but different name    <texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" />    <texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" /> -	<texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120"  scale_type="scale_outer"/> + +  <texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" /> +   +  <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120"  scale_type="scale_outer"/>      <texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"             scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" /> diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index a80440e844..4473ce0cda 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -154,6 +154,136 @@        </button>      </layout_panel>      <layout_panel +     height="22" +     layout="topleft" +     left_delta="0" +     name="debug_controls" +     top_delta="0" +     auto_resize="false" +     width="585"> +      <button +        image_overlay="Home_Off" +            image_disabled="PushButton_Disabled" +            image_disabled_selected="PushButton_Disabled" +            image_selected="PushButton_Selected" +            image_unselected="PushButton_Off" +        chrome="true" +        tool_tip="Web tests home page" +        enabled="true" +        follows="left|top" +        height="22" +        layout="topleft" +        left="1" +        name="web_test_home_page" +        top="0" +        width="22"> +        <button.commit_callback +          function="WebContent.TestURL" +          parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/> +      </button> + +      <button +        image_overlay="Video_URL_Off" +            image_disabled="PushButton_Disabled" +            image_disabled_selected="PushButton_Disabled" +            image_selected="PushButton_Selected" +            image_unselected="PushButton_Off" +        chrome="true" +        tool_tip="MPEG4 Video Test" +        enabled="true" +        follows="left|top" +        height="22" +        layout="topleft" +        left="27" +        name="VLC Plugin Test" +        top="0" +        width="22"> +        <button.commit_callback +          function="WebContent.TestURL" +          parameter="https://callum-linden.s3.amazonaws.com/sample_media/ss.mp4"/> +      </button> +      <button +        image_overlay="Video_URL_Off" +            image_disabled="PushButton_Disabled" +            image_disabled_selected="PushButton_Disabled" +            image_selected="PushButton_Selected" +            image_unselected="PushButton_Off" +        chrome="true" +        tool_tip="MKV Video Test" +        enabled="true" +        follows="left|top" +        height="22" +        layout="topleft" +        left="51" +        name="VLC Plugin Test" +        top="0" +        width="22"> +        <button.commit_callback +          function="WebContent.TestURL" +          parameter="https://callum-linden.s3.amazonaws.com/sample_media/jellyfish.mkv"/> +      </button> +      <button +        image_overlay="Video_URL_Off" +            image_disabled="PushButton_Disabled" +            image_disabled_selected="PushButton_Disabled" +            image_selected="PushButton_Selected" +            image_unselected="PushButton_Off" +        chrome="true" +        tool_tip="WebM Video Test" +        enabled="true" +        follows="left|top" +        height="22" +        layout="topleft" +        left="75" +        name="VLC Plugin Test" +        top="0" +        width="22"> +        <button.commit_callback +          function="WebContent.TestURL" +          parameter="https://callum-linden.s3.amazonaws.com/sample_media/jumprope.webm"/> +      </button> +      <button +        image_overlay="Video_URL_Off" +            image_disabled="PushButton_Disabled" +            image_disabled_selected="PushButton_Disabled" +            image_selected="PushButton_Selected" +            image_unselected="PushButton_Off" +        chrome="true" +        tool_tip="MP3 audio Test" +        enabled="true" +        follows="left|top" +        height="22" +        layout="topleft" +        left="99" +        name="VLC Plugin Test" +        top="0" +        width="22"> +        <button.commit_callback +          function="WebContent.TestURL" +          parameter="https://callum-linden.s3.amazonaws.com/alegria.mp3"/> +      </button> +      <button +        image_overlay="Video_URL_Off" +            image_disabled="PushButton_Disabled" +            image_disabled_selected="PushButton_Disabled" +            image_selected="PushButton_Selected" +            image_unselected="PushButton_Off" +        chrome="true" +        tool_tip="FLV Test" +        enabled="true" +        follows="left|top" +        height="22" +        layout="topleft" +        left="123" +        name="VLC Plugin Test" +        top="0" +        width="22"> +        <button.commit_callback +          function="WebContent.TestURL" +          parameter="https://callum-linden.s3.amazonaws.com/sample_media/vandal.flv"/> +      </button> +    </layout_panel> +    <layout_panel        height="40"        layout="topleft"        left_delta="0" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index dcf2da52f1..a39ee5fddd 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -225,11 +225,11 @@               parameter="message_critical" />          </menu_item_call>        <menu_item_call -       label="Web Content Floater Debug Test" -       name="Web Content Floater Debug Test"> +       label="Media Browser" +       name="Media Browser">          <menu_item_call.on_click           function="Advanced.WebContentTest" -         parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/> +         parameter="http://google.com"/>        </menu_item_call>        <menu         create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b189d1038f..8a649a57d1 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3141,30 +3141,13 @@           label="UI"           name="UI"           tear_off="true"> -         <!--   <menu_item_check -             label="New Bottom Bar" -             name="New Bottom Bar"> -                <menu_item_check.on_check -                 function="CheckControl" -                 parameter="BottomPanelNew" /> -                <menu_item_check.on_click -                 function="ToggleControl" -                 parameter="BottomPanelNew" /> -            </menu_item_check>--> -            <menu_item_call -             label="Media Browser Test" -             name="Web Browser Test"> -                <menu_item_call.on_click -                 function="Advanced.WebBrowserTest" -                 parameter="http://secondlife.com/app/search/slurls.html"/> -            </menu_item_call>            <menu_item_call -           label="Web Content Browser" -           name="Web Content Browser" -           shortcut="control|shift|Z"> +           label="Media Browser" +           name="Media Browser" +           shortcut="control|alt|shift|Z">              <menu_item_call.on_click               function="Advanced.WebContentTest" -             parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/> +             parameter="http://google.com"/>            </menu_item_call>            <menu_item_call             label="FB Connect Test" diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml index 7cb4a6e53b..c27fac6731 100644 --- a/indra/newview/skins/default/xui/en/mime_types.xml +++ b/indra/newview/skins/default/xui/en/mime_types.xml @@ -130,10 +130,21 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_cef  		</impl>  	</scheme> -	<mimetype name="blank"> +  <scheme name="libvlc"> +    <label name="libvlc_label"> +      LibVLC supported media +    </label> +    <widgettype> +      movie +    </widgettype> +    <impl> +      media_plugin_libvlc +    </impl> +  </scheme> +  <mimetype name="blank">  		<label name="blank_label">  			- None -  		</label> @@ -163,7 +174,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/*"> @@ -174,7 +185,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="image/*"> @@ -196,7 +207,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="application/javascript"> @@ -218,7 +229,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_cef  		</impl>  	</mimetype>  	<mimetype name="application/pdf"> @@ -295,7 +306,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_cef  		</impl>  	</mimetype>  	<mimetype name="audio/mpeg"> @@ -306,7 +317,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="audio/x-aiff"> @@ -317,7 +328,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="audio/x-wav"> @@ -328,7 +339,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype menu="1" name="image/bmp"> @@ -438,7 +449,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/mp4"> @@ -449,10 +460,21 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype> -	<mimetype menu="1" name="video/quicktime"> +  <mimetype name="application/octet-stream"> +    <label name="video/octet-stream"> +      Movie +    </label> +    <widgettype> +      movie +    </widgettype> +    <impl> +      media_plugin_libvlc +    </impl> +  </mimetype> +  <mimetype menu="1" name="video/quicktime">  		<label name="video/quicktime_label">  			Movie (QuickTime)  		</label> @@ -460,7 +482,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/x-ms-asf"> @@ -471,7 +493,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/x-ms-wmv"> @@ -482,7 +504,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_cef  		</impl>  	</mimetype>  	<mimetype menu="1" name="video/x-msvideo"> @@ -493,7 +515,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_cef  		</impl>  	</mimetype>  </mimetypes> diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml index 84aeaf3b54..7188b1e699 100644 --- a/indra/newview/skins/default/xui/en/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml @@ -130,7 +130,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</scheme>  	<mimetype name="blank"> @@ -163,7 +163,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/*"> @@ -174,7 +174,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="image/*"> @@ -196,7 +196,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="application/javascript"> @@ -218,7 +218,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="application/pdf"> @@ -295,7 +295,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="audio/mpeg"> @@ -306,7 +306,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="audio/x-aiff"> @@ -317,7 +317,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="audio/x-wav"> @@ -328,7 +328,7 @@  			audio  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype menu="1" name="image/bmp"> @@ -438,7 +438,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/mp4"> @@ -449,7 +449,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype menu="1" name="video/quicktime"> @@ -460,7 +460,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/x-ms-asf"> @@ -471,7 +471,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype name="video/x-ms-wmv"> @@ -482,7 +482,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  	<mimetype menu="1" name="video/x-msvideo"> @@ -493,7 +493,7 @@  			movie  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_libvlc  		</impl>  	</mimetype>  </mimetypes> diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index eb67d07601..068e4420bc 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -374,9 +374,11 @@  		  layout="topleft"  		  tool_tip="Movie play progress"  		  width="200"> -		<slider_bar.commit_callback -			function="MediaCtrl.JumpProgress" /> -	  </slider_bar> +      <slider_bar.mouse_down_callback +        function="MediaCtrl.MouseDown" /> +      <slider_bar.mouse_up_callback +        function="MediaCtrl.MouseUp" /> +    </slider_bar>  	</layout_panel>  	<layout_panel  		name="skip_back" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b19c6756bc..0a17c202c3 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -51,13 +51,14 @@ OpenGL Version: [OPENGL_VERSION]  J2C Decoder Version: [J2C_VERSION]  Audio Driver Version: [AUDIO_DRIVER_VERSION]  LLCEFLib/CEF Version: [LLCEFLIB_VERSION] +LibVLC Version: [LIBVLC_VERSION]  Voice Server Version: [VOICE_VERSION]  	</string>  	<string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string>  	<string name="AboutTime">[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second,datetime,slt]</string>  	<string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string>  	<string name="BuildConfiguration">Build Configuration</string> - +	  	<!--  progress -->  	<string name="ProgressRestoring">Restoring...</string>  	<string name="ProgressChangingResolution">Changing resolution...</string> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index f3d89bb866..66d730d1ac 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -444,6 +444,11 @@ class Windows_i686_Manifest(ViewerManifest):              self.path("media_plugin_cef.dll")              self.end_prefix() +        # Media plugins - LibVLC +        if self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"): +            self.path("media_plugin_libvlc.dll") +            self.end_prefix() +          # winmm.dll shim          if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):              self.path("winmm.dll") @@ -550,6 +555,12 @@ class Windows_i686_Manifest(ViewerManifest):              self.path("zh-TW.pak")              self.end_prefix() +            if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"): +                self.path("libvlc.dll") +                self.path("libvlccore.dll") +                self.path("plugins/") +                self.end_prefix() +          # pull in the crash logger and updater from other projects          # tag:"crash-logger" here as a cue to the exporter          self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], @@ -1089,8 +1100,18 @@ class LinuxManifest(ViewerManifest):          # plugins          if self.prefix(src="", dst="bin/llplugin"):              self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") +            self.path("../media_plugins/libvlc/libmedia_plugin_libvlc.so", "libmedia_plugin_libvlc.so")              self.end_prefix("bin/llplugin") +        if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): +            self.path( "plugins.dat" ) +            self.path( "*/*.so" ) +            self.end_prefix() + +        if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib' ), dst="lib"): +            self.path( "libvlc*.so*" ) +            self.end_prefix() +          # llcommon          if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"):              print "Skipping llcommon.so (assuming llcommon was linked statically)" @@ -1144,7 +1165,7 @@ class LinuxManifest(ViewerManifest):      def strip_binaries(self):          if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():              print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" -            self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure +            self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install \! -name *.dat | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure  class Linux_i686_Manifest(LinuxManifest):      def construct(self): diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index 53d4acc9e0..c767d52c7b 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -42,6 +42,8 @@  #include "llevents.h"  #include "lleventfilter.h"  #include "lleventcoro.h" +#include "llexception.h" +#include "stringize.h"  //*********************  // LLLogin @@ -128,30 +130,23 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)  void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)  { -	try -	{ -	LLSD printable_params = login_params; -	//if(printable_params.has("params")  -	//	&& printable_params["params"].has("passwd"))  -	//{ -	//	printable_params["params"]["passwd"] = "*******"; -	//} -	LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName() +    LLSD printable_params = login_params; +    if (printable_params.has("params")  +        && printable_params["params"].has("passwd"))  +    { +        printable_params["params"]["passwd"] = "*******"; +    } +    try +    { +    LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()                          << " with uri '" << uri << "', parameters " << printable_params << LL_ENDL; -	// Arriving in SRVRequest state -    LLEventStream replyPump("SRVreply", true); -    // Should be an array of one or more uri strings. -      LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));      // EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used      // to share them -- but the EXT-3934 fix made it possible for an abandoned      // SRV response to arrive just as we were expecting the XMLRPC response.      LLEventStream loginReplyPump("loginreply", true); -    // Loop through the rewrittenURIs, counting attempts along the way. -    // Because of possible redirect responses, we may make more than one -    // attempt per rewrittenURIs entry.      LLSD::Integer attempts = 0;      LLSD request(login_params); @@ -167,11 +162,11 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)          LLSD progress_data;          progress_data["attempt"] = attempts;          progress_data["request"] = request; -		if(progress_data["request"].has("params") -			&& progress_data["request"]["params"].has("passwd")) -		{ -			progress_data["request"]["params"]["passwd"] = "*******"; -		} +        if (progress_data["request"].has("params") +            && progress_data["request"]["params"].has("passwd")) +        { +            progress_data["request"]["params"]["passwd"] = "*******"; +        }          sendProgressEvent("offline", "authenticating", progress_data);          // We expect zero or more "Downloading" status events, followed by @@ -189,8 +184,8 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)              // Still Downloading -- send progress update.              sendProgressEvent("offline", "downloading");          } -	 -		LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL; + +        LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;          status = mAuthResponse["status"].asString();          // Okay, we've received our final status event for this @@ -202,7 +197,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)              break;          } -		sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]); +        sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);          // Here the login service at the current URI is redirecting us          // to some other URI ("indeterminate" -- why not "redirect"?). @@ -212,8 +207,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)          request["method"] = mAuthResponse["responses"]["next_method"].asString();      } // loop back to try the redirected URI -    // Here we're done with redirects for the current rewrittenURIs -    // entry. +    // Here we're done with redirects.      if (status == "Complete")      {          // StatusComplete does not imply auth success. Check the @@ -230,14 +224,14 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)          return;             // Done!      } -// 	/* Sometimes we end with "Started" here. Slightly slow server? -// 		* Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below. -// 		*/ -// 	if( status == "Started") -// 	{ -// 		LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL; -// 		continue; -// 	} +//  /* Sometimes we end with "Started" here. Slightly slow server? +//   * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below. +//   */ +//  if( status == "Started") +//  { +//      LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL; +//      continue; +//  }      // If we don't recognize status at all, trouble      if (! (status == "CURLError" @@ -250,27 +244,25 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)      }      // Here status IS one of the errors tested above. - -    // Here we got through all the rewrittenURIs without succeeding. Tell -    // caller this didn't work out so well. Of course, the only failure data -    // we can reasonably show are from the last of the rewrittenURIs. - -	// *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an -	// llsd with no "responses" node. To make the output from an incomplete login symmetrical  -	// to success, add a data/message and data/reason fields. -	LLSD error_response; -	error_response["reason"] = mAuthResponse["status"]; -	error_response["errorcode"] = mAuthResponse["errorcode"]; -	error_response["message"] = mAuthResponse["error"]; -	if(mAuthResponse.has("certificate")) -	{ -		error_response["certificate"] = mAuthResponse["certificate"]; -	} -	sendProgressEvent("offline", "fail.login", error_response); -	} -	catch (...) { -		LL_ERRS() << "login exception caught" << LL_ENDL;  -	} +    // Tell caller this didn't work out so well. + +    // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an +    // llsd with no "responses" node. To make the output from an incomplete login symmetrical  +    // to success, add a data/message and data/reason fields. +    LLSD error_response; +    error_response["reason"] = mAuthResponse["status"]; +    error_response["errorcode"] = mAuthResponse["errorcode"]; +    error_response["message"] = mAuthResponse["error"]; +    if(mAuthResponse.has("certificate")) +    { +        error_response["certificate"] = mAuthResponse["certificate"]; +    } +    sendProgressEvent("offline", "fail.login", error_response); +    } +    catch (...) { +        CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName() +                                               << "('" << uri << "', " << printable_params << ")")); +    }  }  void LLLogin::Impl::disconnect() diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index cd4b108c1a..04e0395c50 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -30,7 +30,6 @@  #include "llexception.h"  #include <boost/format.hpp>  #include <boost/lexical_cast.hpp> -#include <boost/throw_exception.hpp>  #include <curl/curl.h>  #include "lldir.h"  #include "llevents.h" @@ -468,7 +467,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u  	if(!mCurl)  	{ -		BOOST_THROW_EXCEPTION(DownloadError("failed to initialize curl")); +		LLTHROW(DownloadError("failed to initialize curl"));  	}      throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true));  	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true)); @@ -509,7 +508,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)  	mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());  	if(mHeaderList == 0)  	{ -		BOOST_THROW_EXCEPTION(DownloadError("cannot add Range header")); +		LLTHROW(DownloadError("cannot add Range header"));  	}  	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList)); @@ -525,7 +524,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std  	mDownloadData["hash"] = hash;  	mDownloadData["current_version"] = ll_get_version();  	LLSD path = uri.pathArray(); -	if(path.size() == 0) BOOST_THROW_EXCEPTION(DownloadError("no file path")); +	if(path.size() == 0) LLTHROW(DownloadError("no file path"));  	std::string fileName = path[path.size() - 1].asString();  	std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);  	mDownloadData["path"] = filePath; @@ -548,9 +547,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)  	if(code != CURLE_OK) {  		const char * errorString = curl_easy_strerror(code);  		if(errorString != 0) { -			BOOST_THROW_EXCEPTION(DownloadError(curl_easy_strerror(code))); +			LLTHROW(DownloadError(curl_easy_strerror(code)));  		} else { -			BOOST_THROW_EXCEPTION(DownloadError("unknown curl error")); +			LLTHROW(DownloadError("unknown curl error"));  		}  	} else {  		; // No op. diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index 9f9a08f590..1c7629da23 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -36,7 +36,6 @@  #pragma warning(disable: 4702)      // disable 'unreachable code' so we can use lexical_cast (really!).  #endif  #include <boost/lexical_cast.hpp> -#include <boost/throw_exception.hpp>  namespace {  	struct RelocateError: public LLException @@ -49,7 +48,7 @@ namespace {  		std::string scriptFile = gDirUtilp->getBaseFileName(path);  		std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);  		apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp); -		if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(RelocateError()); +		if(status != APR_SUCCESS) LLTHROW(RelocateError());  		return newPath;  	} diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 0bdd1ede43..1665e41e70 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -32,10 +32,10 @@  #include "lltimer.h"  #include "llupdatechecker.h"  #include "llupdateinstaller.h" +#include "llexception.h"  #include <boost/scoped_ptr.hpp>  #include <boost/weak_ptr.hpp> -#include <boost/throw_exception.hpp>  #include "lldir.h"  #include "llsdserialize.h"  #include "llfile.h" @@ -191,9 +191,8 @@ void LLUpdaterServiceImpl::initialize(const std::string&  channel,  {  	if(mIsChecking || mIsDownloading)  	{ -		BOOST_THROW_EXCEPTION( -			LLUpdaterService::UsageError("LLUpdaterService::initialize call " -										 "while updater is running.")); +		LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call " +											  "while updater is running."));  	}  	mChannel = channel; @@ -224,9 +223,8 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready)  {  	if(mChannel.empty() || mVersion.empty())  	{ -		BOOST_THROW_EXCEPTION( -			LLUpdaterService::UsageError("Set params before call to " -										 "LLUpdaterService::startCheck().")); +		LLTHROW(LLUpdaterService::UsageError("Set params before call to " +											 "LLUpdaterService::startCheck()."));  	}  	mIsChecking = true; | 
