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

Side by Side Diff: components/ntp_snippets/content_suggestions_service.cc

Issue 2102023002: Add ContentSuggestionsService (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove NTPSnippet::ToContentSuggestion and make ContentSuggestionsProvider::MakeUniqueID protected Created 4 years, 5 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/ntp_snippets/content_suggestions_service.h"
6
7 #include <algorithm>
8 #include <iterator>
9
10 #include "base/bind.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "ui/gfx/image/image.h"
13
14 namespace ntp_snippets {
15
16 ContentSuggestionsService::ContentSuggestionsService(State state)
17 : state_(state) {}
18
19 ContentSuggestionsService::~ContentSuggestionsService() {}
20
21 void ContentSuggestionsService::Shutdown() {
22 DCHECK(providers_.empty());
23 DCHECK(categories_.empty());
24 DCHECK(suggestions_by_category_.empty());
25 DCHECK(id_category_map_.empty());
26 state_ = State::DISABLED;
27 FOR_EACH_OBSERVER(Observer, observers_, ContentSuggestionsServiceShutdown());
28 }
29
30 ContentSuggestionsCategoryStatus ContentSuggestionsService::GetCategoryStatus(
31 ContentSuggestionsCategory category) const {
32 if (state_ == State::DISABLED)
33 return ContentSuggestionsCategoryStatus::
Marc Treib 2016/07/07 09:37:51 nit: braces if the body doesn't fit on one line
Philipp Keck 2016/07/07 12:22:30 Done.
34 ALL_SUGGESTIONS_EXPLICITLY_DISABLED;
35
36 auto iterator = providers_.find(category);
37 if (iterator == providers_.end())
38 return ContentSuggestionsCategoryStatus::NOT_PROVIDED;
39
40 return iterator->second->GetCategoryStatus(category);
41 }
42
43 const std::vector<ContentSuggestion>&
44 ContentSuggestionsService::GetSuggestionsForCategory(
45 ContentSuggestionsCategory category) const {
46 auto iterator = suggestions_by_category_.find(category);
47 if (iterator == suggestions_by_category_.end()) {
Bernhard Bauer 2016/07/07 10:02:19 And no braces here ☺
Philipp Keck 2016/07/07 12:22:29 Done.
48 return no_suggestions_;
49 }
50 return iterator->second;
51 }
52
53 void ContentSuggestionsService::FetchSuggestionImage(
54 const std::string& suggestion_id,
55 const ImageFetchedCallback& callback) {
56 if (!id_category_map_.count(suggestion_id)) {
57 LOG(WARNING) << "Requested image for unknown suggestion " << suggestion_id;
58 callback.Run(suggestion_id, gfx::Image());
59 return;
60 }
61 ContentSuggestionsCategory category = id_category_map_[suggestion_id];
62 if (!providers_.count(category)) {
63 LOG(WARNING) << "Requested image for suggestion " << suggestion_id
64 << " for unavailable category " << int(category);
65 callback.Run(suggestion_id, gfx::Image());
66 return;
67 }
68 providers_[category]->FetchSuggestionImage(suggestion_id, callback);
69 }
70
71 void ContentSuggestionsService::ClearCachedSuggestionsForDebugging() {
72 suggestions_by_category_.clear();
73 id_category_map_.clear();
74 for (auto& provider : providers_) {
Marc Treib 2016/07/07 09:37:51 nit: The elements are not providers, but category+
Philipp Keck 2016/07/07 12:22:30 Done.
75 provider.second->ClearCachedSuggestionsForDebugging();
76 }
77 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions());
78 }
79
80 void ContentSuggestionsService::ClearDiscardedSuggestionsForDebugging() {
81 for (auto& provider : providers_) {
Marc Treib 2016/07/07 09:37:51 Same here
Philipp Keck 2016/07/07 12:22:30 Done.
82 provider.second->ClearDiscardedSuggestionsForDebugging();
83 }
84 }
85
86 void ContentSuggestionsService::DiscardSuggestion(
87 const std::string& suggestion_id) {
88 if (!id_category_map_.count(suggestion_id)) {
89 LOG(WARNING) << "Discarded unknown suggestion " << suggestion_id;
90 return;
91 }
92 ContentSuggestionsCategory category = id_category_map_[suggestion_id];
93 if (!providers_.count(category)) {
94 LOG(WARNING) << "Discarded suggestion " << suggestion_id
95 << " for unavailable category " << int(category);
96 return;
97 }
98 providers_[category]->DiscardSuggestion(suggestion_id);
99
100 // Remove the suggestion locally.
101 id_category_map_.erase(suggestion_id);
102 std::vector<ContentSuggestion>* suggestions =
103 &suggestions_by_category_[category];
104 auto position =
105 std::find_if(suggestions->begin(), suggestions->end(),
106 [&suggestion_id](const ContentSuggestion& suggestion) {
107 return suggestion_id == suggestion.id();
108 });
109 DCHECK(position != suggestions->end());
110 suggestions->erase(position);
111 }
112
113 void ContentSuggestionsService::AddObserver(Observer* observer) {
114 observers_.AddObserver(observer);
115 }
116
117 void ContentSuggestionsService::RemoveObserver(Observer* observer) {
118 observers_.RemoveObserver(observer);
119 }
120
121 void ContentSuggestionsService::RegisterProvider(
122 ContentSuggestionsProvider* provider) {
123 if (state_ == State::DISABLED)
Marc Treib 2016/07/07 09:37:51 Are we sure about this? We'll have to change it on
Philipp Keck 2016/07/07 12:22:30 Yes. It is here because the NTPSnippetsService wil
Marc Treib 2016/07/07 12:32:16 Alright. Add a TODO maybe?
Philipp Keck 2016/07/07 12:44:06 Done.
124 return;
125
126 for (ContentSuggestionsCategory category : provider->provided_categories()) {
127 DCHECK_EQ(0ul, providers_.count(category));
128 providers_[category] = provider;
129 // TODO(pke) In the future, make sure that the categories have some useful
Bernhard Bauer 2016/07/07 10:02:19 Nit: The exact format for TODOs is TODO(ldap): ☺
Philipp Keck 2016/07/07 12:22:29 Done.
130 // (maybe constant, at least consistent) ordering for the UI.
131 categories_.push_back(category);
132 if (IsContentSuggestionsCategoryStatusAvailable(
133 provider->GetCategoryStatus(category))) {
134 suggestions_by_category_[category] = std::vector<ContentSuggestion>();
135 }
136 provider->SetObserver(this);
Marc Treib 2016/07/07 09:37:51 This should go out of the loop
Philipp Keck 2016/07/07 12:22:29 Done.
137 FOR_EACH_OBSERVER(Observer, observers_,
138 OnCategoryStatusChanged(
139 category, provider->GetCategoryStatus(category)));
140 }
141 }
142
143 ////////////////////////////////////////////////////////////////////////////////
144 // Private methods
145
146 void ContentSuggestionsService::OnNewSuggestions(
147 ContentSuggestionsCategory changed_category,
148 std::vector<ContentSuggestion> new_suggestions) {
149 DCHECK(IsCategoryRegistered(changed_category));
150
151 for (const ContentSuggestion& suggestion :
152 suggestions_by_category_[changed_category]) {
153 id_category_map_.erase(suggestion.id());
154 }
155
156 for (const ContentSuggestion& suggestion : new_suggestions) {
157 id_category_map_[suggestion.id()] = changed_category;
158 }
159
160 suggestions_by_category_[changed_category] = std::move(new_suggestions);
161
162 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions());
163 }
164
165 void ContentSuggestionsService::OnCategoryStatusChanged(
166 ContentSuggestionsCategory changed_category,
167 ContentSuggestionsCategoryStatus new_status) {
168 if (!IsContentSuggestionsCategoryStatusAvailable(new_status)) {
169 for (const ContentSuggestion& suggestion :
170 suggestions_by_category_[changed_category]) {
171 id_category_map_.erase(suggestion.id());
172 }
173 suggestions_by_category_.erase(changed_category);
174 }
Marc Treib 2016/07/07 09:37:51 Do we also need to do something if it is now avail
Philipp Keck 2016/07/07 12:22:30 No. id_category_map_ and suggestions_by_category_
175 FOR_EACH_OBSERVER(Observer, observers_,
176 OnCategoryStatusChanged(changed_category, new_status));
177 }
178
179 void ContentSuggestionsService::OnProviderShutdown(
180 ContentSuggestionsProvider* provider) {
181 for (ContentSuggestionsCategory category : provider->provided_categories()) {
182 auto iterator = std::find(categories_.begin(), categories_.end(), category);
183 DCHECK(iterator != categories_.end());
184 categories_.erase(iterator);
185 for (const ContentSuggestion& suggestion :
186 suggestions_by_category_[category]) {
187 id_category_map_.erase(suggestion.id());
188 }
189 suggestions_by_category_.erase(category);
190 providers_.erase(category);
191 FOR_EACH_OBSERVER(
192 Observer, observers_,
193 OnCategoryStatusChanged(category, GetCategoryStatus(category)));
Marc Treib 2016/07/07 09:37:51 optional: You could replace all the OnCategoryStat
Philipp Keck 2016/07/07 12:22:29 Done.
194 }
195 }
196
197 bool ContentSuggestionsService::IsCategoryRegistered(
198 ContentSuggestionsCategory category) const {
199 return std::find(categories_.begin(), categories_.end(), category) !=
200 categories_.end();
201 }
202
203 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698