| Index: ppapi/utility/completion_callback_factory.h
|
| diff --git a/ppapi/utility/completion_callback_factory.h b/ppapi/utility/completion_callback_factory.h
|
| index e7e7c863c9dbb1e0fd0f30199672dac8e2f3364d..d521f4b5d92bb38b45b78ce3684217d68f3cab07 100644
|
| --- a/ppapi/utility/completion_callback_factory.h
|
| +++ b/ppapi/utility/completion_callback_factory.h
|
| @@ -570,8 +570,12 @@ class CompletionCallbackFactory {
|
| static void Thunk(void* user_data, int32_t result) {
|
| Self* self = static_cast<Self*>(user_data);
|
| T* object = self->back_pointer_->GetObject();
|
| - if (object)
|
| - (*self->dispatcher_)(object, result);
|
| +
|
| + // Please note that |object| may be NULL at this point. But we still need
|
| + // to call into Dispatcher::operator() in that case, so that it can do
|
| + // necessary cleanup.
|
| + (*self->dispatcher_)(object, result);
|
| +
|
| delete self;
|
| }
|
|
|
| @@ -592,7 +596,8 @@ class CompletionCallbackFactory {
|
| explicit Dispatcher0(Method method) : method_(method) {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result);
|
| + if (object)
|
| + (object->*method_)(result);
|
| }
|
| private:
|
| Method method_;
|
| @@ -604,11 +609,21 @@ class CompletionCallbackFactory {
|
| typedef Output OutputType;
|
| typedef internal::CallbackOutputTraits<Output> Traits;
|
|
|
| - DispatcherWithOutput0() : method_(NULL) {}
|
| - DispatcherWithOutput0(Method method) : method_(method) {
|
| + DispatcherWithOutput0()
|
| + : method_(NULL),
|
| + output_() {
|
| + }
|
| + DispatcherWithOutput0(Method method)
|
| + : method_(method),
|
| + output_() {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, Traits::StorageToPluginArg(output_));
|
| + // We must call Traits::StorageToPluginArg() even if we don't need to call
|
| + // the callback anymore, otherwise we may leak resource or var references.
|
| + if (object)
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_));
|
| + else
|
| + Traits::StorageToPluginArg(output_);
|
| }
|
| typename Traits::StorageType* output() {
|
| return &output_;
|
| @@ -622,13 +637,17 @@ class CompletionCallbackFactory {
|
| template <typename Method, typename A>
|
| class Dispatcher1 {
|
| public:
|
| - Dispatcher1() : method_(NULL) {}
|
| + Dispatcher1()
|
| + : method_(NULL),
|
| + a_() {
|
| + }
|
| Dispatcher1(Method method, const A& a)
|
| : method_(method),
|
| a_(a) {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, a_);
|
| + if (object)
|
| + (object->*method_)(result, a_);
|
| }
|
| private:
|
| Method method_;
|
| @@ -641,13 +660,23 @@ class CompletionCallbackFactory {
|
| typedef Output OutputType;
|
| typedef internal::CallbackOutputTraits<Output> Traits;
|
|
|
| - DispatcherWithOutput1() : method_(NULL) {}
|
| + DispatcherWithOutput1()
|
| + : method_(NULL),
|
| + a_(),
|
| + output_() {
|
| + }
|
| DispatcherWithOutput1(Method method, const A& a)
|
| : method_(method),
|
| - a_(a) {
|
| + a_(a),
|
| + output_() {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
|
| + // We must call Traits::StorageToPluginArg() even if we don't need to call
|
| + // the callback anymore, otherwise we may leak resource or var references.
|
| + if (object)
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
|
| + else
|
| + Traits::StorageToPluginArg(output_);
|
| }
|
| typename Traits::StorageType* output() {
|
| return &output_;
|
| @@ -662,14 +691,19 @@ class CompletionCallbackFactory {
|
| template <typename Method, typename A, typename B>
|
| class Dispatcher2 {
|
| public:
|
| - Dispatcher2() : method_(NULL) {}
|
| + Dispatcher2()
|
| + : method_(NULL),
|
| + a_(),
|
| + b_() {
|
| + }
|
| Dispatcher2(Method method, const A& a, const B& b)
|
| : method_(method),
|
| a_(a),
|
| b_(b) {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, a_, b_);
|
| + if (object)
|
| + (object->*method_)(result, a_, b_);
|
| }
|
| private:
|
| Method method_;
|
| @@ -683,14 +717,25 @@ class CompletionCallbackFactory {
|
| typedef Output OutputType;
|
| typedef internal::CallbackOutputTraits<Output> Traits;
|
|
|
| - DispatcherWithOutput2() : method_(NULL) {}
|
| + DispatcherWithOutput2()
|
| + : method_(NULL),
|
| + a_(),
|
| + b_(),
|
| + output_() {
|
| + }
|
| DispatcherWithOutput2(Method method, const A& a, const B& b)
|
| : method_(method),
|
| a_(a),
|
| - b_(b) {
|
| + b_(b),
|
| + output_() {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
|
| + // We must call Traits::StorageToPluginArg() even if we don't need to call
|
| + // the callback anymore, otherwise we may leak resource or var references.
|
| + if (object)
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
|
| + else
|
| + Traits::StorageToPluginArg(output_);
|
| }
|
| typename Traits::StorageType* output() {
|
| return &output_;
|
| @@ -706,7 +751,12 @@ class CompletionCallbackFactory {
|
| template <typename Method, typename A, typename B, typename C>
|
| class Dispatcher3 {
|
| public:
|
| - Dispatcher3() : method_(NULL) {}
|
| + Dispatcher3()
|
| + : method_(NULL),
|
| + a_(),
|
| + b_(),
|
| + c_() {
|
| + }
|
| Dispatcher3(Method method, const A& a, const B& b, const C& c)
|
| : method_(method),
|
| a_(a),
|
| @@ -714,7 +764,8 @@ class CompletionCallbackFactory {
|
| c_(c) {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, a_, b_, c_);
|
| + if (object)
|
| + (object->*method_)(result, a_, b_, c_);
|
| }
|
| private:
|
| Method method_;
|
| @@ -730,16 +781,29 @@ class CompletionCallbackFactory {
|
| typedef Output OutputType;
|
| typedef internal::CallbackOutputTraits<Output> Traits;
|
|
|
| - DispatcherWithOutput3() : method_(NULL) {}
|
| + DispatcherWithOutput3()
|
| + : method_(NULL),
|
| + a_(),
|
| + b_(),
|
| + c_(),
|
| + output_() {
|
| + }
|
| DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c)
|
| : method_(method),
|
| a_(a),
|
| b_(b),
|
| - c_(c) {
|
| + c_(c),
|
| + output_() {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, Traits::StorageToPluginArg(output_),
|
| - a_, b_, c_);
|
| + // We must call Traits::StorageToPluginArg() even if we don't need to call
|
| + // the callback anymore, otherwise we may leak resource or var references.
|
| + if (object) {
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_),
|
| + a_, b_, c_);
|
| + } else {
|
| + Traits::StorageToPluginArg(output_);
|
| + }
|
| }
|
| typename Traits::StorageType* output() {
|
| return &output_;
|
|
|