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; | |
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 } | |
89 if (downloads_status_ != CategoryStatus::NOT_PROVIDED) { | |
90 provided_categories.push_back(downloads_category_); | |
91 } | |
92 return provided_categories; | |
61 } | 93 } |
62 | 94 |
63 CategoryStatus OfflinePageSuggestionsProvider::GetCategoryStatus( | 95 CategoryStatus OfflinePageSuggestionsProvider::GetCategoryStatus( |
64 Category category) { | 96 Category category) { |
65 DCHECK_EQ(category, provided_category_); | 97 if (category == recent_tabs_category_) { |
66 return category_status_; | 98 return recent_tabs_status_; |
99 } else if (category == downloads_category_) { | |
Marc Treib
2016/08/12 09:21:14
nit: No "else" after "return"
Philipp Keck
2016/08/12 09:56:40
Done. Don't really like this rule. Now the shape o
Marc Treib
2016/08/12 10:12:53
Well, the rule is the rule... in general, I do lik
Bernhard Bauer
2016/08/12 10:28:31
Alternatively, use a switch statement?
Philipp Keck
2016/08/12 11:02:25
Yeah, but that wouldn't get rid of the code duplic
| |
100 return downloads_status_; | |
101 } else { | |
102 NOTREACHED() << "Unknown category " << category.id(); | |
103 return CategoryStatus::NOT_PROVIDED; | |
104 } | |
67 } | 105 } |
68 | 106 |
69 CategoryInfo OfflinePageSuggestionsProvider::GetCategoryInfo( | 107 CategoryInfo OfflinePageSuggestionsProvider::GetCategoryInfo( |
70 Category category) { | 108 Category category) { |
71 // TODO(pke): Use the proper string once it's agreed on. | 109 if (category == recent_tabs_category_) { |
72 return CategoryInfo(base::ASCIIToUTF16("Offline pages"), | 110 return CategoryInfo(l10n_util::GetStringUTF16( |
73 ContentSuggestionsCardLayout::MINIMAL_CARD); | 111 IDS_NTP_RECENT_TAB_SUGGESTIONS_SECTION_HEADER), |
112 ContentSuggestionsCardLayout::MINIMAL_CARD); | |
113 } else if (category == downloads_category_) { | |
Marc Treib
2016/08/12 09:21:14
Same here
Philipp Keck
2016/08/12 09:56:40
Done.
| |
114 return CategoryInfo( | |
115 l10n_util::GetStringUTF16(IDS_NTP_DOWNLOAD_SUGGESTIONS_SECTION_HEADER), | |
116 ContentSuggestionsCardLayout::MINIMAL_CARD); | |
117 } else { | |
118 NOTREACHED() << "Unknown category " << category.id(); | |
119 return CategoryInfo(base::string16(), | |
120 ContentSuggestionsCardLayout::MINIMAL_CARD); | |
121 } | |
74 } | 122 } |
75 | 123 |
76 void OfflinePageSuggestionsProvider::DismissSuggestion( | 124 void OfflinePageSuggestionsProvider::DismissSuggestion( |
77 const std::string& suggestion_id) { | 125 const std::string& suggestion_id) { |
126 Category category = GetCategoryFromUniqueID(suggestion_id); | |
78 std::string offline_page_id = GetWithinCategoryIDFromUniqueID(suggestion_id); | 127 std::string offline_page_id = GetWithinCategoryIDFromUniqueID(suggestion_id); |
79 dismissed_ids_.insert(offline_page_id); | 128 if (category == recent_tabs_category_) { |
80 StoreDismissedIDsToPrefs(); | 129 DCHECK_NE(recent_tabs_status_, CategoryStatus::NOT_PROVIDED); |
Marc Treib
2016/08/12 09:21:14
This is enforced in the ContentSuggestionsService?
Philipp Keck
2016/08/12 09:56:40
Yes, but not only:
Firstly, if the status is NOT_P
Marc Treib
2016/08/12 10:12:53
Acknowledged.
| |
130 dismissed_recent_tab_ids_.insert(offline_page_id); | |
131 StoreDismissedIDsToPrefs(prefs::kDismissedRecentOfflineTabSuggestions, | |
132 dismissed_recent_tab_ids_); | |
133 } else if (category == downloads_category_) { | |
134 DCHECK_NE(downloads_status_, CategoryStatus::NOT_PROVIDED); | |
135 dismissed_download_ids_.insert(offline_page_id); | |
136 StoreDismissedIDsToPrefs(prefs::kDismissedDownloadSuggestions, | |
137 dismissed_download_ids_); | |
138 } | |
Marc Treib
2016/08/12 09:21:14
else NOTREACHED?
Philipp Keck
2016/08/12 09:56:40
Done.
| |
81 } | 139 } |
82 | 140 |
83 void OfflinePageSuggestionsProvider::FetchSuggestionImage( | 141 void OfflinePageSuggestionsProvider::FetchSuggestionImage( |
84 const std::string& suggestion_id, | 142 const std::string& suggestion_id, |
85 const ImageFetchedCallback& callback) { | 143 const ImageFetchedCallback& callback) { |
86 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available | 144 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available |
87 // there. | 145 // there. |
88 base::ThreadTaskRunnerHandle::Get()->PostTask( | 146 base::ThreadTaskRunnerHandle::Get()->PostTask( |
89 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image())); | 147 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image())); |
90 } | 148 } |
91 | 149 |
92 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging( | 150 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging( |
93 Category category) { | 151 Category category) { |
94 DCHECK_EQ(category, provided_category_); | |
95 // Ignored. | 152 // Ignored. |
96 } | 153 } |
97 | 154 |
98 std::vector<ContentSuggestion> | 155 std::vector<ContentSuggestion> |
99 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging( | 156 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging( |
100 Category category) { | 157 Category category) { |
101 // TODO(pke): Make GetDismissedSuggestionsForDebugging asynchronous so this | 158 // TODO(pke): Make GetDismissedSuggestionsForDebugging asynchronous so this |
102 // can return proper values. | 159 // can return proper values. |
103 DCHECK_EQ(category, provided_category_); | |
104 std::vector<ContentSuggestion> suggestions; | 160 std::vector<ContentSuggestion> suggestions; |
105 for (const std::string& dismissed_id : dismissed_ids_) { | 161 std::set<std::string>* dismissed_ids = nullptr; |
Marc Treib
2016/08/12 09:21:14
const?
Philipp Keck
2016/08/12 09:56:40
Done.
| |
162 if (category == recent_tabs_category_) { | |
163 DCHECK_NE(recent_tabs_status_, CategoryStatus::NOT_PROVIDED); | |
164 dismissed_ids = &dismissed_recent_tab_ids_; | |
165 } else if (category == downloads_category_) { | |
166 DCHECK_NE(downloads_status_, CategoryStatus::NOT_PROVIDED); | |
167 dismissed_ids = &dismissed_download_ids_; | |
168 } else { | |
169 return suggestions; | |
Marc Treib
2016/08/12 09:21:14
NOTREACHED?
Philipp Keck
2016/08/12 09:56:40
Done.
| |
170 } | |
171 | |
172 for (const std::string& dismissed_id : *dismissed_ids) { | |
106 ContentSuggestion suggestion( | 173 ContentSuggestion suggestion( |
107 MakeUniqueID(provided_category_, dismissed_id), | 174 MakeUniqueID(category, dismissed_id), |
108 GURL("http://dismissed-offline-page-" + dismissed_id)); | 175 GURL("http://dismissed-offline-page-" + dismissed_id)); |
109 suggestion.set_title(base::UTF8ToUTF16("Title not available")); | 176 suggestion.set_title(base::UTF8ToUTF16("Title not available")); |
110 suggestions.push_back(std::move(suggestion)); | 177 suggestions.push_back(std::move(suggestion)); |
111 } | 178 } |
112 return suggestions; | 179 return suggestions; |
113 } | 180 } |
114 | 181 |
115 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging( | 182 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging( |
116 Category category) { | 183 Category category) { |
117 DCHECK_EQ(category, provided_category_); | 184 if (category == recent_tabs_category_) { |
118 dismissed_ids_.clear(); | 185 DCHECK_NE(recent_tabs_status_, CategoryStatus::NOT_PROVIDED); |
119 StoreDismissedIDsToPrefs(); | 186 dismissed_recent_tab_ids_.clear(); |
187 StoreDismissedIDsToPrefs(prefs::kDismissedRecentOfflineTabSuggestions, | |
188 dismissed_recent_tab_ids_); | |
189 } else if (category == downloads_category_) { | |
190 DCHECK_NE(downloads_status_, CategoryStatus::NOT_PROVIDED); | |
191 dismissed_download_ids_.clear(); | |
192 StoreDismissedIDsToPrefs(prefs::kDismissedDownloadSuggestions, | |
193 dismissed_download_ids_); | |
194 } else { | |
195 NOTREACHED() << "Unknown category " << category.id(); | |
196 } | |
120 FetchOfflinePages(); | 197 FetchOfflinePages(); |
121 } | 198 } |
122 | 199 |
123 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded( | 200 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded( |
124 OfflinePageModel* model) { | 201 OfflinePageModel* model) { |
125 DCHECK_EQ(offline_page_model_, model); | 202 DCHECK_EQ(offline_page_model_, model); |
126 } | 203 } |
127 | 204 |
128 void OfflinePageSuggestionsProvider::OfflinePageModelChanged( | 205 void OfflinePageSuggestionsProvider::OfflinePageModelChanged( |
129 OfflinePageModel* model) { | 206 OfflinePageModel* model) { |
130 DCHECK_EQ(offline_page_model_, model); | 207 DCHECK_EQ(offline_page_model_, model); |
131 FetchOfflinePages(); | 208 FetchOfflinePages(); |
132 } | 209 } |
133 | 210 |
134 void OfflinePageSuggestionsProvider::OfflinePageDeleted( | 211 void OfflinePageSuggestionsProvider::OfflinePageDeleted( |
135 int64_t offline_id, | 212 int64_t offline_id, |
136 const offline_pages::ClientId& client_id) { | 213 const offline_pages::ClientId& client_id) { |
137 // TODO(pke): Implement, suggestion has to be removed from UI immediately. | 214 // TODO(pke): Implement, suggestion has to be removed from UI immediately. |
138 } | 215 } |
139 | 216 |
140 void OfflinePageSuggestionsProvider::FetchOfflinePages() { | 217 void OfflinePageSuggestionsProvider::FetchOfflinePages() { |
141 offline_page_model_->GetAllPages( | 218 offline_page_model_->GetAllPages( |
142 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded, | 219 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded, |
143 base::Unretained(this))); | 220 base::Unretained(this))); |
144 } | 221 } |
145 | 222 |
146 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded( | 223 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded( |
147 const MultipleOfflinePageItemResult& result) { | 224 const MultipleOfflinePageItemResult& result) { |
148 NotifyStatusChanged(CategoryStatus::AVAILABLE); | 225 bool needRecentTabs = recent_tabs_status_ != CategoryStatus::NOT_PROVIDED; |
Marc Treib
2016/08/12 09:21:14
need_recent_tabs, need_downloads
Philipp Keck
2016/08/12 09:56:40
Done.
| |
226 bool needDownloads = recent_tabs_status_ != CategoryStatus::NOT_PROVIDED; | |
Marc Treib
2016/08/12 09:21:14
downloads_status_
Philipp Keck
2016/08/12 09:56:40
Done. Good catch. The whole code duplication isn't
Marc Treib
2016/08/12 10:12:53
The alternative would be to have getters like GetS
Philipp Keck
2016/08/12 10:22:54
I'd refactor only after the provider has grown or
| |
227 if (needRecentTabs) | |
228 NotifyStatusChanged(recent_tabs_category_, CategoryStatus::AVAILABLE); | |
Marc Treib
2016/08/12 09:21:14
Braces for single=line bodies or not? Either is fi
Philipp Keck
2016/08/12 09:56:40
This file is supposed to be without. Changed two i
| |
229 if (needDownloads) | |
230 NotifyStatusChanged(downloads_category_, CategoryStatus::AVAILABLE); | |
149 | 231 |
150 std::vector<ContentSuggestion> suggestions; | 232 std::vector<const OfflinePageItem*> recent_tab_items; |
233 std::vector<const OfflinePageItem*> download_items; | |
151 for (const OfflinePageItem& item : result) { | 234 for (const OfflinePageItem& item : result) { |
152 if (dismissed_ids_.count(base::IntToString(item.offline_id))) | 235 if (needRecentTabs && |
153 continue; | 236 item.client_id.name_space == offline_pages::kLastNNamespace) { |
154 suggestions.push_back(ConvertOfflinePage(item)); | 237 if (!dismissed_recent_tab_ids_.count(base::IntToString(item.offline_id))) |
155 if (suggestions.size() == kMaxSuggestionsCount) | 238 recent_tab_items.push_back(&item); |
156 break; | 239 } else if (needDownloads && |
240 item.client_id.name_space == offline_pages::kDownloadNamespace) { | |
241 if (!dismissed_download_ids_.count(base::IntToString(item.offline_id))) | |
242 download_items.push_back(&item); | |
243 } | |
157 } | 244 } |
158 | 245 |
159 observer()->OnNewSuggestions(this, provided_category_, | 246 // TODO(pke): Once we have our BookmarkModel getter and that doesn't do it |
160 std::move(suggestions)); | 247 // already, filter out duplicate URLs for recent tabs here. Duplicates for |
248 // downloads are fine. | |
249 | |
250 if (needRecentTabs) { | |
251 observer()->OnNewSuggestions( | |
252 this, recent_tabs_category_, | |
253 GetMostRecentlyVisited(recent_tabs_category_, &recent_tab_items)); | |
254 } | |
255 if (needDownloads) { | |
256 observer()->OnNewSuggestions( | |
257 this, downloads_category_, | |
258 GetMostRecentlyVisited(downloads_category_, &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 { |
Marc Treib
2016/08/12 09:21:14
Hrm, I'm not a fan of this kind of mutable input a
Philipp Keck
2016/08/12 09:56:40
Done.
| |
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) { | |
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) { | |
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 |