Chromium Code Reviews| 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> | |
| 8 | |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/location.h" | 10 #include "base/location.h" |
| 9 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 11 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
| 12 #include "base/values.h" | 14 #include "base/values.h" |
| 13 #include "components/ntp_snippets/pref_names.h" | 15 #include "components/ntp_snippets/pref_names.h" |
| 16 #include "components/offline_pages/client_namespace_constants.h" | |
| 14 #include "components/prefs/pref_registry_simple.h" | 17 #include "components/prefs/pref_registry_simple.h" |
| 15 #include "components/prefs/pref_service.h" | 18 #include "components/prefs/pref_service.h" |
| 19 #include "grit/components_strings.h" | |
| 20 #include "ui/base/l10n/l10n_util.h" | |
| 16 #include "ui/gfx/image/image.h" | 21 #include "ui/gfx/image/image.h" |
| 17 | 22 |
| 18 using offline_pages::MultipleOfflinePageItemResult; | 23 using offline_pages::MultipleOfflinePageItemResult; |
| 19 using offline_pages::OfflinePageModel; | 24 using offline_pages::OfflinePageModel; |
| 20 using offline_pages::OfflinePageItem; | 25 using offline_pages::OfflinePageItem; |
| 21 | 26 |
| 22 namespace ntp_snippets { | 27 namespace ntp_snippets { |
| 23 | 28 |
| 24 namespace { | 29 namespace { |
| 25 | 30 |
| 26 const int kMaxSuggestionsCount = 5; | 31 const int kMaxSuggestionsCount = 5; |
| 27 | 32 |
| 33 struct { | |
| 34 bool operator()(const OfflinePageItem* left, | |
| 35 const OfflinePageItem* right) const { | |
| 36 return left->last_access_time > right->last_access_time; | |
| 37 } | |
| 38 } OrderByMostRecentlyVisited; | |
|
Marc Treib
2016/08/12 10:12:53
This instantiates one global instance of the (unna
Philipp Keck
2016/08/12 10:22:55
This is from example code of std::sort. Otherwise,
Bernhard Bauer
2016/08/12 10:28:31
Is that going to create a static initializer? If s
Philipp Keck
2016/08/12 11:02:25
Done.
| |
| 39 | |
| 28 } // namespace | 40 } // namespace |
| 29 | 41 |
| 30 OfflinePageSuggestionsProvider::OfflinePageSuggestionsProvider( | 42 OfflinePageSuggestionsProvider::OfflinePageSuggestionsProvider( |
| 43 bool recent_tabs_enabled, | |
| 44 bool downloads_enabled, | |
| 31 ContentSuggestionsProvider::Observer* observer, | 45 ContentSuggestionsProvider::Observer* observer, |
| 32 CategoryFactory* category_factory, | 46 CategoryFactory* category_factory, |
| 33 OfflinePageModel* offline_page_model, | 47 OfflinePageModel* offline_page_model, |
| 34 PrefService* pref_service) | 48 PrefService* pref_service) |
| 35 : ContentSuggestionsProvider(observer, category_factory), | 49 : ContentSuggestionsProvider(observer, category_factory), |
| 36 category_status_(CategoryStatus::AVAILABLE_LOADING), | 50 recent_tabs_status_(recent_tabs_enabled |
| 51 ? CategoryStatus::AVAILABLE_LOADING | |
| 52 : CategoryStatus::NOT_PROVIDED), | |
| 53 downloads_status_(downloads_enabled ? CategoryStatus::AVAILABLE_LOADING | |
| 54 : CategoryStatus::NOT_PROVIDED), | |
| 37 offline_page_model_(offline_page_model), | 55 offline_page_model_(offline_page_model), |
| 38 provided_category_( | 56 recent_tabs_category_( |
| 39 category_factory->FromKnownCategory(KnownCategories::OFFLINE_PAGES)), | 57 category_factory->FromKnownCategory(KnownCategories::RECENT_TABS)), |
| 40 pref_service_(pref_service) { | 58 downloads_category_( |
| 59 category_factory->FromKnownCategory(KnownCategories::DOWNLOADS)), | |
| 60 pref_service_(pref_service), | |
| 61 dismissed_recent_tab_ids_(ReadDismissedIDsFromPrefs( | |
| 62 prefs::kDismissedRecentOfflineTabSuggestions)), | |
| 63 dismissed_download_ids_( | |
| 64 ReadDismissedIDsFromPrefs(prefs::kDismissedDownloadSuggestions)) { | |
| 65 DCHECK(recent_tabs_enabled || downloads_enabled); | |
| 41 offline_page_model_->AddObserver(this); | 66 offline_page_model_->AddObserver(this); |
| 42 ReadDismissedIDsFromPrefs(); | |
| 43 FetchOfflinePages(); | 67 FetchOfflinePages(); |
| 44 } | 68 } |
| 45 | 69 |
| 46 OfflinePageSuggestionsProvider::~OfflinePageSuggestionsProvider() { | 70 OfflinePageSuggestionsProvider::~OfflinePageSuggestionsProvider() { |
| 47 offline_page_model_->RemoveObserver(this); | 71 offline_page_model_->RemoveObserver(this); |
| 48 } | 72 } |
| 49 | 73 |
| 50 // static | 74 // static |
| 51 void OfflinePageSuggestionsProvider::RegisterProfilePrefs( | 75 void OfflinePageSuggestionsProvider::RegisterProfilePrefs( |
| 52 PrefRegistrySimple* registry) { | 76 PrefRegistrySimple* registry) { |
| 53 registry->RegisterListPref(prefs::kDismissedOfflinePageSuggestions); | 77 registry->RegisterListPref(prefs::kDismissedRecentOfflineTabSuggestions); |
| 78 registry->RegisterListPref(prefs::kDismissedDownloadSuggestions); | |
| 54 } | 79 } |
| 55 | 80 |
| 56 //////////////////////////////////////////////////////////////////////////////// | 81 //////////////////////////////////////////////////////////////////////////////// |
| 57 // Private methods | 82 // Private methods |
| 58 | 83 |
| 59 std::vector<Category> OfflinePageSuggestionsProvider::GetProvidedCategories() { | 84 std::vector<Category> OfflinePageSuggestionsProvider::GetProvidedCategories() { |
| 60 return std::vector<Category>({provided_category_}); | 85 std::vector<Category> provided_categories; |
| 86 if (recent_tabs_status_ != CategoryStatus::NOT_PROVIDED) | |
| 87 provided_categories.push_back(recent_tabs_category_); | |
| 88 if (downloads_status_ != CategoryStatus::NOT_PROVIDED) | |
| 89 provided_categories.push_back(downloads_category_); | |
| 90 return provided_categories; | |
| 61 } | 91 } |
| 62 | 92 |
| 63 CategoryStatus OfflinePageSuggestionsProvider::GetCategoryStatus( | 93 CategoryStatus OfflinePageSuggestionsProvider::GetCategoryStatus( |
| 64 Category category) { | 94 Category category) { |
| 65 DCHECK_EQ(category, provided_category_); | 95 if (category == recent_tabs_category_) |
| 66 return category_status_; | 96 return recent_tabs_status_; |
| 97 if (category == downloads_category_) | |
| 98 return downloads_status_; | |
| 99 NOTREACHED() << "Unknown category " << category.id(); | |
| 100 return CategoryStatus::NOT_PROVIDED; | |
| 67 } | 101 } |
| 68 | 102 |
| 69 CategoryInfo OfflinePageSuggestionsProvider::GetCategoryInfo( | 103 CategoryInfo OfflinePageSuggestionsProvider::GetCategoryInfo( |
| 70 Category category) { | 104 Category category) { |
| 71 // TODO(pke): Use the proper string once it's agreed on. | 105 if (category == recent_tabs_category_) { |
| 72 return CategoryInfo(base::ASCIIToUTF16("Offline pages"), | 106 return CategoryInfo(l10n_util::GetStringUTF16( |
| 107 IDS_NTP_RECENT_TAB_SUGGESTIONS_SECTION_HEADER), | |
| 108 ContentSuggestionsCardLayout::MINIMAL_CARD); | |
| 109 } | |
| 110 if (category == downloads_category_) { | |
| 111 return CategoryInfo( | |
| 112 l10n_util::GetStringUTF16(IDS_NTP_DOWNLOAD_SUGGESTIONS_SECTION_HEADER), | |
| 113 ContentSuggestionsCardLayout::MINIMAL_CARD); | |
| 114 } | |
| 115 NOTREACHED() << "Unknown category " << category.id(); | |
| 116 return CategoryInfo(base::string16(), | |
| 73 ContentSuggestionsCardLayout::MINIMAL_CARD); | 117 ContentSuggestionsCardLayout::MINIMAL_CARD); |
| 74 } | 118 } |
| 75 | 119 |
| 76 void OfflinePageSuggestionsProvider::DismissSuggestion( | 120 void OfflinePageSuggestionsProvider::DismissSuggestion( |
| 77 const std::string& suggestion_id) { | 121 const std::string& suggestion_id) { |
| 122 Category category = GetCategoryFromUniqueID(suggestion_id); | |
| 78 std::string offline_page_id = GetWithinCategoryIDFromUniqueID(suggestion_id); | 123 std::string offline_page_id = GetWithinCategoryIDFromUniqueID(suggestion_id); |
| 79 dismissed_ids_.insert(offline_page_id); | 124 if (category == recent_tabs_category_) { |
| 80 StoreDismissedIDsToPrefs(); | 125 DCHECK_NE(recent_tabs_status_, CategoryStatus::NOT_PROVIDED); |
|
Bernhard Bauer
2016/08/12 10:28:31
The (not 😉) expected value should go first for nic
Philipp Keck
2016/08/12 11:02:25
Done.
| |
| 126 dismissed_recent_tab_ids_.insert(offline_page_id); | |
| 127 StoreDismissedIDsToPrefs(prefs::kDismissedRecentOfflineTabSuggestions, | |
| 128 dismissed_recent_tab_ids_); | |
| 129 } else if (category == downloads_category_) { | |
| 130 DCHECK_NE(downloads_status_, CategoryStatus::NOT_PROVIDED); | |
| 131 dismissed_download_ids_.insert(offline_page_id); | |
| 132 StoreDismissedIDsToPrefs(prefs::kDismissedDownloadSuggestions, | |
| 133 dismissed_download_ids_); | |
| 134 } else { | |
| 135 NOTREACHED() << "Unknown category " << category.id(); | |
| 136 } | |
| 81 } | 137 } |
| 82 | 138 |
| 83 void OfflinePageSuggestionsProvider::FetchSuggestionImage( | 139 void OfflinePageSuggestionsProvider::FetchSuggestionImage( |
| 84 const std::string& suggestion_id, | 140 const std::string& suggestion_id, |
| 85 const ImageFetchedCallback& callback) { | 141 const ImageFetchedCallback& callback) { |
| 86 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available | 142 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available |
| 87 // there. | 143 // there. |
| 88 base::ThreadTaskRunnerHandle::Get()->PostTask( | 144 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 89 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image())); | 145 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image())); |
| 90 } | 146 } |
| 91 | 147 |
| 92 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging( | 148 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging( |
| 93 Category category) { | 149 Category category) { |
| 94 DCHECK_EQ(category, provided_category_); | |
| 95 // Ignored. | 150 // Ignored. |
| 96 } | 151 } |
| 97 | 152 |
| 98 std::vector<ContentSuggestion> | 153 std::vector<ContentSuggestion> |
| 99 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging( | 154 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging( |
| 100 Category category) { | 155 Category category) { |
| 101 // TODO(pke): Make GetDismissedSuggestionsForDebugging asynchronous so this | 156 // TODO(pke): Make GetDismissedSuggestionsForDebugging asynchronous so this |
| 102 // can return proper values. | 157 // can return proper values. |
| 103 DCHECK_EQ(category, provided_category_); | |
| 104 std::vector<ContentSuggestion> suggestions; | 158 std::vector<ContentSuggestion> suggestions; |
| 105 for (const std::string& dismissed_id : dismissed_ids_) { | 159 const std::set<std::string>* dismissed_ids = nullptr; |
| 160 if (category == recent_tabs_category_) { | |
| 161 DCHECK_NE(recent_tabs_status_, CategoryStatus::NOT_PROVIDED); | |
| 162 dismissed_ids = &dismissed_recent_tab_ids_; | |
| 163 } else if (category == downloads_category_) { | |
| 164 DCHECK_NE(downloads_status_, CategoryStatus::NOT_PROVIDED); | |
| 165 dismissed_ids = &dismissed_download_ids_; | |
| 166 } else { | |
| 167 NOTREACHED() << "Unknown category " << category.id(); | |
| 168 return suggestions; | |
| 169 } | |
| 170 | |
| 171 for (const std::string& dismissed_id : *dismissed_ids) { | |
| 106 ContentSuggestion suggestion( | 172 ContentSuggestion suggestion( |
| 107 MakeUniqueID(provided_category_, dismissed_id), | 173 MakeUniqueID(category, dismissed_id), |
| 108 GURL("http://dismissed-offline-page-" + dismissed_id)); | 174 GURL("http://dismissed-offline-page-" + dismissed_id)); |
| 109 suggestion.set_title(base::UTF8ToUTF16("Title not available")); | 175 suggestion.set_title(base::UTF8ToUTF16("Title not available")); |
| 110 suggestions.push_back(std::move(suggestion)); | 176 suggestions.push_back(std::move(suggestion)); |
| 111 } | 177 } |
| 112 return suggestions; | 178 return suggestions; |
| 113 } | 179 } |
| 114 | 180 |
| 115 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging( | 181 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging( |
| 116 Category category) { | 182 Category category) { |
| 117 DCHECK_EQ(category, provided_category_); | 183 if (category == recent_tabs_category_) { |
| 118 dismissed_ids_.clear(); | 184 DCHECK_NE(recent_tabs_status_, CategoryStatus::NOT_PROVIDED); |
| 119 StoreDismissedIDsToPrefs(); | 185 dismissed_recent_tab_ids_.clear(); |
| 186 StoreDismissedIDsToPrefs(prefs::kDismissedRecentOfflineTabSuggestions, | |
| 187 dismissed_recent_tab_ids_); | |
| 188 } else if (category == downloads_category_) { | |
| 189 DCHECK_NE(downloads_status_, CategoryStatus::NOT_PROVIDED); | |
| 190 dismissed_download_ids_.clear(); | |
| 191 StoreDismissedIDsToPrefs(prefs::kDismissedDownloadSuggestions, | |
| 192 dismissed_download_ids_); | |
| 193 } else { | |
| 194 NOTREACHED() << "Unknown category " << category.id(); | |
| 195 } | |
| 120 FetchOfflinePages(); | 196 FetchOfflinePages(); |
| 121 } | 197 } |
| 122 | 198 |
| 123 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded( | 199 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded( |
| 124 OfflinePageModel* model) { | 200 OfflinePageModel* model) { |
| 125 DCHECK_EQ(offline_page_model_, model); | 201 DCHECK_EQ(offline_page_model_, model); |
| 126 } | 202 } |
| 127 | 203 |
| 128 void OfflinePageSuggestionsProvider::OfflinePageModelChanged( | 204 void OfflinePageSuggestionsProvider::OfflinePageModelChanged( |
| 129 OfflinePageModel* model) { | 205 OfflinePageModel* model) { |
| 130 DCHECK_EQ(offline_page_model_, model); | 206 DCHECK_EQ(offline_page_model_, model); |
| 131 FetchOfflinePages(); | 207 FetchOfflinePages(); |
| 132 } | 208 } |
| 133 | 209 |
| 134 void OfflinePageSuggestionsProvider::OfflinePageDeleted( | 210 void OfflinePageSuggestionsProvider::OfflinePageDeleted( |
| 135 int64_t offline_id, | 211 int64_t offline_id, |
| 136 const offline_pages::ClientId& client_id) { | 212 const offline_pages::ClientId& client_id) { |
| 137 // TODO(pke): Implement, suggestion has to be removed from UI immediately. | 213 // TODO(pke): Implement, suggestion has to be removed from UI immediately. |
| 138 } | 214 } |
| 139 | 215 |
| 140 void OfflinePageSuggestionsProvider::FetchOfflinePages() { | 216 void OfflinePageSuggestionsProvider::FetchOfflinePages() { |
| 141 offline_page_model_->GetAllPages( | 217 offline_page_model_->GetAllPages( |
| 142 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded, | 218 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded, |
| 143 base::Unretained(this))); | 219 base::Unretained(this))); |
| 144 } | 220 } |
| 145 | 221 |
| 146 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded( | 222 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded( |
| 147 const MultipleOfflinePageItemResult& result) { | 223 const MultipleOfflinePageItemResult& result) { |
| 148 NotifyStatusChanged(CategoryStatus::AVAILABLE); | 224 bool need_recent_tabs = recent_tabs_status_ != CategoryStatus::NOT_PROVIDED; |
| 225 bool need_downloads = downloads_status_ != CategoryStatus::NOT_PROVIDED; | |
| 226 if (need_recent_tabs) | |
| 227 NotifyStatusChanged(recent_tabs_category_, CategoryStatus::AVAILABLE); | |
| 228 if (need_downloads) | |
| 229 NotifyStatusChanged(downloads_category_, CategoryStatus::AVAILABLE); | |
| 149 | 230 |
| 150 std::vector<ContentSuggestion> suggestions; | 231 std::vector<const OfflinePageItem*> recent_tab_items; |
| 232 std::vector<const OfflinePageItem*> download_items; | |
| 151 for (const OfflinePageItem& item : result) { | 233 for (const OfflinePageItem& item : result) { |
| 152 if (dismissed_ids_.count(base::IntToString(item.offline_id))) | 234 if (need_recent_tabs && |
| 153 continue; | 235 item.client_id.name_space == offline_pages::kLastNNamespace) { |
| 154 suggestions.push_back(ConvertOfflinePage(item)); | 236 if (!dismissed_recent_tab_ids_.count(base::IntToString(item.offline_id))) |
| 155 if (suggestions.size() == kMaxSuggestionsCount) | 237 recent_tab_items.push_back(&item); |
| 156 break; | 238 } else if (need_downloads && |
| 239 item.client_id.name_space == offline_pages::kDownloadNamespace) { | |
| 240 if (!dismissed_download_ids_.count(base::IntToString(item.offline_id))) | |
| 241 download_items.push_back(&item); | |
| 242 } | |
| 157 } | 243 } |
| 158 | 244 |
| 159 observer()->OnNewSuggestions(this, provided_category_, | 245 // TODO(pke): Once we have our OfflinePageModel getter and that doesn't do it |
| 160 std::move(suggestions)); | 246 // already, filter out duplicate URLs for recent tabs here. Duplicates for |
| 247 // downloads are fine. | |
| 248 | |
| 249 if (need_recent_tabs) { | |
| 250 observer()->OnNewSuggestions( | |
| 251 this, recent_tabs_category_, | |
| 252 GetMostRecentlyVisited(recent_tabs_category_, | |
| 253 std::move(recent_tab_items))); | |
| 254 } | |
| 255 if (need_downloads) { | |
| 256 observer()->OnNewSuggestions( | |
| 257 this, downloads_category_, | |
| 258 GetMostRecentlyVisited(downloads_category_, std::move(download_items))); | |
| 259 } | |
| 161 } | 260 } |
| 162 | 261 |
| 163 void OfflinePageSuggestionsProvider::NotifyStatusChanged( | 262 void OfflinePageSuggestionsProvider::NotifyStatusChanged( |
| 263 Category category, | |
| 164 CategoryStatus new_status) { | 264 CategoryStatus new_status) { |
| 165 if (category_status_ == new_status) | 265 if (category == recent_tabs_category_) { |
| 166 return; | 266 DCHECK_NE(recent_tabs_status_, CategoryStatus::NOT_PROVIDED); |
| 167 category_status_ = new_status; | 267 if (recent_tabs_status_ == new_status) |
| 168 | 268 return; |
| 169 observer()->OnCategoryStatusChanged(this, provided_category_, new_status); | 269 recent_tabs_status_ = new_status; |
| 270 observer()->OnCategoryStatusChanged(this, category, new_status); | |
| 271 } else if (category == downloads_category_) { | |
| 272 DCHECK_NE(downloads_status_, CategoryStatus::NOT_PROVIDED); | |
| 273 if (downloads_status_ == new_status) | |
| 274 return; | |
| 275 downloads_status_ = new_status; | |
| 276 observer()->OnCategoryStatusChanged(this, category, new_status); | |
| 277 } else { | |
| 278 NOTREACHED() << "Unknown category " << category.id(); | |
| 279 } | |
| 170 } | 280 } |
| 171 | 281 |
| 172 ContentSuggestion OfflinePageSuggestionsProvider::ConvertOfflinePage( | 282 ContentSuggestion OfflinePageSuggestionsProvider::ConvertOfflinePage( |
| 283 Category category, | |
| 173 const OfflinePageItem& offline_page) const { | 284 const OfflinePageItem& offline_page) const { |
| 174 // TODO(pke): Make sure the URL is actually opened as an offline URL. | 285 // TODO(pke): Make sure the URL is actually opened as an offline URL. |
| 175 // Currently, the browser opens the offline URL and then immediately | 286 // Currently, the browser opens the offline URL and then immediately |
| 176 // redirects to the online URL if the device is online. | 287 // redirects to the online URL if the device is online. |
| 177 ContentSuggestion suggestion( | 288 ContentSuggestion suggestion( |
| 178 MakeUniqueID(provided_category_, | 289 MakeUniqueID(category, base::IntToString(offline_page.offline_id)), |
| 179 base::IntToString(offline_page.offline_id)), | |
| 180 offline_page.GetOfflineURL()); | 290 offline_page.GetOfflineURL()); |
| 181 | 291 |
| 182 // TODO(pke): Sort by most recently visited and only keep the top one of | |
| 183 // multiple entries for the same URL. | |
| 184 // TODO(pke): Get more reasonable data from the OfflinePageModel here. | 292 // TODO(pke): Get more reasonable data from the OfflinePageModel here. |
| 185 suggestion.set_title(base::UTF8ToUTF16(offline_page.url.spec())); | 293 suggestion.set_title(base::UTF8ToUTF16(offline_page.url.spec())); |
| 186 suggestion.set_snippet_text(base::string16()); | 294 suggestion.set_snippet_text(base::string16()); |
| 187 suggestion.set_publish_date(offline_page.creation_time); | 295 suggestion.set_publish_date(offline_page.creation_time); |
| 188 suggestion.set_publisher_name(base::UTF8ToUTF16(offline_page.url.host())); | 296 suggestion.set_publisher_name(base::UTF8ToUTF16(offline_page.url.host())); |
| 189 return suggestion; | 297 return suggestion; |
| 190 } | 298 } |
| 191 | 299 |
| 192 void OfflinePageSuggestionsProvider::ReadDismissedIDsFromPrefs() { | 300 std::vector<ContentSuggestion> |
| 193 dismissed_ids_.clear(); | 301 OfflinePageSuggestionsProvider::GetMostRecentlyVisited( |
| 194 const base::ListValue* list = | 302 Category category, |
| 195 pref_service_->GetList(prefs::kDismissedOfflinePageSuggestions); | 303 std::vector<const OfflinePageItem*> offline_page_items) const { |
| 304 std::sort(offline_page_items.begin(), offline_page_items.end(), | |
| 305 OrderByMostRecentlyVisited); | |
| 306 std::vector<ContentSuggestion> suggestions; | |
| 307 for (const OfflinePageItem* offline_page_item : offline_page_items) { | |
| 308 suggestions.push_back(ConvertOfflinePage(category, *offline_page_item)); | |
| 309 if (suggestions.size() == kMaxSuggestionsCount) | |
| 310 break; | |
| 311 } | |
| 312 return suggestions; | |
| 313 } | |
| 314 | |
| 315 std::set<std::string> OfflinePageSuggestionsProvider::ReadDismissedIDsFromPrefs( | |
| 316 const std::string& pref_name) const { | |
| 317 std::set<std::string> dismissed_ids; | |
| 318 const base::ListValue* list = pref_service_->GetList(pref_name); | |
| 196 for (const std::unique_ptr<base::Value>& value : *list) { | 319 for (const std::unique_ptr<base::Value>& value : *list) { |
| 197 std::string dismissed_id; | 320 std::string dismissed_id; |
| 198 bool success = value->GetAsString(&dismissed_id); | 321 bool success = value->GetAsString(&dismissed_id); |
| 199 DCHECK(success) << "Failed to parse dismissed offline page ID from prefs"; | 322 DCHECK(success) << "Failed to parse dismissed offline page ID from prefs"; |
| 200 dismissed_ids_.insert(std::move(dismissed_id)); | 323 dismissed_ids.insert(dismissed_id); |
| 201 } | 324 } |
| 325 return dismissed_ids; | |
| 202 } | 326 } |
| 203 | 327 |
| 204 void OfflinePageSuggestionsProvider::StoreDismissedIDsToPrefs() { | 328 void OfflinePageSuggestionsProvider::StoreDismissedIDsToPrefs( |
| 329 const std::string& pref_name, | |
| 330 const std::set<std::string>& dismissed_ids) const { | |
| 205 base::ListValue list; | 331 base::ListValue list; |
| 206 for (const std::string& dismissed_id : dismissed_ids_) | 332 for (const std::string& dismissed_id : dismissed_ids) |
| 207 list.AppendString(dismissed_id); | 333 list.AppendString(dismissed_id); |
| 208 pref_service_->Set(prefs::kDismissedOfflinePageSuggestions, list); | 334 pref_service_->Set(pref_name, list); |
| 209 } | 335 } |
| 210 | 336 |
| 211 } // namespace ntp_snippets | 337 } // namespace ntp_snippets |
| OLD | NEW |