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/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 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "ui/gfx/image/image.h" | 12 #include "ui/gfx/image/image.h" |
| 13 | 13 |
| 14 namespace ntp_snippets { | 14 namespace ntp_snippets { |
| 15 | 15 |
| 16 bool ContentSuggestionsService::CompareCategoriesByID::operator()( | |
| 17 const ContentSuggestionsCategory& left, | |
| 18 const ContentSuggestionsCategory& right) const { | |
| 19 return left.id() < right.id(); | |
| 20 } | |
| 21 | |
| 16 ContentSuggestionsService::ContentSuggestionsService(State state) | 22 ContentSuggestionsService::ContentSuggestionsService(State state) |
| 17 : state_(state) {} | 23 : state_(state) {} |
| 18 | 24 |
| 19 ContentSuggestionsService::~ContentSuggestionsService() {} | 25 ContentSuggestionsService::~ContentSuggestionsService() {} |
| 20 | 26 |
| 21 void ContentSuggestionsService::Shutdown() { | 27 void ContentSuggestionsService::Shutdown() { |
| 22 DCHECK(providers_.empty()); | 28 DCHECK(providers_.empty()); |
| 23 DCHECK(categories_.empty()); | 29 DCHECK(categories_.empty()); |
| 24 DCHECK(suggestions_by_category_.empty()); | 30 DCHECK(suggestions_by_category_.empty()); |
| 25 DCHECK(id_category_map_.empty()); | 31 DCHECK(id_category_map_.empty()); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 51 } | 57 } |
| 52 | 58 |
| 53 void ContentSuggestionsService::FetchSuggestionImage( | 59 void ContentSuggestionsService::FetchSuggestionImage( |
| 54 const std::string& suggestion_id, | 60 const std::string& suggestion_id, |
| 55 const ImageFetchedCallback& callback) { | 61 const ImageFetchedCallback& callback) { |
| 56 if (!id_category_map_.count(suggestion_id)) { | 62 if (!id_category_map_.count(suggestion_id)) { |
| 57 LOG(WARNING) << "Requested image for unknown suggestion " << suggestion_id; | 63 LOG(WARNING) << "Requested image for unknown suggestion " << suggestion_id; |
| 58 callback.Run(suggestion_id, gfx::Image()); | 64 callback.Run(suggestion_id, gfx::Image()); |
| 59 return; | 65 return; |
| 60 } | 66 } |
| 61 ContentSuggestionsCategory category = id_category_map_[suggestion_id]; | 67 ContentSuggestionsCategory category = id_category_map_.at(suggestion_id); |
| 62 if (!providers_.count(category)) { | 68 if (!providers_.count(category)) { |
| 63 LOG(WARNING) << "Requested image for suggestion " << suggestion_id | 69 LOG(WARNING) << "Requested image for suggestion " << suggestion_id |
| 64 << " for unavailable category " << static_cast<int>(category); | 70 << " for unavailable category " << category.id(); |
| 65 callback.Run(suggestion_id, gfx::Image()); | 71 callback.Run(suggestion_id, gfx::Image()); |
| 66 return; | 72 return; |
| 67 } | 73 } |
| 68 providers_[category]->FetchSuggestionImage(suggestion_id, callback); | 74 providers_[category]->FetchSuggestionImage(suggestion_id, callback); |
| 69 } | 75 } |
| 70 | 76 |
| 71 void ContentSuggestionsService::ClearCachedSuggestionsForDebugging() { | 77 void ContentSuggestionsService::ClearCachedSuggestionsForDebugging() { |
| 72 suggestions_by_category_.clear(); | 78 suggestions_by_category_.clear(); |
| 73 id_category_map_.clear(); | 79 id_category_map_.clear(); |
| 74 for (auto& category_provider_pair : providers_) { | 80 for (auto& category_provider_pair : providers_) { |
| 75 category_provider_pair.second->ClearCachedSuggestionsForDebugging(); | 81 category_provider_pair.second->ClearCachedSuggestionsForDebugging(); |
| 76 } | 82 } |
| 77 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions()); | 83 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions()); |
| 78 } | 84 } |
| 79 | 85 |
| 80 void ContentSuggestionsService::ClearDismissedSuggestionsForDebugging() { | 86 void ContentSuggestionsService::ClearDismissedSuggestionsForDebugging() { |
| 81 for (auto& category_provider_pair : providers_) { | 87 for (auto& category_provider_pair : providers_) { |
| 82 category_provider_pair.second->ClearDismissedSuggestionsForDebugging(); | 88 category_provider_pair.second->ClearDismissedSuggestionsForDebugging(); |
| 83 } | 89 } |
| 84 } | 90 } |
| 85 | 91 |
| 86 void ContentSuggestionsService::DismissSuggestion( | 92 void ContentSuggestionsService::DismissSuggestion( |
| 87 const std::string& suggestion_id) { | 93 const std::string& suggestion_id) { |
| 88 if (!id_category_map_.count(suggestion_id)) { | 94 if (!id_category_map_.count(suggestion_id)) { |
| 89 LOG(WARNING) << "Dismissed unknown suggestion " << suggestion_id; | 95 LOG(WARNING) << "Dismissed unknown suggestion " << suggestion_id; |
| 90 return; | 96 return; |
| 91 } | 97 } |
| 92 ContentSuggestionsCategory category = id_category_map_[suggestion_id]; | 98 ContentSuggestionsCategory category = id_category_map_.at(suggestion_id); |
| 93 if (!providers_.count(category)) { | 99 if (!providers_.count(category)) { |
| 94 LOG(WARNING) << "Dismissed suggestion " << suggestion_id | 100 LOG(WARNING) << "Dismissed suggestion " << suggestion_id |
| 95 << " for unavailable category " << static_cast<int>(category); | 101 << " for unavailable category " << category.id(); |
| 96 return; | 102 return; |
| 97 } | 103 } |
| 98 providers_[category]->DismissSuggestion(suggestion_id); | 104 providers_[category]->DismissSuggestion(suggestion_id); |
| 99 | 105 |
| 100 // Remove the suggestion locally. | 106 // Remove the suggestion locally. |
| 101 id_category_map_.erase(suggestion_id); | 107 id_category_map_.erase(suggestion_id); |
| 102 std::vector<ContentSuggestion>* suggestions = | 108 std::vector<ContentSuggestion>* suggestions = |
| 103 &suggestions_by_category_[category]; | 109 &suggestions_by_category_[category]; |
| 104 auto position = | 110 auto position = |
| 105 std::find_if(suggestions->begin(), suggestions->end(), | 111 std::find_if(suggestions->begin(), suggestions->end(), |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 124 void ContentSuggestionsService::RegisterProvider( | 130 void ContentSuggestionsService::RegisterProvider( |
| 125 ContentSuggestionsProvider* provider) { | 131 ContentSuggestionsProvider* provider) { |
| 126 // TODO(pke): When NTPSnippetsService is purely a provider, think about | 132 // TODO(pke): When NTPSnippetsService is purely a provider, think about |
| 127 // removing this state check. | 133 // removing this state check. |
| 128 if (state_ == State::DISABLED) | 134 if (state_ == State::DISABLED) |
| 129 return; | 135 return; |
| 130 | 136 |
| 131 for (ContentSuggestionsCategory category : provider->provided_categories()) { | 137 for (ContentSuggestionsCategory category : provider->provided_categories()) { |
| 132 DCHECK_EQ(0ul, providers_.count(category)); | 138 DCHECK_EQ(0ul, providers_.count(category)); |
| 133 providers_[category] = provider; | 139 providers_[category] = provider; |
| 134 // TODO(pke): In the future, make sure that the categories have some useful | |
| 135 // (maybe constant, at least consistent) ordering for the UI. | |
| 136 categories_.push_back(category); | 140 categories_.push_back(category); |
| 137 if (IsContentSuggestionsCategoryStatusAvailable( | 141 if (IsContentSuggestionsCategoryStatusAvailable( |
| 138 provider->GetCategoryStatus(category))) { | 142 provider->GetCategoryStatus(category))) { |
| 139 suggestions_by_category_[category] = std::vector<ContentSuggestion>(); | 143 suggestions_by_category_[category] = std::vector<ContentSuggestion>(); |
| 140 } | 144 } |
| 141 NotifyCategoryStatusChanged(category); | 145 NotifyCategoryStatusChanged(category); |
| 142 } | 146 } |
| 147 std::sort(categories_.begin(), categories_.end(), | |
| 148 [this](const ContentSuggestionsCategory& left, | |
| 149 const ContentSuggestionsCategory& right) { | |
| 150 return category_factory_.CompareCategories(left, right); | |
| 151 }); | |
| 143 provider->SetObserver(this); | 152 provider->SetObserver(this); |
| 144 } | 153 } |
| 145 | 154 |
| 146 //////////////////////////////////////////////////////////////////////////////// | 155 //////////////////////////////////////////////////////////////////////////////// |
| 147 // Private methods | 156 // Private methods |
| 148 | 157 |
| 149 void ContentSuggestionsService::OnNewSuggestions( | 158 void ContentSuggestionsService::OnNewSuggestions( |
| 150 ContentSuggestionsCategory changed_category, | 159 ContentSuggestionsCategory changed_category, |
| 151 std::vector<ContentSuggestion> new_suggestions) { | 160 std::vector<ContentSuggestion> new_suggestions) { |
| 152 DCHECK(IsCategoryRegistered(changed_category)); | 161 DCHECK(IsCategoryRegistered(changed_category)); |
| 153 | 162 |
| 154 for (const ContentSuggestion& suggestion : | 163 for (const ContentSuggestion& suggestion : |
| 155 suggestions_by_category_[changed_category]) { | 164 suggestions_by_category_[changed_category]) { |
| 156 id_category_map_.erase(suggestion.id()); | 165 id_category_map_.erase(suggestion.id()); |
| 157 } | 166 } |
| 158 | 167 |
| 159 for (const ContentSuggestion& suggestion : new_suggestions) { | 168 for (ContentSuggestion& suggestion : new_suggestions) { |
|
Marc Treib
2016/07/28 11:41:46
Why'd you remove the "const"?
Philipp Keck
2016/07/28 13:50:54
That was unintentional.
| |
| 160 id_category_map_[suggestion.id()] = changed_category; | 169 id_category_map_.insert(std::make_pair(suggestion.id(), changed_category)); |
| 161 } | 170 } |
| 162 | 171 |
| 163 suggestions_by_category_[changed_category] = std::move(new_suggestions); | 172 suggestions_by_category_[changed_category] = std::move(new_suggestions); |
| 164 | 173 |
| 165 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions()); | 174 FOR_EACH_OBSERVER(Observer, observers_, OnNewSuggestions()); |
| 166 } | 175 } |
| 167 | 176 |
| 168 void ContentSuggestionsService::OnCategoryStatusChanged( | 177 void ContentSuggestionsService::OnCategoryStatusChanged( |
| 169 ContentSuggestionsCategory changed_category, | 178 ContentSuggestionsCategory changed_category, |
| 170 ContentSuggestionsCategoryStatus new_status) { | 179 ContentSuggestionsCategoryStatus new_status) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 201 } | 210 } |
| 202 | 211 |
| 203 void ContentSuggestionsService::NotifyCategoryStatusChanged( | 212 void ContentSuggestionsService::NotifyCategoryStatusChanged( |
| 204 ContentSuggestionsCategory category) { | 213 ContentSuggestionsCategory category) { |
| 205 FOR_EACH_OBSERVER( | 214 FOR_EACH_OBSERVER( |
| 206 Observer, observers_, | 215 Observer, observers_, |
| 207 OnCategoryStatusChanged(category, GetCategoryStatus(category))); | 216 OnCategoryStatusChanged(category, GetCategoryStatus(category))); |
| 208 } | 217 } |
| 209 | 218 |
| 210 } // namespace ntp_snippets | 219 } // namespace ntp_snippets |
| OLD | NEW |