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

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

Issue 2245583002: Split OfflinePageSuggestions into two categories (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@offlinedismissed
Patch Set: 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>
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698