Chromium Code Reviews| 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..9b34f003331a5f9594dd2f17a04a7d91282ab878 100644 |
| --- a/chromeos/dbus/shill_client_helper.cc |
| +++ b/chromeos/dbus/shill_client_helper.cc |
| @@ -13,12 +13,37 @@ |
| namespace chromeos { |
| +// Class to hold onto a reference to a ShillClientHelper. This calss |
| +// is owned by callbacks and released once the callback completes. |
| +// Note: Only success callbacks hold the reference. If an error callback is |
| +// invoked instead, the success callback will still be destroyed and the |
| +// RefHolder with it, once the callback chain completes. |
| +class ShillClientHelper::RefHolder { |
| + public: |
| + explicit RefHolder(base::WeakPtr<ShillClientHelper> helper) |
| + : helper_(helper) { |
| + helper_->AddRef(); |
| + } |
| + ~RefHolder() { |
| + if (helper_) |
| + helper_->Release(); |
| + } |
| + ShillClientHelper* helper() { return helper_.get(); } |
| + |
| + private: |
| + base::WeakPtr<ShillClientHelper> helper_; |
| +}; |
| + |
| namespace { |
| const char kInvalidResponseErrorName[] = ""; // No error name. |
| const char kInvalidResponseErrorMessage[] = "Invalid response."; |
| +// Note: here and below, |ref_holder| is unused in the function body. It only |
| +// exists so that it will be destroyed (and the reference released) with the |
| +// Callback object once completed. |
| void OnBooleanMethodWithErrorCallback( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const ShillClientHelper::BooleanCallback& callback, |
| const ShillClientHelper::ErrorCallback& error_callback, |
| dbus::Response* response) { |
| @@ -36,6 +61,7 @@ void OnBooleanMethodWithErrorCallback( |
| } |
| void OnStringMethodWithErrorCallback( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const ShillClientHelper::StringCallback& callback, |
| const ShillClientHelper::ErrorCallback& error_callback, |
| dbus::Response* response) { |
| @@ -53,7 +79,8 @@ void OnStringMethodWithErrorCallback( |
| } |
| // Handles responses for methods without results. |
| -void OnVoidMethod(const VoidDBusMethodCallback& callback, |
| +void OnVoidMethod(ShillClientHelper::RefHolder* ref_holder, |
| + const VoidDBusMethodCallback& callback, |
| dbus::Response* response) { |
| if (!response) { |
| callback.Run(DBUS_METHOD_CALL_FAILURE); |
| @@ -64,6 +91,7 @@ void OnVoidMethod(const VoidDBusMethodCallback& callback, |
| // Handles responses for methods with ObjectPath results. |
| void OnObjectPathMethod( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const ObjectPathDBusMethodCallback& callback, |
| dbus::Response* response) { |
| if (!response) { |
| @@ -81,6 +109,7 @@ void OnObjectPathMethod( |
| // Handles responses for methods with ObjectPath results and no status. |
| void OnObjectPathMethodWithoutStatus( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const ObjectPathCallback& callback, |
| const ShillClientHelper::ErrorCallback& error_callback, |
| dbus::Response* response) { |
| @@ -99,6 +128,7 @@ void OnObjectPathMethodWithoutStatus( |
| // Handles responses for methods with DictionaryValue results. |
| void OnDictionaryValueMethod( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const ShillClientHelper::DictionaryValueCallback& callback, |
| dbus::Response* response) { |
| if (!response) { |
| @@ -119,6 +149,7 @@ void OnDictionaryValueMethod( |
| // Handles responses for methods without results. |
| void OnVoidMethodWithErrorCallback( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const base::Closure& callback, |
| dbus::Response* response) { |
| callback.Run(); |
| @@ -127,6 +158,7 @@ void OnVoidMethodWithErrorCallback( |
| // Handles responses for methods with DictionaryValue results. |
| // Used by CallDictionaryValueMethodWithErrorCallback(). |
| void OnDictionaryValueMethodWithErrorCallback( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const ShillClientHelper::DictionaryValueCallbackWithoutStatus& callback, |
| const ShillClientHelper::ErrorCallback& error_callback, |
| dbus::Response* response) { |
| @@ -142,6 +174,7 @@ void OnDictionaryValueMethodWithErrorCallback( |
| // Handles responses for methods with ListValue results. |
| void OnListValueMethodWithErrorCallback( |
| + ShillClientHelper::RefHolder* ref_holder, |
| const ShillClientHelper::ListValueCallback& callback, |
| const ShillClientHelper::ErrorCallback& error_callback, |
| dbus::Response* response) { |
| @@ -171,9 +204,9 @@ void OnError(const ShillClientHelper::ErrorCallback& error_callback, |
| } // namespace |
| -ShillClientHelper::ShillClientHelper(dbus::Bus* bus, |
| - dbus::ObjectProxy* proxy) |
| +ShillClientHelper::ShillClientHelper(dbus::ObjectProxy* proxy) |
| : proxy_(proxy), |
| + active_refs_(0), |
| weak_ptr_factory_(this) { |
| } |
| @@ -182,8 +215,14 @@ ShillClientHelper::~ShillClientHelper() { |
| << "ShillClientHelper destroyed with active observers"; |
| } |
| +void ShillClientHelper::SetReleasedCallback(ReleasedCallback callback) { |
| + CHECK(released_callback_.is_null()); |
| + released_callback_ = callback; |
| +} |
| + |
| 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 +235,7 @@ void ShillClientHelper::AddPropertyChangedObserver( |
| void ShillClientHelper::RemovePropertyChangedObserver( |
| ShillPropertyChangedObserver* observer) { |
| observer_list_.RemoveObserver(observer); |
| + Release(); |
|
hashimoto
2013/09/18 04:32:30
question: Can we be sure that the users of this cl
stevenjb
2013/09/18 16:58:28
Good suggestion. Done. (Note: ObserverList::AddObs
|
| } |
| void ShillClientHelper::MonitorPropertyChanged( |
| @@ -225,18 +265,22 @@ void ShillClientHelper::CallVoidMethod( |
| dbus::MethodCall* method_call, |
| const VoidDBusMethodCallback& callback) { |
| DCHECK(!callback.is_null()); |
| - proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| - base::Bind(&OnVoidMethod, |
| - callback)); |
| + proxy_->CallMethod( |
| + method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| + base::Bind(&OnVoidMethod, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| + callback)); |
| } |
| void ShillClientHelper::CallObjectPathMethod( |
| dbus::MethodCall* method_call, |
| const ObjectPathDBusMethodCallback& callback) { |
| DCHECK(!callback.is_null()); |
| - proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| - base::Bind(&OnObjectPathMethod, |
| - callback)); |
| + proxy_->CallMethod( |
| + method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| + base::Bind(&OnObjectPathMethod, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| + callback)); |
| } |
| void ShillClientHelper::CallObjectPathMethodWithErrorCallback( |
| @@ -249,6 +293,7 @@ void ShillClientHelper::CallObjectPathMethodWithErrorCallback( |
| method_call, |
| dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::Bind(&OnObjectPathMethodWithoutStatus, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| callback, |
| error_callback), |
| base::Bind(&OnError, |
| @@ -259,9 +304,11 @@ void ShillClientHelper::CallDictionaryValueMethod( |
| dbus::MethodCall* method_call, |
| const DictionaryValueCallback& callback) { |
| DCHECK(!callback.is_null()); |
| - proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| - base::Bind(&OnDictionaryValueMethod, |
| - callback)); |
| + proxy_->CallMethod( |
| + method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| + base::Bind(&OnDictionaryValueMethod, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| + callback)); |
| } |
| void ShillClientHelper::CallVoidMethodWithErrorCallback( |
| @@ -273,6 +320,7 @@ void ShillClientHelper::CallVoidMethodWithErrorCallback( |
| proxy_->CallMethodWithErrorCallback( |
| method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::Bind(&OnVoidMethodWithErrorCallback, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| callback), |
| base::Bind(&OnError, |
| error_callback)); |
| @@ -287,6 +335,7 @@ void ShillClientHelper::CallBooleanMethodWithErrorCallback( |
| proxy_->CallMethodWithErrorCallback( |
| method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::Bind(&OnBooleanMethodWithErrorCallback, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| callback, |
| error_callback), |
| base::Bind(&OnError, |
| @@ -302,6 +351,7 @@ void ShillClientHelper::CallStringMethodWithErrorCallback( |
| proxy_->CallMethodWithErrorCallback( |
| method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::Bind(&OnStringMethodWithErrorCallback, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| callback, |
| error_callback), |
| base::Bind(&OnError, |
| @@ -316,10 +366,10 @@ void ShillClientHelper::CallDictionaryValueMethodWithErrorCallback( |
| DCHECK(!error_callback.is_null()); |
| proxy_->CallMethodWithErrorCallback( |
| method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| - base::Bind( |
| - &OnDictionaryValueMethodWithErrorCallback, |
| - callback, |
| - error_callback), |
| + base::Bind(&OnDictionaryValueMethodWithErrorCallback, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| + callback, |
| + error_callback), |
| base::Bind(&OnError, |
| error_callback)); |
| } |
| @@ -332,10 +382,10 @@ void ShillClientHelper::CallListValueMethodWithErrorCallback( |
| DCHECK(!error_callback.is_null()); |
| proxy_->CallMethodWithErrorCallback( |
| method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| - base::Bind( |
| - &OnListValueMethodWithErrorCallback, |
| - callback, |
| - error_callback), |
| + base::Bind(&OnListValueMethodWithErrorCallback, |
| + base::Owned(new RefHolder(weak_ptr_factory_.GetWeakPtr())), |
| + callback, |
| + error_callback), |
| base::Bind(&OnError, |
| error_callback)); |
| } |
| @@ -420,6 +470,16 @@ void ShillClientHelper::AppendServicePropertiesDictionary( |
| writer->CloseContainer(&array_writer); |
| } |
| +void ShillClientHelper::AddRef() { |
| + ++active_refs_; |
| +} |
| + |
| +void ShillClientHelper::Release() { |
| + --active_refs_; |
| + if (active_refs_ == 0 && !released_callback_.is_null()) |
| + released_callback_.Run(this); // May delete this |
|
hashimoto
2013/09/18 04:32:30
nit: base::ResetAndReturn(&released_callback_).Run
stevenjb
2013/09/18 16:58:28
Hmm, good suggestion. Hopefully that wouldn't be a
|
| +} |
| + |
| void ShillClientHelper::OnSignalConnected(const std::string& interface, |
| const std::string& signal, |
| bool success) { |
| @@ -443,5 +503,4 @@ void ShillClientHelper::OnPropertyChanged(dbus::Signal* signal) { |
| OnPropertyChanged(name, *value)); |
| } |
| - |
| } // namespace chromeos |