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

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: feedback, test compile Created 3 years, 11 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(const SavePageRequest& request,
108 RequestNotifier::BackgroundSavePageResult status) {
fgorski 2017/01/20 17:03:01 nit: git cl format
Dmitry Titov 2017/01/27 04:26:24 Done.
109 if (!delegate_->IsVisibleInUI(request.client_id()))
110 return;
111
112 // If request completed sucecssfully, report ItemUpdated when a page is added
113 // to the model. If the request failed, tell UI that the item is gone.
114
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::OnTemporaryHidenStatusChanged(
137 const ClientId& client_id, bool hidden) {
138 // Generate ItemAdded/ItemDeleted notifications when items change their
139 // hidden status.
140
141 // Sanity check. The items that are not visible in UI can not be temporarily
142 // hidden.
143 DCHECK(delegate_->IsVisibleInUI(client_id));
144
145 for (const auto& item : items_) {
146 if (item.second->client_id == client_id) {
147 if (item.second->temporarily_hidden == hidden)
148 continue;
149 item.second->temporarily_hidden = hidden;
150 if (hidden) {
151 for (Observer& observer : observers_)
152 observer.ItemDeleted(item.second->ui_item->guid);
153 } else {
154 for (Observer& observer : observers_)
155 observer.ItemAdded(*item.second->ui_item.get());
156 }
157 }
158 }
108 } 159 }
109 160
110 std::vector<const DownloadUIItem*> DownloadUIAdapter::GetAllItems() const { 161 std::vector<const DownloadUIItem*> DownloadUIAdapter::GetAllItems() const {
111 std::vector<const DownloadUIItem*> result; 162 std::vector<const DownloadUIItem*> result;
112 for (const auto& item : items_) 163 for (const auto& item : items_)
113 result.push_back(item.second->ui_item.get()); 164 result.push_back(item.second->ui_item.get());
114 return result; 165 return result;
115 } 166 }
116 167
117 const DownloadUIItem* DownloadUIAdapter::GetItem( 168 const DownloadUIItem* DownloadUIAdapter::GetItem(
118 const std::string& guid) const { 169 const std::string& guid) const {
119 DownloadUIItems::const_iterator it = items_.find(guid); 170 DownloadUIItems::const_iterator it = items_.find(guid);
120 if (it == items_.end()) 171 if (it == items_.end())
121 return nullptr; 172 return nullptr;
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 items_[guid] = base::MakeUnique<ItemInfo>(page);
177 } 224 }
178 } 225 }
179 model_->AddObserver(this); 226 model_->AddObserver(this);
227
228 state_ = State::LOADING_REQUESTS;
229 request_coordinator_->GetAllRequests(
230 base::Bind(&DownloadUIAdapter::OnRequestsLoaded,
231 weak_ptr_factory_.GetWeakPtr()));
232 }
233
234 void DownloadUIAdapter::OnRequestsLoaded(
235 std::vector<std::unique_ptr<SavePageRequest>> requests) {
236 // If multiple observers register quickly, the cache might be already loaded
237 // by the previous LoadCache call. At the same time, if all observers already
238 // left, there is no reason to populate the cache.
239 if (state_ != State::LOADING_REQUESTS)
240 return;
241
242 for (const auto& request : requests) {
243 if (delegate_->IsVisibleInUI(request->client_id())) {
244 std::string guid = request->client_id().id;
245 DCHECK(items_.find(guid) == items_.end());
246 items_[guid] = base::MakeUnique<ItemInfo>(*request.get());
247 }
248 }
249 request_coordinator_->AddObserver(this);
250
180 state_ = State::LOADED; 251 state_ = State::LOADED;
181 for (Observer& observer : observers_) 252 for (Observer& observer : observers_)
182 observer.ItemsLoaded(); 253 observer.ItemsLoaded();
183 } 254 }
184 255
185 void DownloadUIAdapter::NotifyItemsLoaded(Observer* observer) { 256 void DownloadUIAdapter::NotifyItemsLoaded(Observer* observer) {
186 if (observer && observers_.HasObserver(observer)) 257 if (observer && observers_.HasObserver(observer))
187 observer->ItemsLoaded(); 258 observer->ItemsLoaded();
188 } 259 }
189 260
190 261
191 void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) { 262 void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) {
192 // TODO(dimich): Consider adding UMA to record user actions. 263 // TODO(dimich): Consider adding UMA to record user actions.
193 } 264 }
194 265
195 bool DownloadUIAdapter::IsVisibleInUI(const ClientId& client_id) { 266 void DownloadUIAdapter::addItemHelper(std::unique_ptr<ItemInfo> item_info) {
196 const std::string& name_space = client_id.name_space; 267 const std::string& guid = item_info->ui_item->guid;
197 return model_->GetPolicyController()->IsSupportedByDownload(name_space) && 268
198 base::IsValidGUID(client_id.id); 269 DownloadUIItems::const_iterator it = items_.find(guid);
270 // In case when request is completed and morphed into a page, this comes as
271 // new page added and request completed. We ignore request completion
272 // notification and when page is added, fire 'updated' instead of 'added'.
273 bool request_to_page_transition = (it != items_.end() &&
274 it->second->is_request && !item_info->is_request);
275
276 items_[guid] = std::move(item_info);
277
278 if (state_ != State::LOADED)
279 return;
280
281 const DownloadUIItem& download_ui_item = *(items_[guid]->ui_item);
282 if (request_to_page_transition) {
283 for (Observer& observer : observers_)
284 observer.ItemUpdated(download_ui_item);
285 } else {
286 for (Observer& observer : observers_)
287 observer.ItemAdded(download_ui_item);
288 }
289 }
290
291 void DownloadUIAdapter::deleteItemHelper(const std::string& guid) {
292 DownloadUIItems::const_iterator it = items_.find(guid);
293 if (it == items_.end())
294 return;
295 items_.erase(it);
296
297 if (state_ != State::LOADED)
298 return;
299
300 for (Observer& observer : observers_)
301 observer.ItemDeleted(guid);
302
fgorski 2017/01/20 17:03:01 nit: remove empty line.
Dmitry Titov 2017/01/27 04:26:24 Done.
199 } 303 }
200 304
201 } // namespace offline_pages 305 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698