Index: chromeos/dbus/shill_client_helper.cc |
diff --git a/chromeos/dbus/shill_client_helper.cc b/chromeos/dbus/shill_client_helper.cc |
index 87b526cc40906d0d2dad7fbd22881dea0cf1ba26..1108e11dd41c3c274d3a69e857fdfe92e6e8fdcd 100644 |
--- a/chromeos/dbus/shill_client_helper.cc |
+++ b/chromeos/dbus/shill_client_helper.cc |
@@ -18,10 +18,25 @@ namespace { |
const char kInvalidResponseErrorName[] = ""; // No error name. |
const char kInvalidResponseErrorMessage[] = "Invalid response."; |
+class HelperRelease { |
hashimoto
2013/09/17 03:28:53
nit: "Helper" here sounds ambiguous, does it mean
stevenjb
2013/09/17 21:03:17
-> ShillClientHelperAutoRelease
|
+ public: |
+ HelperRelease(base::WeakPtr<ShillClientHelper> helper) |
+ : helper_(helper) { |
+ } |
+ ~HelperRelease() { |
+ if (helper_) |
+ helper_->Release(); |
+ } |
+ private: |
+ base::WeakPtr<ShillClientHelper> helper_; |
+}; |
+ |
void OnBooleanMethodWithErrorCallback( |
+ base::WeakPtr<ShillClientHelper> helper, |
const ShillClientHelper::BooleanCallback& callback, |
const ShillClientHelper::ErrorCallback& error_callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
hashimoto
2013/09/17 03:28:53
I'm a bit worried about manually adding HelperRele
stevenjb
2013/09/17 21:03:17
I initially considered that approach but decided a
|
if (!response) { |
error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
return; |
@@ -32,13 +47,14 @@ void OnBooleanMethodWithErrorCallback( |
error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
return; |
} |
- callback.Run(result); |
} |
void OnStringMethodWithErrorCallback( |
+ base::WeakPtr<ShillClientHelper> helper, |
const ShillClientHelper::StringCallback& callback, |
const ShillClientHelper::ErrorCallback& error_callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
if (!response) { |
error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
return; |
@@ -53,8 +69,10 @@ void OnStringMethodWithErrorCallback( |
} |
// Handles responses for methods without results. |
-void OnVoidMethod(const VoidDBusMethodCallback& callback, |
+void OnVoidMethod(base::WeakPtr<ShillClientHelper> helper, |
+ const VoidDBusMethodCallback& callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
if (!response) { |
callback.Run(DBUS_METHOD_CALL_FAILURE); |
return; |
@@ -64,8 +82,10 @@ void OnVoidMethod(const VoidDBusMethodCallback& callback, |
// Handles responses for methods with ObjectPath results. |
void OnObjectPathMethod( |
+ base::WeakPtr<ShillClientHelper> helper, |
const ObjectPathDBusMethodCallback& callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
if (!response) { |
callback.Run(DBUS_METHOD_CALL_FAILURE, dbus::ObjectPath()); |
return; |
@@ -81,9 +101,11 @@ void OnObjectPathMethod( |
// Handles responses for methods with ObjectPath results and no status. |
void OnObjectPathMethodWithoutStatus( |
+ base::WeakPtr<ShillClientHelper> helper, |
const ObjectPathCallback& callback, |
const ShillClientHelper::ErrorCallback& error_callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
if (!response) { |
error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
return; |
@@ -99,8 +121,10 @@ void OnObjectPathMethodWithoutStatus( |
// Handles responses for methods with DictionaryValue results. |
void OnDictionaryValueMethod( |
+ base::WeakPtr<ShillClientHelper> helper, |
const ShillClientHelper::DictionaryValueCallback& callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
if (!response) { |
base::DictionaryValue result; |
callback.Run(DBUS_METHOD_CALL_FAILURE, result); |
@@ -119,17 +143,21 @@ void OnDictionaryValueMethod( |
// Handles responses for methods without results. |
void OnVoidMethodWithErrorCallback( |
+ base::WeakPtr<ShillClientHelper> helper, |
const base::Closure& callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
callback.Run(); |
} |
// Handles responses for methods with DictionaryValue results. |
// Used by CallDictionaryValueMethodWithErrorCallback(). |
void OnDictionaryValueMethodWithErrorCallback( |
+ base::WeakPtr<ShillClientHelper> helper, |
const ShillClientHelper::DictionaryValueCallbackWithoutStatus& callback, |
const ShillClientHelper::ErrorCallback& error_callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
dbus::MessageReader reader(response); |
scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); |
base::DictionaryValue* result = NULL; |
@@ -142,9 +170,11 @@ void OnDictionaryValueMethodWithErrorCallback( |
// Handles responses for methods with ListValue results. |
void OnListValueMethodWithErrorCallback( |
+ base::WeakPtr<ShillClientHelper> helper, |
const ShillClientHelper::ListValueCallback& callback, |
const ShillClientHelper::ErrorCallback& error_callback, |
dbus::Response* response) { |
+ HelperRelease release(helper); |
dbus::MessageReader reader(response); |
scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); |
base::ListValue* result = NULL; |
@@ -156,8 +186,10 @@ void OnListValueMethodWithErrorCallback( |
} |
// Handles running appropriate error callbacks. |
-void OnError(const ShillClientHelper::ErrorCallback& error_callback, |
+void OnError(base::WeakPtr<ShillClientHelper> helper, |
+ const ShillClientHelper::ErrorCallback& error_callback, |
dbus::ErrorResponse* response) { |
+ HelperRelease release(helper); |
std::string error_name; |
std::string error_message; |
if (response) { |
@@ -171,9 +203,10 @@ void OnError(const ShillClientHelper::ErrorCallback& error_callback, |
} // namespace |
-ShillClientHelper::ShillClientHelper(dbus::Bus* bus, |
- dbus::ObjectProxy* proxy) |
+ShillClientHelper::ShillClientHelper(dbus::ObjectProxy* proxy) |
: proxy_(proxy), |
+ owner_(NULL), |
+ active_refs_(0), |
weak_ptr_factory_(this) { |
} |
@@ -182,8 +215,24 @@ ShillClientHelper::~ShillClientHelper() { |
<< "ShillClientHelper destroyed with active observers"; |
} |
+void ShillClientHelper::SetOwner(Owner* owner) { |
+ CHECK(!owner_); |
+ owner_ = owner; |
+} |
+ |
+void ShillClientHelper::AddRef() { |
+ ++active_refs_; |
+} |
+ |
+void ShillClientHelper::Release() { |
+ --active_refs_; |
+ if (active_refs_ == 0 && owner_) |
+ owner_->NotifyReleased(this); // May delete this |
+} |
+ |
void ShillClientHelper::AddPropertyChangedObserver( |
ShillPropertyChangedObserver* observer) { |
+ AddRef(); |
// Excecute all the pending MonitorPropertyChanged calls. |
for (size_t i = 0; i < interfaces_to_be_monitored_.size(); ++i) { |
MonitorPropertyChangedInternal(interfaces_to_be_monitored_[i]); |
@@ -196,6 +245,7 @@ void ShillClientHelper::AddPropertyChangedObserver( |
void ShillClientHelper::RemovePropertyChangedObserver( |
ShillPropertyChangedObserver* observer) { |
observer_list_.RemoveObserver(observer); |
+ Release(); |
} |
void ShillClientHelper::MonitorPropertyChanged( |
@@ -225,8 +275,10 @@ void ShillClientHelper::CallVoidMethod( |
dbus::MethodCall* method_call, |
const VoidDBusMethodCallback& callback) { |
DCHECK(!callback.is_null()); |
+ AddRef(); |
proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind(&OnVoidMethod, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback)); |
} |
@@ -234,8 +286,10 @@ void ShillClientHelper::CallObjectPathMethod( |
dbus::MethodCall* method_call, |
const ObjectPathDBusMethodCallback& callback) { |
DCHECK(!callback.is_null()); |
+ AddRef(); |
proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind(&OnObjectPathMethod, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback)); |
} |
@@ -245,13 +299,16 @@ void ShillClientHelper::CallObjectPathMethodWithErrorCallback( |
const ErrorCallback& error_callback) { |
DCHECK(!callback.is_null()); |
DCHECK(!error_callback.is_null()); |
+ AddRef(); |
proxy_->CallMethodWithErrorCallback( |
method_call, |
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind(&OnObjectPathMethodWithoutStatus, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback, |
error_callback), |
base::Bind(&OnError, |
+ weak_ptr_factory_.GetWeakPtr(), |
error_callback)); |
} |
@@ -259,8 +316,10 @@ void ShillClientHelper::CallDictionaryValueMethod( |
dbus::MethodCall* method_call, |
const DictionaryValueCallback& callback) { |
DCHECK(!callback.is_null()); |
+ AddRef(); |
proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind(&OnDictionaryValueMethod, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback)); |
} |
@@ -270,11 +329,14 @@ void ShillClientHelper::CallVoidMethodWithErrorCallback( |
const ErrorCallback& error_callback) { |
DCHECK(!callback.is_null()); |
DCHECK(!error_callback.is_null()); |
+ AddRef(); |
proxy_->CallMethodWithErrorCallback( |
method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind(&OnVoidMethodWithErrorCallback, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback), |
base::Bind(&OnError, |
+ weak_ptr_factory_.GetWeakPtr(), |
error_callback)); |
} |
@@ -284,12 +346,15 @@ void ShillClientHelper::CallBooleanMethodWithErrorCallback( |
const ErrorCallback& error_callback) { |
DCHECK(!callback.is_null()); |
DCHECK(!error_callback.is_null()); |
+ AddRef(); |
proxy_->CallMethodWithErrorCallback( |
method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind(&OnBooleanMethodWithErrorCallback, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback, |
error_callback), |
base::Bind(&OnError, |
+ weak_ptr_factory_.GetWeakPtr(), |
error_callback)); |
} |
@@ -299,12 +364,15 @@ void ShillClientHelper::CallStringMethodWithErrorCallback( |
const ErrorCallback& error_callback) { |
DCHECK(!callback.is_null()); |
DCHECK(!error_callback.is_null()); |
+ AddRef(); |
proxy_->CallMethodWithErrorCallback( |
method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind(&OnStringMethodWithErrorCallback, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback, |
error_callback), |
base::Bind(&OnError, |
+ weak_ptr_factory_.GetWeakPtr(), |
error_callback)); |
} |
@@ -314,13 +382,16 @@ void ShillClientHelper::CallDictionaryValueMethodWithErrorCallback( |
const ErrorCallback& error_callback) { |
DCHECK(!callback.is_null()); |
DCHECK(!error_callback.is_null()); |
+ AddRef(); |
proxy_->CallMethodWithErrorCallback( |
method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind( |
&OnDictionaryValueMethodWithErrorCallback, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback, |
error_callback), |
base::Bind(&OnError, |
+ weak_ptr_factory_.GetWeakPtr(), |
error_callback)); |
} |
@@ -330,13 +401,16 @@ void ShillClientHelper::CallListValueMethodWithErrorCallback( |
const ErrorCallback& error_callback) { |
DCHECK(!callback.is_null()); |
DCHECK(!error_callback.is_null()); |
+ AddRef(); |
proxy_->CallMethodWithErrorCallback( |
method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
base::Bind( |
&OnListValueMethodWithErrorCallback, |
+ weak_ptr_factory_.GetWeakPtr(), |
callback, |
error_callback), |
base::Bind(&OnError, |
+ weak_ptr_factory_.GetWeakPtr(), |
error_callback)); |
} |