libweave: Add removing of weave::Command::Observer
Not a problem yet, but this is a cleaner approach.
BUG=none
TEST='FEATURES=test emerge-gizmo buffet'
Change-Id: I1889ee293a3e1db34aad14a7166b7ebbe32a8c10
Reviewed-on: https://chromium-review.googlesource.com/290161
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
Trybot-Ready: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/dbus_command_dispatcher.cc b/buffet/dbus_command_dispatcher.cc
index 39e106b..9bbb55e 100644
--- a/buffet/dbus_command_dispatcher.cc
+++ b/buffet/dbus_command_dispatcher.cc
@@ -30,7 +30,10 @@
object_manager_.get(), object_manager_->GetBus(), command,
buffet::kCommandServicePathPrefix + std::to_string(++next_id_))};
proxy->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
- command->AddObserver(proxy.release());
+ // DBusCommandProxy::DBusCommandProxy() subscribe itself to weave::Command
+ // notifications. When weave::Command is being destroyed it sends
+ // ::OnCommandDestroyed() and DBusCommandProxy deletes itself.
+ proxy.release();
}
} // namespace buffet
diff --git a/buffet/dbus_command_proxy.cc b/buffet/dbus_command_proxy.cc
index d53355a..f89ec52 100644
--- a/buffet/dbus_command_proxy.cc
+++ b/buffet/dbus_command_proxy.cc
@@ -20,7 +20,9 @@
weave::Command* command,
std::string object_path)
: command_{command},
- dbus_object_{object_manager, bus, dbus::ObjectPath{object_path}} {}
+ dbus_object_{object_manager, bus, dbus::ObjectPath{object_path}} {
+ observer_.Add(command);
+}
void DBusCommandProxy::RegisterAsync(
const AsyncEventSequencer::CompletionAction& completion_callback) {
diff --git a/buffet/dbus_command_proxy.h b/buffet/dbus_command_proxy.h
index 86d9c6e..7be3938 100644
--- a/buffet/dbus_command_proxy.h
+++ b/buffet/dbus_command_proxy.h
@@ -8,6 +8,7 @@
#include <string>
#include <base/macros.h>
+#include <base/scoped_observer.h>
#include <chromeos/dbus/data_serialization.h>
#include <chromeos/dbus/dbus_object.h>
@@ -59,6 +60,8 @@
org::chromium::Buffet::CommandAdaptor dbus_adaptor_{this};
chromeos::dbus_utils::DBusObject dbus_object_;
+ ScopedObserver<weave::Command, weave::Command::Observer> observer_{this};
+
friend class DBusCommandProxyTest;
friend class DBusCommandDispacherTest;
DISALLOW_COPY_AND_ASSIGN(DBusCommandProxy);
diff --git a/libweave/include/weave/command.h b/libweave/include/weave/command.h
index 58a63fe..0533afa 100644
--- a/libweave/include/weave/command.h
+++ b/libweave/include/weave/command.h
@@ -30,18 +30,22 @@
// This interface lets the command to notify clients about changes.
class Observer {
public:
- virtual ~Observer() = default;
-
virtual void OnResultsChanged() = 0;
virtual void OnStatusChanged() = 0;
virtual void OnProgressChanged() = 0;
virtual void OnCommandDestroyed() = 0;
+
+ protected:
+ virtual ~Observer() = default;
};
// Adds an observer for this command. The observer object is not owned by this
// class.
virtual void AddObserver(Observer* observer) = 0;
+ // Removes an observer for this command.
+ virtual void RemoveObserver(Observer* observer) = 0;
+
// Returns the full command ID.
virtual const std::string& GetID() const = 0;
diff --git a/libweave/include/weave/mock_command.h b/libweave/include/weave/mock_command.h
index def903d..8addfea 100644
--- a/libweave/include/weave/mock_command.h
+++ b/libweave/include/weave/mock_command.h
@@ -22,6 +22,7 @@
~MockCommand() override = default;
MOCK_METHOD1(AddObserver, void(Observer*));
+ MOCK_METHOD1(RemoveObserver, void(Observer*));
MOCK_CONST_METHOD0(GetID, const std::string&());
MOCK_CONST_METHOD0(GetName, const std::string&());
MOCK_CONST_METHOD0(GetCategory, const std::string&());
diff --git a/libweave/src/commands/cloud_command_proxy.cc b/libweave/src/commands/cloud_command_proxy.cc
index a6685fc..b277802 100644
--- a/libweave/src/commands/cloud_command_proxy.cc
+++ b/libweave/src/commands/cloud_command_proxy.cc
@@ -28,6 +28,7 @@
callback_token_ = state_change_queue_->AddOnStateUpdatedCallback(
base::Bind(&CloudCommandProxy::OnDeviceStateUpdated,
weak_ptr_factory_.GetWeakPtr()));
+ observer_.Add(command_instance);
}
void CloudCommandProxy::OnResultsChanged() {
diff --git a/libweave/src/commands/cloud_command_proxy.h b/libweave/src/commands/cloud_command_proxy.h
index db03885..5f7d21c 100644
--- a/libweave/src/commands/cloud_command_proxy.h
+++ b/libweave/src/commands/cloud_command_proxy.h
@@ -13,6 +13,7 @@
#include <base/macros.h>
#include <base/memory/ref_counted.h>
#include <base/memory/weak_ptr.h>
+#include <base/scoped_observer.h>
#include <base/task_runner.h>
#include <chromeos/backoff_entry.h>
@@ -90,6 +91,8 @@
// successfully.
UpdateID last_state_update_id_{0};
+ ScopedObserver<Command, Command::Observer> observer_{this};
+
base::WeakPtrFactory<CloudCommandProxy> backoff_weak_ptr_factory_{this};
base::WeakPtrFactory<CloudCommandProxy> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CloudCommandProxy);
diff --git a/libweave/src/commands/cloud_command_proxy_unittest.cc b/libweave/src/commands/cloud_command_proxy_unittest.cc
index 7cc054e..f3e9b60 100644
--- a/libweave/src/commands/cloud_command_proxy_unittest.cc
+++ b/libweave/src/commands/cloud_command_proxy_unittest.cc
@@ -157,7 +157,10 @@
&state_change_queue_,
std::move(backoff),
task_runner_}};
- command_instance_->AddObserver(proxy.release());
+ // CloudCommandProxy::CloudCommandProxy() subscribe itself to weave::Command
+ // notifications. When weave::Command is being destroyed it sends
+ // ::OnCommandDestroyed() and CloudCommandProxy deletes itself.
+ proxy.release();
}
StateChangeQueueInterface::UpdateID current_state_update_id_{0};
diff --git a/libweave/src/commands/command_instance.cc b/libweave/src/commands/command_instance.cc
index 8c4b89a..4e89dca 100644
--- a/libweave/src/commands/command_instance.cc
+++ b/libweave/src/commands/command_instance.cc
@@ -58,8 +58,7 @@
}
CommandInstance::~CommandInstance() {
- for (auto observer : observers_)
- observer->OnCommandDestroyed();
+ FOR_EACH_OBSERVER(Observer, observers_, OnCommandDestroyed());
}
const std::string& CommandInstance::GetID() const {
@@ -107,8 +106,7 @@
SetStatus(CommandStatus::kInProgress);
if (obj != progress_) {
progress_ = obj;
- for (auto observer : observers_)
- observer->OnProgressChanged();
+ FOR_EACH_OBSERVER(Observer, observers_, OnProgressChanged());
}
return true;
}
@@ -124,8 +122,7 @@
if (obj != results_) {
results_ = obj;
- for (auto observer : observers_)
- observer->OnResultsChanged();
+ FOR_EACH_OBSERVER(Observer, observers_, OnResultsChanged());
}
return true;
}
@@ -251,7 +248,11 @@
}
void CommandInstance::AddObserver(Observer* observer) {
- observers_.push_back(observer);
+ observers_.AddObserver(observer);
+}
+
+void CommandInstance::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
}
void CommandInstance::Abort() {
@@ -275,8 +276,7 @@
void CommandInstance::SetStatus(CommandStatus status) {
if (status != status_) {
status_ = status;
- for (auto observer : observers_)
- observer->OnStatusChanged();
+ FOR_EACH_OBSERVER(Observer, observers_, OnStatusChanged());
}
}
diff --git a/libweave/src/commands/command_instance.h b/libweave/src/commands/command_instance.h
index 1b30d53..d709e2f 100644
--- a/libweave/src/commands/command_instance.h
+++ b/libweave/src/commands/command_instance.h
@@ -11,6 +11,7 @@
#include <vector>
#include <base/macros.h>
+#include <base/observer_list.h>
#include <chromeos/errors/error.h>
#include "libweave/src/commands/prop_values.h"
@@ -42,6 +43,7 @@
// Command overrides.
std::unique_ptr<base::DictionaryValue> ToJson() const override;
void AddObserver(Observer* observer) override;
+ void RemoveObserver(Observer* observer) override;
const std::string& GetID() const override;
const std::string& GetName() const override;
const std::string& GetCategory() const override;
@@ -109,8 +111,8 @@
ValueMap results_;
// Current command status.
CommandStatus status_ = CommandStatus::kQueued;
- // Command observer for the command.
- std::vector<Observer*> observers_;
+ // Command observers.
+ base::ObserverList<Observer> observers_;
// Pointer to the command queue this command instance is added to.
// The queue owns the command instance, so it outlives this object.
CommandQueue* queue_ = nullptr;
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc
index 1eddc21..ff35f5c 100644
--- a/libweave/src/device_registration_info.cc
+++ b/libweave/src/device_registration_info.cc
@@ -1012,10 +1012,13 @@
<< "' arrived, ID: " << command_instance->GetID();
std::unique_ptr<chromeos::BackoffEntry> backoff_entry{
new chromeos::BackoffEntry{cloud_backoff_policy_.get()}};
- std::unique_ptr<Command::Observer> cloud_proxy{new CloudCommandProxy{
+ std::unique_ptr<CloudCommandProxy> cloud_proxy{new CloudCommandProxy{
command_instance.get(), this, state_manager_->GetStateChangeQueue(),
std::move(backoff_entry), task_runner_}};
- command_instance->AddObserver(cloud_proxy.release());
+ // CloudCommandProxy::CloudCommandProxy() subscribe itself to weave::Command
+ // notifications. When weave::Command is being destroyed it sends
+ // ::OnCommandDestroyed() and CloudCommandProxy deletes itself.
+ cloud_proxy.release();
command_manager_->AddCommand(std::move(command_instance));
}
}