OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |