blob: a61dcd2989eff61aa4b7d18054b98db2edd9ed68 [file] [log] [blame]
yoshiki iguchic13b16f92017-10-13 05:31:581// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/message_center/change_queue.h"
6
7#include "ui/message_center/message_center_impl.h"
8#include "ui/message_center/notification.h"
9
10namespace message_center {
11
12// Change represents an operation made on a notification. Since it contains
13// the final state of the notification, except complex cases, we generally
14// optimize the list and keep only the last change for a particular notification
15// that is in the notification list around. There are two ids; |id_| is the
16// post-update notification id that has been assigned by an update, and
17// |previous_id| is the previous id of the notification before the Change.
18// The two ids are same unless the Change changes the id of the notification.
19// See the comments of id() and previous_id() for reference.
20class ChangeQueue::Change {
21 public:
22 Change(ChangeType type,
23 const std::string& id,
24 std::unique_ptr<Notification> notification);
25 ~Change();
26
27 // Used to transfer ownership of the contained notification.
28 std::unique_ptr<Notification> PassNotification();
29
30 Notification* notification() const { return notification_.get(); }
31 // Returns the post-update ID. It means:
32 // - ADD event: ID of the notification to be added. In this case, this must be
33 // same as |previous_id()|.
34 // - UPDATE event: ID of the notification after the change. If the change
35 // doesn't update its ID, this value is same as |previous_id()|.
36 // - DELETE event: ID of the notification to be deleted. This must be same as
37 // |previous_id()|.
38 const std::string& id() const { return id_; }
39 ChangeType type() const { return type_; }
40 bool by_user() const { return by_user_; }
41 void set_by_user(bool by_user) { by_user_ = by_user; }
42 // Returns the ID which is used in the notification list. In other word, it
43 // means the ID before the change.
44 const std::string& previous_id() const { return previous_id_; }
45 void set_type(const ChangeType new_type) { type_ = new_type; }
46 void ReplaceNotification(std::unique_ptr<Notification> new_notification);
47
48 private:
49 ChangeType type_;
50 std::string id_;
51 std::string previous_id_;
52 bool by_user_;
53 std::unique_ptr<Notification> notification_;
54
55 DISALLOW_COPY_AND_ASSIGN(Change);
56};
57
58////////////////////////////////////////////////////////////////////////////////
59// ChangeFinder
60
61struct ChangeFinder {
62 explicit ChangeFinder(const std::string& id) : id(id) {}
63 bool operator()(const std::unique_ptr<ChangeQueue::Change>& change) {
64 return change->id() == id;
65 }
66
67 std::string id;
68};
69
70////////////////////////////////////////////////////////////////////////////////
71// ChangeQueue::Change
72
73ChangeQueue::Change::Change(ChangeType type,
74 const std::string& id,
75 std::unique_ptr<Notification> notification)
76 : type_(type),
77 previous_id_(id),
78 by_user_(false),
79 notification_(std::move(notification)) {
80 DCHECK(!id.empty());
81 DCHECK(type != CHANGE_TYPE_DELETE || !notification_);
82
83 id_ = notification_ ? notification_->id() : previous_id_;
84}
85
86ChangeQueue::Change::~Change() {}
87
88std::unique_ptr<Notification> ChangeQueue::Change::PassNotification() {
89 return std::move(notification_);
90}
91
92void ChangeQueue::Change::ReplaceNotification(
93 std::unique_ptr<Notification> new_notification) {
94 id_ = new_notification ? new_notification->id() : previous_id_;
95 notification_.swap(new_notification);
96}
97
98////////////////////////////////////////////////////////////////////////////////
99// ChangeQueue
100
101ChangeQueue::ChangeQueue() = default;
102
103ChangeQueue::~ChangeQueue() = default;
104
105void ChangeQueue::ApplyChanges(MessageCenterImpl* message_center) {
106 while (!changes_.empty()) {
107 auto iter = changes_.begin();
108 std::unique_ptr<Change> change(std::move(*iter));
109 changes_.erase(iter);
110 ApplyChangeInternal(message_center, std::move(change));
111 }
112}
113
114void ChangeQueue::AddNotification(std::unique_ptr<Notification> notification) {
115 std::string id = notification->id();
116 changes_.push_back(
117 std::make_unique<Change>(CHANGE_TYPE_ADD, id, std::move(notification)));
118}
119
120void ChangeQueue::UpdateNotification(
121 const std::string& old_id,
122 std::unique_ptr<Notification> notification) {
123 changes_.push_back(std::make_unique<Change>(CHANGE_TYPE_UPDATE, old_id,
124 std::move(notification)));
125}
126
127void ChangeQueue::RemoveNotification(const std::string& id, bool by_user) {
128 auto change = std::make_unique<Change>(CHANGE_TYPE_DELETE, id, nullptr);
129 change->set_by_user(by_user);
130 changes_.push_back(std::move(change));
131}
132
133Notification* ChangeQueue::GetLatestNotification(const std::string& id) const {
134 auto iter =
135 std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(id));
136 if (iter == changes_.rend())
137 return nullptr;
138
139 if ((*iter)->type() == CHANGE_TYPE_DELETE)
140 return nullptr;
141
142 return (*iter)->notification();
143}
144
145void ChangeQueue::ApplyChangeInternal(MessageCenterImpl* message_center,
146 std::unique_ptr<Change> change) {
147 switch (change->type()) {
148 case CHANGE_TYPE_ADD:
149 message_center->AddNotificationImmediately(change->PassNotification());
150 break;
151 case CHANGE_TYPE_UPDATE:
152 message_center->UpdateNotificationImmediately(change->previous_id(),
153 change->PassNotification());
154 break;
155 case CHANGE_TYPE_DELETE:
156 message_center->RemoveNotificationImmediately(change->previous_id(),
157 change->by_user());
158 break;
159 default:
160 NOTREACHED();
161 }
162}
163
164} // namespace message_center