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

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: 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)),
23 is_request(false),
25 offline_id(page.offline_id) {} 24 offline_id(page.offline_id) {}
26 25
26 DownloadUIAdapter::ItemInfo::ItemInfo(const SavePageRequest& request)
27 : ui_item(base::MakeUnique<DownloadUIItem>(request)),
28 is_request(true),
29 offline_id(request.request_id()) {}
30
27 DownloadUIAdapter::ItemInfo::~ItemInfo() {} 31 DownloadUIAdapter::ItemInfo::~ItemInfo() {}
28 32
29 DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model) 33 DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model,
34 RequestCoordinator* request_coordinator,
35 std::unique_ptr<Delegate> delegate)
30 : model_(model), 36 : model_(model),
37 request_coordinator_(request_coordinator),
38 delegate_(std::move(delegate)),
31 state_(State::NOT_LOADED), 39 state_(State::NOT_LOADED),
32 observers_count_(0), 40 observers_count_(0),
33 weak_ptr_factory_(this) {} 41 weak_ptr_factory_(this) {}
34 42
35 DownloadUIAdapter::~DownloadUIAdapter() {} 43 DownloadUIAdapter::~DownloadUIAdapter() {}
36 44
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) { 45 void DownloadUIAdapter::AddObserver(Observer* observer) {
50 DCHECK(observer); 46 DCHECK(observer);
51 if (observers_.HasObserver(observer)) 47 if (observers_.HasObserver(observer))
52 return; 48 return;
53 if (observers_count_ == 0) 49 if (observers_count_ == 0)
54 LoadCache(); 50 LoadCache();
55 observers_.AddObserver(observer); 51 observers_.AddObserver(observer);
56 ++observers_count_; 52 ++observers_count_;
57 // If the items are already loaded, post the notification right away. 53 // 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. 54 // Don't just invoke it from here to avoid reentrancy in the client.
(...skipping 16 matching lines...) Expand all
75 ClearCache(); 71 ClearCache();
76 } 72 }
77 73
78 void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) { 74 void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) {
79 // This signal is not used here. 75 // This signal is not used here.
80 } 76 }
81 77
82 void DownloadUIAdapter::OfflinePageAdded(OfflinePageModel* model, 78 void DownloadUIAdapter::OfflinePageAdded(OfflinePageModel* model,
83 const OfflinePageItem& added_page) { 79 const OfflinePageItem& added_page) {
84 DCHECK(model == model_); 80 DCHECK(model == model_);
85 if (!IsVisibleInUI(added_page.client_id)) 81 if (!delegate_->IsVisibleInUI(added_page.client_id))
86 return; 82 return;
87 83
88 const std::string& guid = added_page.client_id.id; 84 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 } 85 }
96 86
97 void DownloadUIAdapter::OfflinePageDeleted(int64_t offline_id, 87 void DownloadUIAdapter::OfflinePageDeleted(int64_t offline_id,
98 const ClientId& client_id) { 88 const ClientId& client_id) {
99 if (!IsVisibleInUI(client_id)) 89 if (!delegate_->IsVisibleInUI(client_id))
100 return; 90 return;
101 std::string guid = client_id.id; 91 deleteItemHelper(client_id.id);
102 DownloadUIItems::const_iterator it = items_.find(guid); 92 }
103 if (it == items_.end()) 93
94 // RequestCoordinator::Observer
95 void DownloadUIAdapter::OnAdded(const SavePageRequest& added_request) {
96 if (!delegate_->IsVisibleInUI(added_request.client_id()))
104 return; 97 return;
105 items_.erase(it); 98
99 addItemHelper(base::MakeUnique<ItemInfo>(added_request));
100 }
101
102 // RequestCoordinator::Observer
103 void DownloadUIAdapter::OnCompleted(const SavePageRequest& request,
dewittj 2017/01/18 18:49:48 OK to do in future, but now that we have classes t
Dmitry Titov 2017/01/27 04:30:22 Acknowledged.
104 RequestNotifier::BackgroundSavePageResult status) {
105 if (!delegate_->IsVisibleInUI(request.client_id()))
106 return;
107
108 // If request completed sucecssfully, report ItemUpdated when a page is added
109 // to the model. If the request failed, tell UI that the item is gone.
110
111 if (status == RequestNotifier::BackgroundSavePageResult::SUCCESS)
112 return;
113 deleteItemHelper(request.client_id().id);
114 }
115
116 // RequestCoordinator::Observer
117 void DownloadUIAdapter::OnChanged(const SavePageRequest& request) {
118 if (!delegate_->IsVisibleInUI(request.client_id()))
119 return;
120
121 std::string guid = request.client_id().id;
122 items_[guid] = base::MakeUnique<ItemInfo>(request);
123
124 if (state_ != State::LOADED)
125 return;
126
127 const DownloadUIItem& download_ui_item = *(items_[guid]->ui_item);
106 for (Observer& observer : observers_) 128 for (Observer& observer : observers_)
107 observer.ItemDeleted(guid); 129 observer.ItemUpdated(download_ui_item);
108 } 130 }
109 131
110 std::vector<const DownloadUIItem*> DownloadUIAdapter::GetAllItems() const { 132 std::vector<const DownloadUIItem*> DownloadUIAdapter::GetAllItems() const {
111 std::vector<const DownloadUIItem*> result; 133 std::vector<const DownloadUIItem*> result;
112 for (const auto& item : items_) 134 for (const auto& item : items_)
113 result.push_back(item.second->ui_item.get()); 135 result.push_back(item.second->ui_item.get());
114 return result; 136 return result;
115 } 137 }
116 138
117 const DownloadUIItem* DownloadUIAdapter::GetItem( 139 const DownloadUIItem* DownloadUIAdapter::GetItem(
118 const std::string& guid) const { 140 const std::string& guid) const {
119 DownloadUIItems::const_iterator it = items_.find(guid); 141 DownloadUIItems::const_iterator it = items_.find(guid);
120 if (it == items_.end()) 142 if (it == items_.end())
121 return nullptr; 143 return nullptr;
122 return it->second->ui_item.get(); 144 return it->second->ui_item.get();
123 } 145 }
124 146
125 void DownloadUIAdapter::DeleteItem(const std::string& guid) { 147 void DownloadUIAdapter::DeleteItem(const std::string& guid) {
126 // TODO(dimich): Also remove pending request from RequestQueue.
127 DownloadUIItems::const_iterator it = items_.find(guid); 148 DownloadUIItems::const_iterator it = items_.find(guid);
128 if (it == items_.end()) 149 if (it == items_.end())
129 return; 150 return;
130 151
131 std::vector<int64_t> page_ids; 152 std::vector<int64_t> page_ids;
132 page_ids.push_back(it->second->offline_id); 153 page_ids.push_back(it->second->offline_id);
133 model_->DeletePagesByOfflineId( 154 model_->DeletePagesByOfflineId(
134 page_ids, base::Bind(&DownloadUIAdapter::OnDeletePagesDone, 155 page_ids, base::Bind(&DownloadUIAdapter::OnDeletePagesDone,
135 weak_ptr_factory_.GetWeakPtr())); 156 weak_ptr_factory_.GetWeakPtr()));
136 } 157 }
137 158
138 int64_t DownloadUIAdapter::GetOfflineIdByGuid(const std::string& guid) const { 159 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); 160 DownloadUIItems::const_iterator it = items_.find(guid);
142 if (it != items_.end()) 161 if (it != items_.end())
143 return it->second->offline_id; 162 return it->second->offline_id;
144 return 0; 163 return 0;
145 } 164 }
146 165
147 // Note that several LoadCache calls may be issued before the async GetAllPages 166 // Note that several LoadCache calls may be issued before the async GetAllPages
148 // comes back. 167 // comes back.
149 void DownloadUIAdapter::LoadCache() { 168 void DownloadUIAdapter::LoadCache() {
150 // TODO(dimich): Add fetching from RequestQueue as well. 169 state_ = State::LOADING_PAGES;
151 state_ = State::LOADING;
152 model_->GetAllPages(base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded, 170 model_->GetAllPages(base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded,
153 weak_ptr_factory_.GetWeakPtr())); 171 weak_ptr_factory_.GetWeakPtr()));
154 } 172 }
155 173
156 void DownloadUIAdapter::ClearCache() { 174 void DownloadUIAdapter::ClearCache() {
157 // Once loaded, this class starts to observe the model. Only remove observer 175 // Once loaded, this class starts to observe the model. Only remove observer
158 // if it was added. 176 // if it was added.
159 if (state_ == State::LOADED) 177 if (state_ == State::LOADED)
160 model_->RemoveObserver(this); 178 model_->RemoveObserver(this);
161 items_.clear(); 179 items_.clear();
162 state_ = State::NOT_LOADED; 180 state_ = State::NOT_LOADED;
163 } 181 }
164 182
165 void DownloadUIAdapter::OnOfflinePagesLoaded( 183 void DownloadUIAdapter::OnOfflinePagesLoaded(
166 const MultipleOfflinePageItemResult& pages) { 184 const MultipleOfflinePageItemResult& pages) {
167 // If multiple observers register quickly, the cache might be already loaded 185 // 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 186 // by the previous LoadCache call. At the same time, if all observers already
169 // left, there is no reason to populate the cache. 187 // left, there is no reason to populate the cache.
170 if (state_ != State::LOADING) 188 if (state_ != State::LOADING_PAGES)
171 return; 189 return;
172 for (const auto& page : pages) { 190 for (const auto& page : pages) {
173 if (IsVisibleInUI(page.client_id)) { 191 if (delegate_->IsVisibleInUI(page.client_id)) {
174 std::string guid = page.client_id.id; 192 std::string guid = page.client_id.id;
175 DCHECK(items_.find(guid) == items_.end()); 193 DCHECK(items_.find(guid) == items_.end());
176 items_[guid] = base::MakeUnique<ItemInfo>(page); 194 items_[guid] = base::MakeUnique<ItemInfo>(page);
177 } 195 }
178 } 196 }
179 model_->AddObserver(this); 197 model_->AddObserver(this);
198
199 state_ = State::LOADING_REQUESTS;
200 request_coordinator_->GetAllRequests(
201 base::Bind(&DownloadUIAdapter::OnRequestsLoaded,
202 weak_ptr_factory_.GetWeakPtr()));
203 }
204
205 void DownloadUIAdapter::OnRequestsLoaded(
206 std::vector<std::unique_ptr<SavePageRequest>> requests) {
207 // If multiple observers register quickly, the cache might be already loaded
208 // by the previous LoadCache call. At the same time, if all observers already
209 // left, there is no reason to populate the cache.
210 if (state_ != State::LOADING_REQUESTS)
211 return;
212
213 for (const auto& request : requests) {
214 if (delegate_->IsVisibleInUI(request->client_id())) {
215 std::string guid = request->client_id().id;
216 DCHECK(items_.find(guid) == items_.end());
217 items_[guid] = base::MakeUnique<ItemInfo>(*request.get());
218 }
219 }
220 request_coordinator_->AddObserver(this);
221
180 state_ = State::LOADED; 222 state_ = State::LOADED;
181 for (Observer& observer : observers_) 223 for (Observer& observer : observers_)
182 observer.ItemsLoaded(); 224 observer.ItemsLoaded();
183 } 225 }
184 226
185 void DownloadUIAdapter::NotifyItemsLoaded(Observer* observer) { 227 void DownloadUIAdapter::NotifyItemsLoaded(Observer* observer) {
186 if (observer && observers_.HasObserver(observer)) 228 if (observer && observers_.HasObserver(observer))
187 observer->ItemsLoaded(); 229 observer->ItemsLoaded();
188 } 230 }
189 231
190 232
191 void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) { 233 void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) {
192 // TODO(dimich): Consider adding UMA to record user actions. 234 // TODO(dimich): Consider adding UMA to record user actions.
193 } 235 }
194 236
195 bool DownloadUIAdapter::IsVisibleInUI(const ClientId& client_id) { 237 void DownloadUIAdapter::addItemHelper(std::unique_ptr<ItemInfo> item_info) {
196 const std::string& name_space = client_id.name_space; 238 const std::string& guid = item_info->ui_item->guid;
197 return model_->GetPolicyController()->IsSupportedByDownload(name_space) && 239
198 base::IsValidGUID(client_id.id); 240 DownloadUIItems::const_iterator it = items_.find(guid);
241 // In case when request is completed and morphed into a page, this comes as
242 // new page added and request completed. We ignore request completion
243 // notification and when page is added, fire 'updated' instead of 'added'.
244 bool request_to_page_transition = (it != items_.end() &&
245 it->second->is_request && !item_info->is_request);
246
247 items_[guid] = std::move(item_info);
248
249 if (state_ != State::LOADED)
250 return;
251
252 const DownloadUIItem& download_ui_item = *(items_[guid]->ui_item);
253 if (request_to_page_transition) {
254 for (Observer& observer : observers_)
255 observer.ItemUpdated(download_ui_item);
256 } else {
257 for (Observer& observer : observers_)
258 observer.ItemAdded(download_ui_item);
259 }
260 }
261
262 void DownloadUIAdapter::deleteItemHelper(const std::string& guid) {
263 DownloadUIItems::const_iterator it = items_.find(guid);
264 if (it == items_.end())
265 return;
266 items_.erase(it);
267
268 if (state_ != State::LOADED)
269 return;
270
271 for (Observer& observer : observers_)
272 observer.ItemDeleted(guid);
273
199 } 274 }
200 275
201 } // namespace offline_pages 276 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698