Chromium Code Reviews| Index: chromeos/dbus/shill_service_client.cc |
| diff --git a/chromeos/dbus/shill_service_client.cc b/chromeos/dbus/shill_service_client.cc |
| index 8e0ede00f565ea2ecb7d795702c48a3891816029..ccb1ef53743325e57c88f06609298e52e90bc1a6 100644 |
| --- a/chromeos/dbus/shill_service_client.cc |
| +++ b/chromeos/dbus/shill_service_client.cc |
| @@ -40,12 +40,81 @@ void OnGetPropertiesError( |
| callback.Run(DBUS_METHOD_CALL_FAILURE, empty_dictionary); |
| } |
| +// ShillClientHelper callback wrappers. |
| +// For each one of the different callback types in ShillClientHelper, we define |
| +// a wrapper that attachs a clousure to the given callback. This allows it to |
| +// call a second callback (the clousure) after the first callback is called. |
| +// This is used to get a notification in the ShillServiceClient when a |
| +// MethodCall returns. |
| + |
| +// * Wrapper for DictionaryValueCallback. |
| +void RunDictionaryValueCallback( |
| + const base::Closure& closure, |
| + const ShillClientHelper::DictionaryValueCallback& callback, |
| + DBusMethodCallStatus call_status, |
| + const DictionaryValue& argument) { |
| + callback.Run(call_status, argument); |
| + closure.Run(); |
| +} |
| + |
| +ShillClientHelper::DictionaryValueCallback |
| + AttachClosureToDictionaryValueCallback( |
| + const ShillClientHelper::DictionaryValueCallback& callback, |
| + const base::Closure& closure) { |
| + return base::Bind(&RunDictionaryValueCallback, closure, callback); |
| +} |
| + |
|
stevenjb
2013/02/07 01:12:30
So, I apologize for continuing to iterate on this,
hashimoto
2013/02/07 05:20:31
Wasn't the bug marked as P1/ReleaseBlocker?
I thin
|
| +// * Wrapper for ListValueCallback |
| +void RunListValueCallback( |
| + const base::Closure& closure, |
| + const ShillClientHelper::ListValueCallback& callback, |
| + const ListValue& argument) { |
| + callback.Run(argument); |
| + closure.Run(); |
| +} |
| + |
| +ShillClientHelper::ListValueCallback AttachClosureToListValueCallback( |
| + const ShillClientHelper::ListValueCallback& callback, |
| + const base::Closure& closure) { |
| + return base::Bind(&RunListValueCallback, closure, callback); |
| +} |
| + |
| +// * Wrapper for ErrorCallback |
| +void RunErrorCallback( |
| + const base::Closure& closure, |
| + const ShillClientHelper::ErrorCallback& callback, |
| + const std::string& error_name, |
| + const std::string& error_message) { |
| + callback.Run(error_name, error_message); |
| + closure.Run(); |
| +} |
| + |
| +ShillClientHelper::ErrorCallback AttachClosureToErrorCallback( |
| + const ShillClientHelper::ErrorCallback& callback, |
| + const base::Closure& closure) { |
| + return base::Bind(&RunErrorCallback, closure, callback); |
| +} |
| + |
| +// * Wrapper for Closure |
| +void RunClosure(const base::Closure& closure, |
| + const base::Closure& callback) { |
| + callback.Run(); |
| + closure.Run(); |
| +} |
| + |
| +base::Closure AttachClosureToClosure( |
| + const base::Closure& callback, |
| + const base::Closure& closure) { |
| + return base::Bind(&RunClosure, closure, callback); |
| +} |
| + |
| // The ShillServiceClient implementation. |
| class ShillServiceClientImpl : public ShillServiceClient { |
| public: |
| explicit ShillServiceClientImpl(dbus::Bus* bus) |
| : bus_(bus), |
| - helpers_deleter_(&helpers_) { |
| + helpers_deleter_(&helpers_), |
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| } |
| ///////////////////////////////////// |
| @@ -60,6 +129,7 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| const dbus::ObjectPath& service_path, |
| ShillPropertyChangedObserver* observer) OVERRIDE { |
| GetHelper(service_path)->RemovePropertyChangedObserver(observer); |
| + OnHelperStatusUpdate(service_path); |
| } |
| virtual void GetProperties(const dbus::ObjectPath& service_path, |
| @@ -68,8 +138,14 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| flimflam::kGetPropertiesFunction); |
| GetHelper(service_path)->CallDictionaryValueMethodWithErrorCallback( |
| &method_call, |
| - base::Bind(callback, DBUS_METHOD_CALL_SUCCESS), |
| - base::Bind(&OnGetPropertiesError, service_path, callback)); |
| + base::Bind( |
| + AttachClosureToDictionaryValueCallback(callback, |
| + base::Bind(&ShillServiceClientImpl::OnHelperStatusUpdate, |
| + weak_ptr_factory_.GetWeakPtr(), service_path)), |
| + DBUS_METHOD_CALL_SUCCESS), |
| + AttachClosureToErrorCallback( |
| + base::Bind(&OnGetPropertiesError, service_path, callback), |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| virtual void SetProperty(const dbus::ObjectPath& service_path, |
| @@ -82,9 +158,12 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(name); |
| ShillClientHelper::AppendValueDataAsVariant(&writer, value); |
| - GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, |
| - callback, |
| - error_callback); |
| + GetHelper(service_path)->CallVoidMethodWithErrorCallback( |
| + &method_call, |
| + AttachClosureToClosure(callback, |
| + HelperStatusUpdateCallback(service_path)), |
| + AttachClosureToErrorCallback(error_callback, |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| virtual void ClearProperty(const dbus::ObjectPath& service_path, |
| @@ -95,9 +174,12 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| flimflam::kClearPropertyFunction); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(name); |
| - GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, |
| - callback, |
| - error_callback); |
| + GetHelper(service_path)->CallVoidMethodWithErrorCallback( |
| + &method_call, |
| + AttachClosureToClosure(callback, |
| + HelperStatusUpdateCallback(service_path)), |
| + AttachClosureToErrorCallback(error_callback, |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| @@ -111,8 +193,10 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| writer.AppendArrayOfStrings(names); |
| GetHelper(service_path)->CallListValueMethodWithErrorCallback( |
| &method_call, |
| - callback, |
| - error_callback); |
| + AttachClosureToListValueCallback(callback, |
| + HelperStatusUpdateCallback(service_path)), |
| + AttachClosureToErrorCallback(error_callback, |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| virtual void Connect(const dbus::ObjectPath& service_path, |
| @@ -121,7 +205,11 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, |
| flimflam::kConnectFunction); |
| GetHelper(service_path)->CallVoidMethodWithErrorCallback( |
| - &method_call, callback, error_callback); |
| + &method_call, |
| + AttachClosureToClosure(callback, |
| + HelperStatusUpdateCallback(service_path)), |
| + AttachClosureToErrorCallback(error_callback, |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| virtual void Disconnect(const dbus::ObjectPath& service_path, |
| @@ -129,9 +217,12 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| const ErrorCallback& error_callback) OVERRIDE { |
| dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, |
| flimflam::kDisconnectFunction); |
| - GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, |
| - callback, |
| - error_callback); |
| + GetHelper(service_path)->CallVoidMethodWithErrorCallback( |
| + &method_call, |
| + AttachClosureToClosure(callback, |
| + HelperStatusUpdateCallback(service_path)), |
| + AttachClosureToErrorCallback(error_callback, |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| virtual void Remove(const dbus::ObjectPath& service_path, |
| @@ -139,9 +230,12 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| const ErrorCallback& error_callback) OVERRIDE { |
| dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, |
| flimflam::kRemoveServiceFunction); |
| - GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, |
| - callback, |
| - error_callback); |
| + GetHelper(service_path)->CallVoidMethodWithErrorCallback( |
| + &method_call, |
| + AttachClosureToClosure(callback, |
| + HelperStatusUpdateCallback(service_path)), |
| + AttachClosureToErrorCallback(error_callback, |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| virtual void ActivateCellularModem( |
| @@ -153,9 +247,12 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| flimflam::kActivateCellularModemFunction); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(carrier); |
| - GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, |
| - callback, |
| - error_callback); |
| + GetHelper(service_path)->CallVoidMethodWithErrorCallback( |
| + &method_call, |
| + AttachClosureToClosure(callback, |
| + HelperStatusUpdateCallback(service_path)), |
| + AttachClosureToErrorCallback(error_callback, |
| + HelperStatusUpdateCallback(service_path))); |
| } |
| virtual bool CallActivateCellularModemAndBlock( |
| @@ -165,7 +262,9 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| flimflam::kActivateCellularModemFunction); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(carrier); |
| - return GetHelper(service_path)->CallVoidMethodAndBlock(&method_call); |
| + bool result = GetHelper(service_path)->CallVoidMethodAndBlock(&method_call); |
| + OnHelperStatusUpdate(service_path); |
| + return result; |
| } |
| virtual ShillServiceClient::TestInterface* GetTestInterface() OVERRIDE { |
| @@ -185,15 +284,48 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| dbus::ObjectProxy* object_proxy = |
| bus_->GetObjectProxy(flimflam::kFlimflamServiceName, service_path); |
| ShillClientHelper* helper = new ShillClientHelper(bus_, object_proxy); |
| + // TODO(deymo): Delay the MonitorPropertyChanged call until an observer is |
| + // added to the helper. If no observer is add and every call finishes we |
| + // delete the helper making this AddMatch and RemoveMatch blocking cycle is |
| + // useless. |
|
stevenjb
2013/02/07 01:12:30
This doesn't seem too difficult, I think it's wort
|
| helper->MonitorPropertyChanged(flimflam::kFlimflamServiceInterface); |
| helpers_.insert(HelperMap::value_type(service_path.value(), helper)); |
| return helper; |
| } |
| + // Returns a Closure that calls OnHelperStatusUpdate with the given |
| + // |service_path| argument. |
| + base::Closure HelperStatusUpdateCallback( |
| + const dbus::ObjectPath& service_path) { |
| + return base::Bind(&ShillServiceClientImpl::OnHelperStatusUpdate, |
| + weak_ptr_factory_.GetWeakPtr(), service_path); |
| + } |
| + |
| + // This function is called every time the IsObserved or the IsWaitingResponse |
| + // helper's properties may have changed. If both are false, the cached helper |
| + // can be safely removed. |
| + void OnHelperStatusUpdate(const dbus::ObjectPath& service_path) { |
| + HelperMap::iterator it = helpers_.find(service_path.value()); |
| + if (it == helpers_.end()) |
| + return; |
| + |
| + ShillClientHelper* const helper = it->second; |
| + if (!helper->IsObserved() && !helper->IsWaitingResponse()) { |
| + helpers_.erase(it); |
| + delete helper; |
| + bus_->RemoveObjectProxy(flimflam::kFlimflamServiceName, service_path, |
| + base::Bind(&base::DoNothing)); |
| + } |
| + } |
| + |
| dbus::Bus* bus_; |
| HelperMap helpers_; |
| STLValueDeleter<HelperMap> helpers_deleter_; |
| + // Note: This should remain the last member so it'll be destroyed and |
| + // invalidate its weak pointers before any other members are destroyed. |
| + base::WeakPtrFactory<ShillServiceClientImpl> weak_ptr_factory_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(ShillServiceClientImpl); |
| }; |
| @@ -201,7 +333,8 @@ class ShillServiceClientImpl : public ShillServiceClient { |
| class ShillServiceClientStubImpl : public ShillServiceClient, |
| public ShillServiceClient::TestInterface { |
| public: |
| - ShillServiceClientStubImpl() : weak_ptr_factory_(this) { |
| + ShillServiceClientStubImpl() : |
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| SetDefaultProperties(); |
| } |