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

Side by Side Diff: components/ntp_snippets/offline_pages/offline_page_suggestions_provider.cc

Issue 2251743002: Refactor OfflinePageSuggestionsProvider dismissed ID handling (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@offlinedelete
Patch Set: Fire OnSuggestionInvalidated even if previously dismissed Created 4 years, 4 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/ntp_snippets/offline_pages/offline_page_suggestions_provide r.h" 5 #include "components/ntp_snippets/offline_pages/offline_page_suggestions_provide r.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/guid.h" 10 #include "base/guid.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 ? CategoryStatus::AVAILABLE_LOADING 53 ? CategoryStatus::AVAILABLE_LOADING
54 : CategoryStatus::NOT_PROVIDED), 54 : CategoryStatus::NOT_PROVIDED),
55 downloads_status_(downloads_enabled ? CategoryStatus::AVAILABLE_LOADING 55 downloads_status_(downloads_enabled ? CategoryStatus::AVAILABLE_LOADING
56 : CategoryStatus::NOT_PROVIDED), 56 : CategoryStatus::NOT_PROVIDED),
57 offline_page_model_(offline_page_model), 57 offline_page_model_(offline_page_model),
58 recent_tabs_category_( 58 recent_tabs_category_(
59 category_factory->FromKnownCategory(KnownCategories::RECENT_TABS)), 59 category_factory->FromKnownCategory(KnownCategories::RECENT_TABS)),
60 downloads_category_( 60 downloads_category_(
61 category_factory->FromKnownCategory(KnownCategories::DOWNLOADS)), 61 category_factory->FromKnownCategory(KnownCategories::DOWNLOADS)),
62 pref_service_(pref_service), 62 pref_service_(pref_service),
63 dismissed_recent_tab_ids_(ReadDismissedIDsFromPrefs(
64 prefs::kDismissedRecentOfflineTabSuggestions)),
65 dismissed_download_ids_(
66 ReadDismissedIDsFromPrefs(prefs::kDismissedDownloadSuggestions)),
67 download_manager_ui_enabled_(download_manager_ui_enabled) { 63 download_manager_ui_enabled_(download_manager_ui_enabled) {
68 DCHECK(recent_tabs_enabled || downloads_enabled); 64 DCHECK(recent_tabs_enabled || downloads_enabled);
69 offline_page_model_->AddObserver(this); 65 offline_page_model_->AddObserver(this);
70 FetchOfflinePages(); 66 FetchOfflinePages();
71 } 67 }
72 68
73 OfflinePageSuggestionsProvider::~OfflinePageSuggestionsProvider() { 69 OfflinePageSuggestionsProvider::~OfflinePageSuggestionsProvider() {
74 offline_page_model_->RemoveObserver(this); 70 offline_page_model_->RemoveObserver(this);
75 } 71 }
76 72
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 NOTREACHED() << "Unknown category " << category.id(); 116 NOTREACHED() << "Unknown category " << category.id();
121 return CategoryInfo(base::string16(), 117 return CategoryInfo(base::string16(),
122 ContentSuggestionsCardLayout::MINIMAL_CARD, 118 ContentSuggestionsCardLayout::MINIMAL_CARD,
123 /* has_more_button */ false); 119 /* has_more_button */ false);
124 } 120 }
125 121
126 void OfflinePageSuggestionsProvider::DismissSuggestion( 122 void OfflinePageSuggestionsProvider::DismissSuggestion(
127 const std::string& suggestion_id) { 123 const std::string& suggestion_id) {
128 Category category = GetCategoryFromUniqueID(suggestion_id); 124 Category category = GetCategoryFromUniqueID(suggestion_id);
129 std::string offline_page_id = GetWithinCategoryIDFromUniqueID(suggestion_id); 125 std::string offline_page_id = GetWithinCategoryIDFromUniqueID(suggestion_id);
130 if (category == recent_tabs_category_) { 126 std::set<std::string> dismissed_ids = ReadDismissedIDsFromPrefs(category);
131 DCHECK_NE(CategoryStatus::NOT_PROVIDED, recent_tabs_status_); 127 dismissed_ids.insert(offline_page_id);
132 dismissed_recent_tab_ids_.insert(offline_page_id); 128 StoreDismissedIDsToPrefs(category, dismissed_ids);
133 StoreDismissedIDsToPrefs(prefs::kDismissedRecentOfflineTabSuggestions,
134 dismissed_recent_tab_ids_);
135 } else if (category == downloads_category_) {
136 DCHECK_NE(CategoryStatus::NOT_PROVIDED, downloads_status_);
137 dismissed_download_ids_.insert(offline_page_id);
138 StoreDismissedIDsToPrefs(prefs::kDismissedDownloadSuggestions,
139 dismissed_download_ids_);
140 } else {
141 NOTREACHED() << "Unknown category " << category.id();
142 }
143 } 129 }
144 130
145 void OfflinePageSuggestionsProvider::FetchSuggestionImage( 131 void OfflinePageSuggestionsProvider::FetchSuggestionImage(
146 const std::string& suggestion_id, 132 const std::string& suggestion_id,
147 const ImageFetchedCallback& callback) { 133 const ImageFetchedCallback& callback) {
148 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available 134 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available
149 // there. 135 // there.
150 base::ThreadTaskRunnerHandle::Get()->PostTask( 136 base::ThreadTaskRunnerHandle::Get()->PostTask(
151 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image())); 137 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image()));
152 } 138 }
153 139
154 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging( 140 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging(
155 Category category) { 141 Category category) {
156 // Ignored. 142 // Ignored.
157 } 143 }
158 144
159 std::vector<ContentSuggestion> 145 std::vector<ContentSuggestion>
160 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging( 146 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging(
161 Category category) { 147 Category category) {
162 // TODO(pke): Make GetDismissedSuggestionsForDebugging asynchronous so this 148 // TODO(pke): Make GetDismissedSuggestionsForDebugging asynchronous so this
163 // can return proper values. 149 // can return proper values.
150 std::set<std::string> dismissed_ids = ReadDismissedIDsFromPrefs(category);
164 std::vector<ContentSuggestion> suggestions; 151 std::vector<ContentSuggestion> suggestions;
165 const std::set<std::string>* dismissed_ids = nullptr; 152 for (const std::string& dismissed_id : dismissed_ids) {
166 if (category == recent_tabs_category_) {
167 DCHECK_NE(CategoryStatus::NOT_PROVIDED, recent_tabs_status_);
168 dismissed_ids = &dismissed_recent_tab_ids_;
169 } else if (category == downloads_category_) {
170 DCHECK_NE(CategoryStatus::NOT_PROVIDED, downloads_status_);
171 dismissed_ids = &dismissed_download_ids_;
172 } else {
173 NOTREACHED() << "Unknown category " << category.id();
174 return suggestions;
175 }
176
177 for (const std::string& dismissed_id : *dismissed_ids) {
178 ContentSuggestion suggestion( 153 ContentSuggestion suggestion(
179 MakeUniqueID(category, dismissed_id), 154 MakeUniqueID(category, dismissed_id),
180 GURL("http://dismissed-offline-page-" + dismissed_id)); 155 GURL("http://dismissed-offline-page-" + dismissed_id));
181 suggestion.set_title(base::UTF8ToUTF16("Title not available")); 156 suggestion.set_title(base::UTF8ToUTF16("Title not available"));
182 suggestions.push_back(std::move(suggestion)); 157 suggestions.push_back(std::move(suggestion));
183 } 158 }
184 return suggestions; 159 return suggestions;
185 } 160 }
186 161
187 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging( 162 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
188 Category category) { 163 Category category) {
189 if (category == recent_tabs_category_) { 164 StoreDismissedIDsToPrefs(category, std::set<std::string>());
190 DCHECK_NE(CategoryStatus::NOT_PROVIDED, recent_tabs_status_);
191 dismissed_recent_tab_ids_.clear();
192 StoreDismissedIDsToPrefs(prefs::kDismissedRecentOfflineTabSuggestions,
193 dismissed_recent_tab_ids_);
194 } else if (category == downloads_category_) {
195 DCHECK_NE(CategoryStatus::NOT_PROVIDED, downloads_status_);
196 dismissed_download_ids_.clear();
197 StoreDismissedIDsToPrefs(prefs::kDismissedDownloadSuggestions,
198 dismissed_download_ids_);
199 } else {
200 NOTREACHED() << "Unknown category " << category.id();
201 }
202 FetchOfflinePages(); 165 FetchOfflinePages();
203 } 166 }
204 167
205 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded( 168 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded(
206 OfflinePageModel* model) { 169 OfflinePageModel* model) {
207 DCHECK_EQ(offline_page_model_, model); 170 DCHECK_EQ(offline_page_model_, model);
208 } 171 }
209 172
210 void OfflinePageSuggestionsProvider::OfflinePageModelChanged( 173 void OfflinePageSuggestionsProvider::OfflinePageModelChanged(
211 OfflinePageModel* model) { 174 OfflinePageModel* model) {
212 DCHECK_EQ(offline_page_model_, model); 175 DCHECK_EQ(offline_page_model_, model);
213 FetchOfflinePages(); 176 FetchOfflinePages();
214 } 177 }
215 178
216 void OfflinePageSuggestionsProvider::OfflinePageDeleted( 179 void OfflinePageSuggestionsProvider::OfflinePageDeleted(
217 int64_t offline_id, 180 int64_t offline_id,
218 const offline_pages::ClientId& client_id) { 181 const offline_pages::ClientId& client_id) {
219 std::string offline_page_id = base::IntToString(offline_id);
220 if (recent_tabs_status_ != CategoryStatus::NOT_PROVIDED && 182 if (recent_tabs_status_ != CategoryStatus::NOT_PROVIDED &&
221 client_id.name_space == offline_pages::kLastNNamespace) { 183 client_id.name_space == offline_pages::kLastNNamespace) {
222 auto it = std::find(dismissed_recent_tab_ids_.begin(), 184 InvalidateSuggestion(recent_tabs_category_, offline_id);
223 dismissed_recent_tab_ids_.end(), offline_page_id);
224 if (it == dismissed_recent_tab_ids_.end()) {
225 observer()->OnSuggestionInvalidated(
226 this, recent_tabs_category_,
227 MakeUniqueID(recent_tabs_category_, offline_page_id));
228 } else {
229 dismissed_recent_tab_ids_.erase(it);
230 StoreDismissedIDsToPrefs(prefs::kDismissedRecentOfflineTabSuggestions,
231 dismissed_recent_tab_ids_);
232 }
233 } else if (downloads_status_ != CategoryStatus::NOT_PROVIDED && 185 } else if (downloads_status_ != CategoryStatus::NOT_PROVIDED &&
234 client_id.name_space == offline_pages::kAsyncNamespace && 186 client_id.name_space == offline_pages::kAsyncNamespace &&
235 base::IsValidGUID(client_id.id)) { 187 base::IsValidGUID(client_id.id)) {
236 auto it = std::find(dismissed_download_ids_.begin(), 188 InvalidateSuggestion(downloads_category_, offline_id);
237 dismissed_download_ids_.end(), offline_page_id);
238 if (it == dismissed_download_ids_.end()) {
239 observer()->OnSuggestionInvalidated(
240 this, downloads_category_,
241 MakeUniqueID(downloads_category_, offline_page_id));
242 } else {
243 dismissed_download_ids_.erase(it);
244 StoreDismissedIDsToPrefs(prefs::kDismissedDownloadSuggestions,
245 dismissed_download_ids_);
246 }
247 } 189 }
248 } 190 }
249 191
250 void OfflinePageSuggestionsProvider::FetchOfflinePages() { 192 void OfflinePageSuggestionsProvider::FetchOfflinePages() {
251 offline_page_model_->GetAllPages( 193 offline_page_model_->GetAllPages(
252 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded, 194 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded,
253 base::Unretained(this))); 195 base::Unretained(this)));
254 } 196 }
255 197
256 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded( 198 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded(
257 const MultipleOfflinePageItemResult& result) { 199 const MultipleOfflinePageItemResult& result) {
258 bool need_recent_tabs = recent_tabs_status_ != CategoryStatus::NOT_PROVIDED; 200 bool need_recent_tabs = recent_tabs_status_ != CategoryStatus::NOT_PROVIDED;
259 bool need_downloads = downloads_status_ != CategoryStatus::NOT_PROVIDED; 201 bool need_downloads = downloads_status_ != CategoryStatus::NOT_PROVIDED;
260 if (need_recent_tabs) 202 if (need_recent_tabs)
261 NotifyStatusChanged(recent_tabs_category_, CategoryStatus::AVAILABLE); 203 NotifyStatusChanged(recent_tabs_category_, CategoryStatus::AVAILABLE);
262 if (need_downloads) 204 if (need_downloads)
263 NotifyStatusChanged(downloads_category_, CategoryStatus::AVAILABLE); 205 NotifyStatusChanged(downloads_category_, CategoryStatus::AVAILABLE);
264 206
207 std::set<std::string> dismissed_recent_tab_ids =
208 ReadDismissedIDsFromPrefs(recent_tabs_category_);
209 std::set<std::string> dismissed_download_ids =
210 ReadDismissedIDsFromPrefs(downloads_category_);
265 std::vector<const OfflinePageItem*> recent_tab_items; 211 std::vector<const OfflinePageItem*> recent_tab_items;
266 std::vector<const OfflinePageItem*> download_items; 212 std::vector<const OfflinePageItem*> download_items;
267 for (const OfflinePageItem& item : result) { 213 for (const OfflinePageItem& item : result) {
268 if (need_recent_tabs && 214 if (need_recent_tabs &&
269 item.client_id.name_space == offline_pages::kLastNNamespace && 215 item.client_id.name_space == offline_pages::kLastNNamespace &&
270 !dismissed_recent_tab_ids_.count(base::IntToString(item.offline_id))) { 216 !dismissed_recent_tab_ids.count(base::IntToString(item.offline_id))) {
271 recent_tab_items.push_back(&item); 217 recent_tab_items.push_back(&item);
272 } 218 }
273 219
274 // TODO(pke): Use kDownloadNamespace once the OfflinePageModel uses that. 220 // TODO(pke): Use kDownloadNamespace once the OfflinePageModel uses that.
275 // The current logic is taken from DownloadUIAdapter::IsVisibleInUI. 221 // The current logic is taken from DownloadUIAdapter::IsVisibleInUI.
276 // Note: This is also copied in OfflinePageDeleted above. 222 // Note: This is also copied in OfflinePageDeleted above.
277 if (need_downloads && 223 if (need_downloads &&
278 item.client_id.name_space == offline_pages::kAsyncNamespace && 224 item.client_id.name_space == offline_pages::kAsyncNamespace &&
279 base::IsValidGUID(item.client_id.id) && 225 base::IsValidGUID(item.client_id.id) &&
280 !dismissed_download_ids_.count(base::IntToString(item.offline_id))) { 226 !dismissed_download_ids.count(base::IntToString(item.offline_id))) {
281 download_items.push_back(&item); 227 download_items.push_back(&item);
282 } 228 }
283 } 229 }
284 230
285 // TODO(pke): Once we have our OfflinePageModel getter and that doesn't do it 231 // TODO(pke): Once we have our OfflinePageModel getter and that doesn't do it
286 // already, filter out duplicate URLs for recent tabs here. Duplicates for 232 // already, filter out duplicate URLs for recent tabs here. Duplicates for
287 // downloads are fine. 233 // downloads are fine.
288 234
289 if (need_recent_tabs) { 235 if (need_recent_tabs) {
290 observer()->OnNewSuggestions( 236 observer()->OnNewSuggestions(
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 OrderByMostRecentlyVisited()); 295 OrderByMostRecentlyVisited());
350 std::vector<ContentSuggestion> suggestions; 296 std::vector<ContentSuggestion> suggestions;
351 for (const OfflinePageItem* offline_page_item : offline_page_items) { 297 for (const OfflinePageItem* offline_page_item : offline_page_items) {
352 suggestions.push_back(ConvertOfflinePage(category, *offline_page_item)); 298 suggestions.push_back(ConvertOfflinePage(category, *offline_page_item));
353 if (suggestions.size() == kMaxSuggestionsCount) 299 if (suggestions.size() == kMaxSuggestionsCount)
354 break; 300 break;
355 } 301 }
356 return suggestions; 302 return suggestions;
357 } 303 }
358 304
305 void OfflinePageSuggestionsProvider::InvalidateSuggestion(Category category,
306 int64_t offline_id) {
307 std::string offline_page_id = base::IntToString(offline_id);
308 observer()->OnSuggestionInvalidated(this, category,
309 MakeUniqueID(category, offline_page_id));
310
311 std::set<std::string> dismissed_ids = ReadDismissedIDsFromPrefs(category);
312 auto it =
313 std::find(dismissed_ids.begin(), dismissed_ids.end(), offline_page_id);
314 if (it != dismissed_ids.end()) {
315 dismissed_ids.erase(it);
316 StoreDismissedIDsToPrefs(category, dismissed_ids);
317 }
318 }
319
320 std::string OfflinePageSuggestionsProvider::GetDismissedPref(
321 Category category) const {
322 if (category == recent_tabs_category_) {
323 return prefs::kDismissedRecentOfflineTabSuggestions;
324 } else if (category == downloads_category_) {
Marc Treib 2016/08/16 11:45:17 no else after return
Philipp Keck 2016/08/16 12:04:01 Done.
325 return prefs::kDismissedDownloadSuggestions;
326 } else {
327 NOTREACHED() << "Unknown category " << category.id();
328 return std::string();
329 }
330 }
331
359 std::set<std::string> OfflinePageSuggestionsProvider::ReadDismissedIDsFromPrefs( 332 std::set<std::string> OfflinePageSuggestionsProvider::ReadDismissedIDsFromPrefs(
360 const std::string& pref_name) const { 333 Category category) const {
361 std::set<std::string> dismissed_ids; 334 std::set<std::string> dismissed_ids;
362 const base::ListValue* list = pref_service_->GetList(pref_name); 335 const base::ListValue* list =
336 pref_service_->GetList(GetDismissedPref(category));
363 for (const std::unique_ptr<base::Value>& value : *list) { 337 for (const std::unique_ptr<base::Value>& value : *list) {
364 std::string dismissed_id; 338 std::string dismissed_id;
365 bool success = value->GetAsString(&dismissed_id); 339 bool success = value->GetAsString(&dismissed_id);
366 DCHECK(success) << "Failed to parse dismissed offline page ID from prefs"; 340 DCHECK(success) << "Failed to parse dismissed offline page ID from prefs";
367 dismissed_ids.insert(dismissed_id); 341 dismissed_ids.insert(dismissed_id);
368 } 342 }
369 return dismissed_ids; 343 return dismissed_ids;
370 } 344 }
371 345
372 void OfflinePageSuggestionsProvider::StoreDismissedIDsToPrefs( 346 void OfflinePageSuggestionsProvider::StoreDismissedIDsToPrefs(
373 const std::string& pref_name, 347 Category category,
374 const std::set<std::string>& dismissed_ids) { 348 const std::set<std::string>& dismissed_ids) {
375 base::ListValue list; 349 base::ListValue list;
376 for (const std::string& dismissed_id : dismissed_ids) 350 for (const std::string& dismissed_id : dismissed_ids)
377 list.AppendString(dismissed_id); 351 list.AppendString(dismissed_id);
378 pref_service_->Set(pref_name, list); 352 pref_service_->Set(GetDismissedPref(category), list);
379 } 353 }
380 354
381 } // namespace ntp_snippets 355 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698