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/content_suggestions_service.h" | 5 #include "components/ntp_snippets/content_suggestions_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <set> | 9 #include <set> |
10 #include <utility> | 10 #include <utility> |
(...skipping 15 matching lines...) Expand all Loading... |
26 user_classifier_(pref_service) { | 26 user_classifier_(pref_service) { |
27 // Can be null in tests. | 27 // Can be null in tests. |
28 if (history_service) | 28 if (history_service) |
29 history_service_observer_.Add(history_service); | 29 history_service_observer_.Add(history_service); |
30 } | 30 } |
31 | 31 |
32 ContentSuggestionsService::~ContentSuggestionsService() {} | 32 ContentSuggestionsService::~ContentSuggestionsService() {} |
33 | 33 |
34 void ContentSuggestionsService::Shutdown() { | 34 void ContentSuggestionsService::Shutdown() { |
35 ntp_snippets_service_ = nullptr; | 35 ntp_snippets_service_ = nullptr; |
36 id_category_map_.clear(); | |
37 suggestions_by_category_.clear(); | 36 suggestions_by_category_.clear(); |
38 providers_by_category_.clear(); | 37 providers_by_category_.clear(); |
39 categories_.clear(); | 38 categories_.clear(); |
40 providers_.clear(); | 39 providers_.clear(); |
41 state_ = State::DISABLED; | 40 state_ = State::DISABLED; |
42 FOR_EACH_OBSERVER(Observer, observers_, ContentSuggestionsServiceShutdown()); | 41 FOR_EACH_OBSERVER(Observer, observers_, ContentSuggestionsServiceShutdown()); |
43 } | 42 } |
44 | 43 |
45 CategoryStatus ContentSuggestionsService::GetCategoryStatus( | 44 CategoryStatus ContentSuggestionsService::GetCategoryStatus( |
46 Category category) const { | 45 Category category) const { |
(...skipping 20 matching lines...) Expand all Loading... |
67 ContentSuggestionsService::GetSuggestionsForCategory(Category category) const { | 66 ContentSuggestionsService::GetSuggestionsForCategory(Category category) const { |
68 auto iterator = suggestions_by_category_.find(category); | 67 auto iterator = suggestions_by_category_.find(category); |
69 if (iterator == suggestions_by_category_.end()) | 68 if (iterator == suggestions_by_category_.end()) |
70 return no_suggestions_; | 69 return no_suggestions_; |
71 return iterator->second; | 70 return iterator->second; |
72 } | 71 } |
73 | 72 |
74 void ContentSuggestionsService::FetchSuggestionImage( | 73 void ContentSuggestionsService::FetchSuggestionImage( |
75 const std::string& suggestion_id, | 74 const std::string& suggestion_id, |
76 const ImageFetchedCallback& callback) { | 75 const ImageFetchedCallback& callback) { |
77 if (!id_category_map_.count(suggestion_id)) { | 76 Category category = category_factory_.GetCategoryFromUniqueID(suggestion_id); |
78 LOG(WARNING) << "Requested image for unknown suggestion " << suggestion_id; | |
79 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
80 FROM_HERE, base::Bind(callback, gfx::Image())); | |
81 return; | |
82 } | |
83 Category category = id_category_map_.at(suggestion_id); | |
84 if (!providers_by_category_.count(category)) { | 77 if (!providers_by_category_.count(category)) { |
85 LOG(WARNING) << "Requested image for suggestion " << suggestion_id | 78 LOG(WARNING) << "Requested image for suggestion " << suggestion_id |
86 << " for unavailable category " << category; | 79 << " for unavailable category " << category; |
87 base::ThreadTaskRunnerHandle::Get()->PostTask( | 80 base::ThreadTaskRunnerHandle::Get()->PostTask( |
88 FROM_HERE, base::Bind(callback, gfx::Image())); | 81 FROM_HERE, base::Bind(callback, gfx::Image())); |
89 return; | 82 return; |
90 } | 83 } |
91 providers_by_category_[category]->FetchSuggestionImage(suggestion_id, | 84 providers_by_category_[category]->FetchSuggestionImage(suggestion_id, |
92 callback); | 85 callback); |
93 } | 86 } |
94 | 87 |
95 void ContentSuggestionsService::ClearHistory( | 88 void ContentSuggestionsService::ClearHistory( |
96 base::Time begin, | 89 base::Time begin, |
97 base::Time end, | 90 base::Time end, |
98 const base::Callback<bool(const GURL& url)>& filter) { | 91 const base::Callback<bool(const GURL& url)>& filter) { |
99 for (const auto& provider : providers_) { | 92 for (const auto& provider : providers_) { |
100 provider->ClearHistory(begin, end, filter); | 93 provider->ClearHistory(begin, end, filter); |
101 } | 94 } |
102 } | 95 } |
103 | 96 |
104 void ContentSuggestionsService::ClearAllCachedSuggestions() { | 97 void ContentSuggestionsService::ClearAllCachedSuggestions() { |
105 suggestions_by_category_.clear(); | 98 suggestions_by_category_.clear(); |
106 id_category_map_.clear(); | |
107 for (const auto& category_provider_pair : providers_by_category_) { | 99 for (const auto& category_provider_pair : providers_by_category_) { |
108 category_provider_pair.second->ClearCachedSuggestions( | 100 category_provider_pair.second->ClearCachedSuggestions( |
109 category_provider_pair.first); | 101 category_provider_pair.first); |
110 FOR_EACH_OBSERVER(Observer, observers_, | 102 FOR_EACH_OBSERVER(Observer, observers_, |
111 OnNewSuggestions(category_provider_pair.first)); | 103 OnNewSuggestions(category_provider_pair.first)); |
112 } | 104 } |
113 } | 105 } |
114 | 106 |
115 void ContentSuggestionsService::ClearCachedSuggestions( | 107 void ContentSuggestionsService::ClearCachedSuggestions(Category category) { |
116 Category category) { | |
117 for (const ContentSuggestion& suggestion : | |
118 suggestions_by_category_[category]) { | |
119 id_category_map_.erase(suggestion.id()); | |
120 } | |
121 suggestions_by_category_[category].clear(); | 108 suggestions_by_category_[category].clear(); |
122 auto iterator = providers_by_category_.find(category); | 109 auto iterator = providers_by_category_.find(category); |
123 if (iterator != providers_by_category_.end()) | 110 if (iterator != providers_by_category_.end()) |
124 iterator->second->ClearCachedSuggestions(category); | 111 iterator->second->ClearCachedSuggestions(category); |
125 } | 112 } |
126 | 113 |
127 void ContentSuggestionsService::GetDismissedSuggestionsForDebugging( | 114 void ContentSuggestionsService::GetDismissedSuggestionsForDebugging( |
128 Category category, | 115 Category category, |
129 const DismissedSuggestionsCallback& callback) { | 116 const DismissedSuggestionsCallback& callback) { |
130 auto iterator = providers_by_category_.find(category); | 117 auto iterator = providers_by_category_.find(category); |
131 if (iterator != providers_by_category_.end()) | 118 if (iterator != providers_by_category_.end()) |
132 iterator->second->GetDismissedSuggestionsForDebugging(category, callback); | 119 iterator->second->GetDismissedSuggestionsForDebugging(category, callback); |
133 else | 120 else |
134 callback.Run(std::vector<ContentSuggestion>()); | 121 callback.Run(std::vector<ContentSuggestion>()); |
135 } | 122 } |
136 | 123 |
137 void ContentSuggestionsService::ClearDismissedSuggestionsForDebugging( | 124 void ContentSuggestionsService::ClearDismissedSuggestionsForDebugging( |
138 Category category) { | 125 Category category) { |
139 auto iterator = providers_by_category_.find(category); | 126 auto iterator = providers_by_category_.find(category); |
140 if (iterator != providers_by_category_.end()) | 127 if (iterator != providers_by_category_.end()) |
141 iterator->second->ClearDismissedSuggestionsForDebugging(category); | 128 iterator->second->ClearDismissedSuggestionsForDebugging(category); |
142 } | 129 } |
143 | 130 |
144 void ContentSuggestionsService::DismissSuggestion( | 131 void ContentSuggestionsService::DismissSuggestion( |
145 const std::string& suggestion_id) { | 132 const std::string& suggestion_id) { |
146 if (!id_category_map_.count(suggestion_id)) { | 133 Category category = category_factory_.GetCategoryFromUniqueID(suggestion_id); |
147 LOG(WARNING) << "Dismissed unknown suggestion " << suggestion_id; | |
148 return; | |
149 } | |
150 Category category = id_category_map_.at(suggestion_id); | |
151 if (!providers_by_category_.count(category)) { | 134 if (!providers_by_category_.count(category)) { |
152 LOG(WARNING) << "Dismissed suggestion " << suggestion_id | 135 LOG(WARNING) << "Dismissed suggestion " << suggestion_id |
153 << " for unavailable category " << category; | 136 << " for unavailable category " << category; |
154 return; | 137 return; |
155 } | 138 } |
156 providers_by_category_[category]->DismissSuggestion(suggestion_id); | 139 providers_by_category_[category]->DismissSuggestion(suggestion_id); |
157 | 140 |
158 // Remove the suggestion locally. | 141 // Remove the suggestion locally. |
159 bool removed = RemoveSuggestionByID(category, suggestion_id); | 142 bool removed = RemoveSuggestionByID(category, suggestion_id); |
160 DCHECK(removed) << "The dismissed suggestion " << suggestion_id | 143 DCHECK(removed) << "The dismissed suggestion " << suggestion_id |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 void ContentSuggestionsService::OnNewSuggestions( | 175 void ContentSuggestionsService::OnNewSuggestions( |
193 ContentSuggestionsProvider* provider, | 176 ContentSuggestionsProvider* provider, |
194 Category category, | 177 Category category, |
195 std::vector<ContentSuggestion> new_suggestions) { | 178 std::vector<ContentSuggestion> new_suggestions) { |
196 if (RegisterCategoryIfRequired(provider, category)) | 179 if (RegisterCategoryIfRequired(provider, category)) |
197 NotifyCategoryStatusChanged(category); | 180 NotifyCategoryStatusChanged(category); |
198 | 181 |
199 if (!IsCategoryStatusAvailable(provider->GetCategoryStatus(category))) | 182 if (!IsCategoryStatusAvailable(provider->GetCategoryStatus(category))) |
200 return; | 183 return; |
201 | 184 |
202 for (const ContentSuggestion& suggestion : | |
203 suggestions_by_category_[category]) { | |
204 id_category_map_.erase(suggestion.id()); | |
205 } | |
206 | |
207 for (const ContentSuggestion& suggestion : new_suggestions) | |
208 id_category_map_.insert(std::make_pair(suggestion.id(), category)); | |
209 | |
210 suggestions_by_category_[category] = std::move(new_suggestions); | 185 suggestions_by_category_[category] = std::move(new_suggestions); |
211 | 186 |
212 // The positioning of the bookmarks category depends on whether it's empty. | 187 // The positioning of the bookmarks category depends on whether it's empty. |
213 // TODO(treib): Remove this temporary hack, crbug.com/640568. | 188 // TODO(treib): Remove this temporary hack, crbug.com/640568. |
214 if (category.IsKnownCategory(KnownCategories::BOOKMARKS)) | 189 if (category.IsKnownCategory(KnownCategories::BOOKMARKS)) |
215 SortCategories(); | 190 SortCategories(); |
216 | 191 |
217 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions(category)); | 192 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions(category)); |
218 } | 193 } |
219 | 194 |
220 void ContentSuggestionsService::OnCategoryStatusChanged( | 195 void ContentSuggestionsService::OnCategoryStatusChanged( |
221 ContentSuggestionsProvider* provider, | 196 ContentSuggestionsProvider* provider, |
222 Category category, | 197 Category category, |
223 CategoryStatus new_status) { | 198 CategoryStatus new_status) { |
224 if (!IsCategoryStatusAvailable(new_status)) { | 199 if (!IsCategoryStatusAvailable(new_status)) { |
225 for (const ContentSuggestion& suggestion : | |
226 suggestions_by_category_[category]) { | |
227 id_category_map_.erase(suggestion.id()); | |
228 } | |
229 suggestions_by_category_.erase(category); | 200 suggestions_by_category_.erase(category); |
230 } | 201 } |
231 if (new_status == CategoryStatus::NOT_PROVIDED) { | 202 if (new_status == CategoryStatus::NOT_PROVIDED) { |
232 DCHECK(providers_by_category_.find(category) != | 203 DCHECK(providers_by_category_.find(category) != |
233 providers_by_category_.end()); | 204 providers_by_category_.end()); |
234 DCHECK_EQ(provider, providers_by_category_.find(category)->second); | 205 DCHECK_EQ(provider, providers_by_category_.find(category)->second); |
235 DismissCategory(category); | 206 DismissCategory(category); |
236 } else { | 207 } else { |
237 RegisterCategoryIfRequired(provider, category); | 208 RegisterCategoryIfRequired(provider, category); |
238 DCHECK_EQ(new_status, provider->GetCategoryStatus(category)); | 209 DCHECK_EQ(new_status, provider->GetCategoryStatus(category)); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 if (IsCategoryStatusAvailable(provider->GetCategoryStatus(category))) { | 281 if (IsCategoryStatusAvailable(provider->GetCategoryStatus(category))) { |
311 suggestions_by_category_.insert( | 282 suggestions_by_category_.insert( |
312 std::make_pair(category, std::vector<ContentSuggestion>())); | 283 std::make_pair(category, std::vector<ContentSuggestion>())); |
313 } | 284 } |
314 return true; | 285 return true; |
315 } | 286 } |
316 | 287 |
317 bool ContentSuggestionsService::RemoveSuggestionByID( | 288 bool ContentSuggestionsService::RemoveSuggestionByID( |
318 Category category, | 289 Category category, |
319 const std::string& suggestion_id) { | 290 const std::string& suggestion_id) { |
320 id_category_map_.erase(suggestion_id); | |
321 std::vector<ContentSuggestion>* suggestions = | 291 std::vector<ContentSuggestion>* suggestions = |
322 &suggestions_by_category_[category]; | 292 &suggestions_by_category_[category]; |
323 auto position = | 293 auto position = |
324 std::find_if(suggestions->begin(), suggestions->end(), | 294 std::find_if(suggestions->begin(), suggestions->end(), |
325 [&suggestion_id](const ContentSuggestion& suggestion) { | 295 [&suggestion_id](const ContentSuggestion& suggestion) { |
326 return suggestion_id == suggestion.id(); | 296 return suggestion_id == suggestion.id(); |
327 }); | 297 }); |
328 if (position == suggestions->end()) | 298 if (position == suggestions->end()) |
329 return false; | 299 return false; |
330 suggestions->erase(position); | 300 suggestions->erase(position); |
(...skipping 26 matching lines...) Expand all Loading... |
357 if (left.IsKnownCategory(KnownCategories::BOOKMARKS)) | 327 if (left.IsKnownCategory(KnownCategories::BOOKMARKS)) |
358 return false; | 328 return false; |
359 if (right.IsKnownCategory(KnownCategories::BOOKMARKS)) | 329 if (right.IsKnownCategory(KnownCategories::BOOKMARKS)) |
360 return true; | 330 return true; |
361 } | 331 } |
362 return category_factory_.CompareCategories(left, right); | 332 return category_factory_.CompareCategories(left, right); |
363 }); | 333 }); |
364 } | 334 } |
365 | 335 |
366 } // namespace ntp_snippets | 336 } // namespace ntp_snippets |
OLD | NEW |