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..42ebbf35033fe00e5e11be8a6378e93f4c962a27 100644 |
--- a/ppapi/utility/completion_callback_factory.h |
+++ b/ppapi/utility/completion_callback_factory.h |
@@ -570,8 +570,7 @@ 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); |
+ (*self->dispatcher_)(object, result); |
delete self; |
} |
@@ -592,7 +591,8 @@ class CompletionCallbackFactory { |
explicit Dispatcher0(Method method) : method_(method) { |
} |
void operator()(T* object, int32_t result) { |
- (object->*method_)(result); |
+ if (object) |
brettw
2012/04/03 21:23:03
I don't totally get this change, can you clarify w
yzshen1
2012/04/04 00:36:34
Because I change Thunk() to call Dispatcher*::oper
|
+ (object->*method_)(result); |
} |
private: |
Method method_; |
@@ -604,11 +604,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 +632,17 @@ class CompletionCallbackFactory { |
template <typename Method, typename A> |
class Dispatcher1 { |
public: |
- Dispatcher1() : method_(NULL) {} |
+ Dispatcher1() |
+ : method_(NULL), |
+ a_() { |
brettw
2012/04/03 21:23:03
Do you initialize these arguments just for complet
yzshen1
2012/04/04 00:36:34
Yes. I understand that.
If we want to init |metho
|
+ } |
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 +655,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 +686,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 +712,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 +746,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 +759,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 +776,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_; |