Commit 0dc92cb3 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

npapi: Don't wrap callback arguments into Variant's out of the plugin thread

This completes previous #16292 fix
parent cd72c202
......@@ -24,13 +24,14 @@
#ifndef UTILS_NPP
#define UTILS_NPP
#include <npruntime.h>
#include <array>
#include <cassert>
#include <cstring>
#include <memory>
#include <type_traits>
#include <npruntime.h>
#include <string>
#include <cstring>
#include <cassert>
#include <tuple>
#include <type_traits>
using CStr = std::unique_ptr<char, void(*)(void*)>;
......@@ -614,107 +615,40 @@ private:
using Variant = details::Variant<details::policy::Embeded>;
using OutVariant = details::Variant<details::policy::Wrapped>;
class VariantArray
namespace details
{
using VPtr = std::unique_ptr<Variant[]>;
public:
VariantArray()
: m_variants( nullptr )
, m_size( 0 )
{
}
VariantArray(unsigned int nbValue)
: m_variants( VPtr( new Variant[nbValue] ) )
, m_size( nbValue )
{
}
Variant& operator[](size_t idx)
{
return m_variants[idx];
}
const Variant& operator[](size_t idx) const
{
return m_variants[idx];
}
// Warning: this assumes the same binary layout between Variant & NPVariant
operator NPVariant*()
{
return (NPVariant*)m_variants.get();
}
operator const NPVariant*() const
{
return (const NPVariant*)m_variants.get();
}
size_t size() const
template <size_t... Ns>
struct Seq
{
return m_size;
}
VariantArray(const VariantArray&) = delete;
VariantArray& operator=(const VariantArray&) = delete;
#ifndef _MSC_VER
VariantArray(VariantArray&&) = default;
VariantArray& operator=(VariantArray&&) = default;
#else
VariantArray(VariantArray&& v)
: m_variants(std::move( v.m_variants ) )
, m_size( v.m_size )
{
}
using type = Seq<Ns..., sizeof...(Ns)>;
};
VariantArray& operator=(VariantArray&& v)
template <size_t N>
struct GenSeq
{
if (&v == this)
return *this;
m_variants = std::move(v.m_variants);
m_size = v.m_size;
return *this;
}
#endif
private:
VPtr m_variants;
size_t m_size;
};
// This will recurse down to Seq<> which yields type = Seq<0>
// Then, from Seq<0>::type, up to Seq<N-1>::type, which ends
// up generating Seq<0, 1, ... N>
using type = typename GenSeq<N - 1>::type::type;
};
// Private implementation namespace
namespace details
{
template <size_t Idx, typename T>
void wrap( VariantArray& array, T arg )
template <>
struct GenSeq<0>
{
array[Idx] = Variant<details::policy::Embeded>(arg);
}
using type = Seq<>;
};
template <size_t Idx, typename T, typename... Args>
void wrap( VariantArray& array, T arg, Args&&... args )
template <typename Tuple, size_t... Indices>
std::array<npapi::Variant, sizeof...(Indices)> wrap( const Tuple& t, Seq<Indices...> )
{
wrap<Idx + 1>( array, std::forward<Args>( args )... );
// This needs the Variant wrapper to be the exact size of a NPVariant
// For future proofness, we make this explicit:
array[Idx] = Variant<details::policy::Embeded>(arg);
return { npapi::Variant( std::get<Indices>( t ) )... };
}
}
// public entry point. Responsible for allocating the array and initializing
// the template index parameter (to avoid filling to array in reverse order with
// sizeof...()
template <typename... Args>
VariantArray wrap(Args&&... args)
{
auto array = VariantArray{sizeof...(args)};
details::wrap<0>( array, std::forward<Args>( args )... );
return array;
}
inline VariantArray wrap()
std::array<Variant, sizeof...(Args)> wrap( const std::tuple<Args...>& args )
{
return VariantArray{};
return details::wrap( args, typename details::GenSeq<sizeof...(Args)>::type{} );
}
}
......
......@@ -277,28 +277,34 @@ bool VlcPluginBase::handle_event(void *)
return false;
}
template <typename... Args>
struct AsyncEventWrapper
{
AsyncEventWrapper(NPP b, NPObject* l, npapi::VariantArray&& a)
template <typename... PFArgs>
AsyncEventWrapper(NPP b, NPObject* l, PFArgs&&... args)
: browser( b )
, listener( l )
, args( std::move( a ) )
, args( std::make_tuple( std::forward<Args>( args )... ) )
{
}
NPP browser;
NPObject* listener;
npapi::VariantArray args;
// If we do not decay Args here, we will end up declaring a tuple holding references
// The tuple returned by make_tuple does that, but we end up converting from the correct tuple
// type to an invalid tuple type, since we would end up using dangling references.
std::tuple<typename std::decay<Args>::type...> args;
};
template <typename... Args>
static void invokeEvent( NPP browser, NPObject* listener, Args&&... args )
{
auto wrapper = new AsyncEventWrapper( browser, listener, npapi::wrap( std::forward<Args>( args )... ) );
auto wrapper = new AsyncEventWrapper<Args...>( browser, listener, std::forward<Args>( args )... );
NPN_PluginThreadAsyncCall( browser, [](void* data) {
auto w = reinterpret_cast<AsyncEventWrapper*>( data );
auto w = reinterpret_cast<AsyncEventWrapper<Args...>*>( data );
auto args = npapi::wrap( w->args );
NPVariant result;
if (NPN_InvokeDefault( w->browser, w->listener, w->args, w->args.size(), &result ))
if (NPN_InvokeDefault( w->browser, w->listener, reinterpret_cast<NPVariant*>( args.data() ), args.size(), &result ))
{
// "result" content is unspecified when invoke fails. Don't clean potential garbage
NPN_ReleaseVariantValue( &result );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment