Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1026)

Side by Side Diff: components/offline_pages/core/downloads/download_ui_adapter.cc

Issue 2631933002: Adding status info to DownloadUIItem and piping it through. (Closed)
Patch Set: fix comment Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/offline_pages/core/downloads/download_ui_adapter.h" 5 #include "components/offline_pages/core/downloads/download_ui_adapter.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/guid.h" 8 #include "base/guid.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
11 #include "base/threading/thread_task_runner_handle.h" 11 #include "base/threading/thread_task_runner_handle.h"
12 #include "components/offline_pages/core/background/request_coordinator.h"
13 #include "components/offline_pages/core/background/save_page_request.h"
12 #include "components/offline_pages/core/client_namespace_constants.h" 14 #include "components/offline_pages/core/client_namespace_constants.h"
13 #include "components/offline_pages/core/client_policy_controller.h" 15 #include "components/offline_pages/core/client_policy_controller.h"
14 #include "components/offline_pages/core/downloads/download_ui_item.h" 16 #include "components/offline_pages/core/downloads/download_ui_item.h"
15 #include "components/offline_pages/core/offline_page_model.h" 17 #include "components/offline_pages/core/offline_page_model.h"
16 18
17 namespace offline_pages { 19 namespace offline_pages {
18 20
19 namespace {
20 const char kDownloadUIAdapterKey[] = "download-ui-adapter";
21 }
22
23 DownloadUIAdapter::ItemInfo::ItemInfo(const OfflinePageItem& page) 21 DownloadUIAdapter::ItemInfo::ItemInfo(const OfflinePageItem& page)
24 : ui_item(base::MakeUnique<DownloadUIItem>(page)), 22 : ui_item(base::MakeUnique<DownloadUIItem>(page)),
25 offline_id(page.offline_id) {} 23 is_request(false),
24 offline_id(page.offline_id),
25 client_id(page.client_id),
26 temporarily_hidden(false) {}
27
28 DownloadUIAdapter::ItemInfo::ItemInfo(const SavePageRequest& request)
29 : ui_item(base::MakeUnique<DownloadUIItem>(request)),
30 is_request(true),
31 offline_id(request.request_id()),
32 client_id(request.client_id()),
33 temporarily_hidden(false) {}
26 34
27 DownloadUIAdapter::ItemInfo::~ItemInfo() {} 35 DownloadUIAdapter::ItemInfo::~ItemInfo() {}
28 36
29 DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model) 37 DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model,
38 RequestCoordinator* request_coordinator,
39 std::unique_ptr<Delegate> delegate)
30 : model_(model), 40 : model_(model),
41 request_coordinator_(request_coordinator),
42 delegate_(std::move(delegate)),
31 state_(State::NOT_LOADED), 43 state_(State::NOT_LOADED),
32 observers_count_(0), 44 observers_count_(0),
33 weak_ptr_factory_(this) {} 45 weak_ptr_factory_(this) {}
34 46
35 DownloadUIAdapter::~DownloadUIAdapter() {} 47 DownloadUIAdapter::~DownloadUIAdapter() {}
36 48
37 // static
38 DownloadUIAdapter* DownloadUIAdapter::FromOfflinePageModel(
39 OfflinePageModel* offline_page_model) {
40 DownloadUIAdapter* adapter = static_cast<DownloadUIAdapter*>(
41 offline_page_model->GetUserData(kDownloadUIAdapterKey));
42 if (!adapter) {
43 adapter = new DownloadUIAdapter(offline_page_model);
44 offline_page_model->SetUserData(kDownloadUIAdapterKey, adapter);
45 }
46 return adapter;
47 }
48
49 void DownloadUIAdapter::AddObserver(Observer* observer) { 49 void DownloadUIAdapter::AddObserver(Observer* observer) {
50 DCHECK(observer); 50 DCHECK(observer);
51 if (observers_.HasObserver(observer)) 51 if (observers_.HasObserver(observer))
52 return; 52 return;
53 if (observers_count_ == 0) 53 if (observers_count_ == 0)
54 LoadCache(); 54 LoadCache();
55 observers_.AddObserver(observer); 55 observers_.AddObserver(observer);
56 ++observers_count_; 56 ++observers_count_;
57 // If the items are already loaded, post the notification right away. 57 // If the items are already loaded, post the notification right away.
58 // Don't just invoke it from here to avoid reentrancy in the client. 58 // Don't just invoke it from here to avoid reentrancy in the client.
(...skipping 16 matching lines...) Expand all
75 ClearCache(); 75 ClearCache();
76 } 76 }
77 77
78 void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) { 78 void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) {
79 // This signal is not used here. 79 // This signal is not used here.
80 } 80 }
81 81
82 void DownloadUIAdapter::OfflinePageAdded(OfflinePageModel* model, 82 void DownloadUIAdapter::OfflinePageAdded(OfflinePageModel* model,
83 const OfflinePageItem& added_page) { 83 const OfflinePageItem& added_page) {
84 DCHECK(model == model_); 84 DCHECK(model == model_);
85 if (!IsVisibleInUI(added_page.client_id)) 85 if (!delegate_->IsVisibleInUI(added_page.client_id))
86 return; 86 return;
87 87
88 const std::string& guid = added_page.client_id.id; 88 AddItemHelper(base::MakeUnique<ItemInfo>(added_page));
89 DCHECK(items_.find(guid) == items_.end());
90
91 items_[guid] = base::MakeUnique<ItemInfo>(added_page);
92 const DownloadUIItem& item = *(items_[guid]->ui_item);
93 for (Observer& observer : observers_)
94 observer.ItemAdded(item);
95 } 89 }
96 90
97 void DownloadUIAdapter::OfflinePageDeleted(int64_t offline_id, 91 void DownloadUIAdapter::OfflinePageDeleted(int64_t offline_id,
98 const ClientId& client_id) { 92 const ClientId& client_id) {
99 if (!IsVisibleInUI(client_id)) 93 if (!delegate_->IsVisibleInUI(client_id))
100 return; 94 return;
101 std::string guid = client_id.id; 95 DeleteItemHelper(client_id.id);
102 DownloadUIItems::const_iterator it = items_.find(guid); 96 }
103 if (it == items_.end()) 97
98 // RequestCoordinator::Observer
99 void DownloadUIAdapter::OnAdded(const SavePageRequest& added_request) {
100 if (!delegate_->IsVisibleInUI(added_request.client_id()))
104 return; 101 return;
105 items_.erase(it); 102
103 AddItemHelper(base::MakeUnique<ItemInfo>(added_request));
104 }
105
106 // RequestCoordinator::Observer
107 void DownloadUIAdapter::OnCompleted(
108 const SavePageRequest& request,
109 RequestNotifier::BackgroundSavePageResult status) {
110 if (!delegate_->IsVisibleInUI(request.client_id()))
111 return;
112
113 // If request completed successfully, report ItemUpdated when a page is added
114 // to the model. If the request failed, tell UI that the item is gone.
115 if (status == RequestNotifier::BackgroundSavePageResult::SUCCESS)
116 return;
117 DeleteItemHelper(request.client_id().id);
118 }
119
120 // RequestCoordinator::Observer
121 void DownloadUIAdapter::OnChanged(const SavePageRequest& request) {
122 if (!delegate_->IsVisibleInUI(request.client_id()))
123 return;
124
125 std::string guid = request.client_id().id;
126 items_[guid] = base::MakeUnique<ItemInfo>(request);
127
128 if (state_ != State::LOADED)
129 return;
130
131 const DownloadUIItem& download_ui_item = *(items_[guid]->ui_item);
106 for (Observer& observer : observers_) 132 for (Observer& observer : observers_)
107 observer.ItemDeleted(guid); 133 observer.ItemUpdated(download_ui_item);
134 }
135
136 void DownloadUIAdapter::TemporaryHiddenStatusChanged(
137 const ClientId& client_id) {
138 bool hidden = delegate_->IsTemporarilyHiddenInUI(client_id);
139
140 for (const auto& item : items_) {
141 if (item.second->client_id == client_id) {
142 if (item.second->temporarily_hidden == hidden)
143 continue;
144 item.second->temporarily_hidden = hidden;
145 if (hidden) {
146 for (Observer& observer : observers_)
147 observer.ItemDeleted(item.second->ui_item->guid);
148 } else {
149 for (Observer& observer : observers_)
150 observer.ItemAdded(*item.second->ui_item.get());
151 }
152 }
153 }
108 } 154 }
109 155
110 std::vector<const DownloadUIItem*> DownloadUIAdapter::GetAllItems() const { 156 std::vector<const DownloadUIItem*> DownloadUIAdapter::GetAllItems() const {
111 std::vector<const DownloadUIItem*> result; 157 std::vector<const DownloadUIItem*> result;
112 for (const auto& item : items_) 158 for (const auto& item : items_) {
159 if (delegate_->IsTemporarilyHiddenInUI(item.second->client_id))
160 continue;
113 result.push_back(item.second->ui_item.get()); 161 result.push_back(item.second->ui_item.get());
162 }
114 return result; 163 return result;
115 } 164 }
116 165
117 const DownloadUIItem* DownloadUIAdapter::GetItem( 166 const DownloadUIItem* DownloadUIAdapter::GetItem(
118 const std::string& guid) const { 167 const std::string& guid) const {
119 DownloadUIItems::const_iterator it = items_.find(guid); 168 DownloadUIItems::const_iterator it = items_.find(guid);
120 if (it == items_.end()) 169 if (it == items_.end() ||
170 delegate_->IsTemporarilyHiddenInUI(it->second->client_id)) {
121 return nullptr; 171 return nullptr;
172 }
122 return it->second->ui_item.get(); 173 return it->second->ui_item.get();
123 } 174 }
124 175
125 void DownloadUIAdapter::DeleteItem(const std::string& guid) { 176 void DownloadUIAdapter::DeleteItem(const std::string& guid) {
126 // TODO(dimich): Also remove pending request from RequestQueue.
127 DownloadUIItems::const_iterator it = items_.find(guid); 177 DownloadUIItems::const_iterator it = items_.find(guid);
128 if (it == items_.end()) 178 if (it == items_.end())
129 return; 179 return;
130 180
131 std::vector<int64_t> page_ids; 181 std::vector<int64_t> page_ids;
132 page_ids.push_back(it->second->offline_id); 182 page_ids.push_back(it->second->offline_id);
133 model_->DeletePagesByOfflineId( 183 model_->DeletePagesByOfflineId(
134 page_ids, base::Bind(&DownloadUIAdapter::OnDeletePagesDone, 184 page_ids, base::Bind(&DownloadUIAdapter::OnDeletePagesDone,
135 weak_ptr_factory_.GetWeakPtr())); 185 weak_ptr_factory_.GetWeakPtr()));
136 } 186 }
137 187
138 int64_t DownloadUIAdapter::GetOfflineIdByGuid(const std::string& guid) const { 188 int64_t DownloadUIAdapter::GetOfflineIdByGuid(const std::string& guid) const {
139 // TODO(dimich): when requests are also in the cache, filter them out.
140 // Requests do not yet have offline ID.
141 DownloadUIItems::const_iterator it = items_.find(guid); 189 DownloadUIItems::const_iterator it = items_.find(guid);
142 if (it != items_.end()) 190 if (it != items_.end())
143 return it->second->offline_id; 191 return it->second->offline_id;
144 return 0; 192 return 0;
145 } 193 }
146 194
147 // Note that several LoadCache calls may be issued before the async GetAllPages 195 // Note that several LoadCache calls may be issued before the async GetAllPages
148 // comes back. 196 // comes back.
149 void DownloadUIAdapter::LoadCache() { 197 void DownloadUIAdapter::LoadCache() {
150 // TODO(dimich): Add fetching from RequestQueue as well. 198 state_ = State::LOADING_PAGES;
151 state_ = State::LOADING;
152 model_->GetAllPages(base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded, 199 model_->GetAllPages(base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded,
153 weak_ptr_factory_.GetWeakPtr())); 200 weak_ptr_factory_.GetWeakPtr()));
154 } 201 }
155 202
156 void DownloadUIAdapter::ClearCache() { 203 void DownloadUIAdapter::ClearCache() {
157 // Once loaded, this class starts to observe the model. Only remove observer 204 // Once loaded, this class starts to observe the model. Only remove observer
158 // if it was added. 205 // if it was added.
159 if (state_ == State::LOADED) 206 if (state_ == State::LOADED)
160 model_->RemoveObserver(this); 207 model_->RemoveObserver(this);
161 items_.clear(); 208 items_.clear();
162 state_ = State::NOT_LOADED; 209 state_ = State::NOT_LOADED;
163 } 210 }
164 211
165 void DownloadUIAdapter::OnOfflinePagesLoaded( 212 void DownloadUIAdapter::OnOfflinePagesLoaded(
166 const MultipleOfflinePageItemResult& pages) { 213 const MultipleOfflinePageItemResult& pages) {
167 // If multiple observers register quickly, the cache might be already loaded 214 // If multiple observers register quickly, the cache might be already loaded
168 // by the previous LoadCache call. At the same time, if all observers already 215 // by the previous LoadCache call. At the same time, if all observers already
169 // left, there is no reason to populate the cache. 216 // left, there is no reason to populate the cache.
170 if (state_ != State::LOADING) 217 if (state_ != State::LOADING_PAGES)
171 return; 218 return;
172 for (const auto& page : pages) { 219 for (const auto& page : pages) {
173 if (IsVisibleInUI(page.client_id)) { 220 if (delegate_->IsVisibleInUI(page.client_id)) {
174 std::string guid = page.client_id.id; 221 std::string guid = page.client_id.id;
175 DCHECK(items_.find(guid) == items_.end()); 222 DCHECK(items_.find(guid) == items_.end());
176 items_[guid] = base::MakeUnique<ItemInfo>(page); 223 std::unique_ptr<ItemInfo> item = base::MakeUnique<ItemInfo>(page);
224 item->temporarily_hidden =
225 delegate_->IsTemporarilyHiddenInUI(page.client_id);
226 items_[guid] = std::move(item);
177 } 227 }
178 } 228 }
179 model_->AddObserver(this); 229 model_->AddObserver(this);
230
231 state_ = State::LOADING_REQUESTS;
232 request_coordinator_->GetAllRequests(base::Bind(
233 &DownloadUIAdapter::OnRequestsLoaded, weak_ptr_factory_.GetWeakPtr()));
234 }
235
236 void DownloadUIAdapter::OnRequestsLoaded(
237 std::vector<std::unique_ptr<SavePageRequest>> requests) {
238 // If multiple observers register quickly, the cache might be already loaded
239 // by the previous LoadCache call. At the same time, if all observers already
240 // left, there is no reason to populate the cache.
241 if (state_ != State::LOADING_REQUESTS)
242 return;
243
244 for (const auto& request : requests) {
245 if (delegate_->IsVisibleInUI(request->client_id())) {
246 std::string guid = request->client_id().id;
247 DCHECK(items_.find(guid) == items_.end());
248 std::unique_ptr<ItemInfo> item =
249 base::MakeUnique<ItemInfo>(*request.get());
250 item->temporarily_hidden =
251 delegate_->IsTemporarilyHiddenInUI(request->client_id());
252 items_[guid] = std::move(item);
253 }
254 }
255 request_coordinator_->AddObserver(this);
256
180 state_ = State::LOADED; 257 state_ = State::LOADED;
181 for (Observer& observer : observers_) 258 for (Observer& observer : observers_)
182 observer.ItemsLoaded(); 259 observer.ItemsLoaded();
183 } 260 }
184 261
185 void DownloadUIAdapter::NotifyItemsLoaded(Observer* observer) { 262 void DownloadUIAdapter::NotifyItemsLoaded(Observer* observer) {
186 if (observer && observers_.HasObserver(observer)) 263 if (observer && observers_.HasObserver(observer))
187 observer->ItemsLoaded(); 264 observer->ItemsLoaded();
188 } 265 }
189 266
190 267
191 void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) { 268 void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) {
192 // TODO(dimich): Consider adding UMA to record user actions. 269 // TODO(dimich): Consider adding UMA to record user actions.
193 } 270 }
194 271
195 bool DownloadUIAdapter::IsVisibleInUI(const ClientId& client_id) { 272 void DownloadUIAdapter::AddItemHelper(std::unique_ptr<ItemInfo> item_info) {
196 const std::string& name_space = client_id.name_space; 273 const std::string& guid = item_info->ui_item->guid;
197 return model_->GetPolicyController()->IsSupportedByDownload(name_space) && 274
198 base::IsValidGUID(client_id.id); 275 DownloadUIItems::const_iterator it = items_.find(guid);
276 // In case when request is completed and morphed into a page, this comes as
277 // new page added and request completed. We ignore request completion
278 // notification and when page is added, fire 'updated' instead of 'added'.
279 bool request_to_page_transition =
280 (it != items_.end() && it->second->is_request && !item_info->is_request);
281
282 items_[guid] = std::move(item_info);
283
284 if (state_ != State::LOADED)
285 return;
286
287 DownloadUIItem* download_ui_item = items_[guid]->ui_item.get();
288 if (request_to_page_transition) {
289 download_ui_item->download_state = DownloadUIItem::DownloadState::COMPLETE;
290 for (Observer& observer : observers_)
291 observer.ItemUpdated(*download_ui_item);
292 } else {
293 for (Observer& observer : observers_)
294 observer.ItemAdded(*download_ui_item);
295 }
296 }
297
298 void DownloadUIAdapter::DeleteItemHelper(const std::string& guid) {
299 DownloadUIItems::const_iterator it = items_.find(guid);
300 if (it == items_.end())
301 return;
302 items_.erase(it);
303
304 if (state_ != State::LOADED)
305 return;
306
307 for (Observer& observer : observers_)
308 observer.ItemDeleted(guid);
199 } 309 }
200 310
201 } // namespace offline_pages 311 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698