| 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()( | 16 bool ContentSuggestionsService::CompareCategoriesByID::operator()( |
| 17 const Category& left, | 17 const Category& left, |
| 18 const Category& right) const { | 18 const Category& right) const { |
| 19 return left.id() < right.id(); | 19 return left.id() < right.id(); |
| 20 } | 20 } |
| 21 | 21 |
| 22 ContentSuggestionsService::ContentSuggestionsService(State state) | 22 ContentSuggestionsService::ContentSuggestionsService(State state) |
| 23 : state_(state) {} | 23 : state_(state) {} |
| 24 | 24 |
| 25 ContentSuggestionsService::~ContentSuggestionsService() {} | 25 ContentSuggestionsService::~ContentSuggestionsService() {} |
| 26 | 26 |
| 27 void ContentSuggestionsService::Shutdown() { | 27 void ContentSuggestionsService::Shutdown() { |
| 28 DCHECK(providers_by_category_.empty()); | 28 ntp_snippets_service_ = nullptr; |
| 29 DCHECK(categories_.empty()); | 29 id_category_map_.clear(); |
| 30 DCHECK(suggestions_by_category_.empty()); | 30 suggestions_by_category_.clear(); |
| 31 DCHECK(id_category_map_.empty()); | 31 providers_by_category_.clear(); |
| 32 categories_.clear(); |
| 33 providers_.clear(); |
| 32 state_ = State::DISABLED; | 34 state_ = State::DISABLED; |
| 33 FOR_EACH_OBSERVER(Observer, observers_, ContentSuggestionsServiceShutdown()); | 35 FOR_EACH_OBSERVER(Observer, observers_, ContentSuggestionsServiceShutdown()); |
| 34 } | 36 } |
| 35 | 37 |
| 36 CategoryStatus ContentSuggestionsService::GetCategoryStatus( | 38 CategoryStatus ContentSuggestionsService::GetCategoryStatus( |
| 37 Category category) const { | 39 Category category) const { |
| 38 if (state_ == State::DISABLED) { | 40 if (state_ == State::DISABLED) { |
| 39 return CategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED; | 41 return CategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED; |
| 40 } | 42 } |
| 41 | 43 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 | 122 |
| 121 void ContentSuggestionsService::AddObserver(Observer* observer) { | 123 void ContentSuggestionsService::AddObserver(Observer* observer) { |
| 122 observers_.AddObserver(observer); | 124 observers_.AddObserver(observer); |
| 123 } | 125 } |
| 124 | 126 |
| 125 void ContentSuggestionsService::RemoveObserver(Observer* observer) { | 127 void ContentSuggestionsService::RemoveObserver(Observer* observer) { |
| 126 observers_.RemoveObserver(observer); | 128 observers_.RemoveObserver(observer); |
| 127 } | 129 } |
| 128 | 130 |
| 129 void ContentSuggestionsService::RegisterProvider( | 131 void ContentSuggestionsService::RegisterProvider( |
| 130 ContentSuggestionsProvider* provider) { | 132 std::unique_ptr<ContentSuggestionsProvider> provider) { |
| 131 // TODO(pke): When NTPSnippetsService is purely a provider, think about | 133 DCHECK(state_ == State::ENABLED); |
| 132 // removing this state check. | |
| 133 if (state_ == State::DISABLED) | |
| 134 return; | |
| 135 | |
| 136 provider->SetObserver(this); | |
| 137 for (Category category : provider->GetProvidedCategories()) { | 134 for (Category category : provider->GetProvidedCategories()) { |
| 138 DCHECK_NE(CategoryStatus::NOT_PROVIDED, | 135 DCHECK_NE(CategoryStatus::NOT_PROVIDED, |
| 139 provider->GetCategoryStatus(category)); | 136 provider->GetCategoryStatus(category)); |
| 140 RegisterCategoryIfRequired(provider, category); | 137 RegisterCategoryIfRequired(provider.get(), category); |
| 141 NotifyCategoryStatusChanged(category); | 138 NotifyCategoryStatusChanged(category); |
| 142 } | 139 } |
| 140 providers_.push_back(std::move(provider)); |
| 143 } | 141 } |
| 144 | 142 |
| 145 //////////////////////////////////////////////////////////////////////////////// | 143 //////////////////////////////////////////////////////////////////////////////// |
| 146 // Private methods | 144 // Private methods |
| 147 | 145 |
| 148 void ContentSuggestionsService::OnNewSuggestions( | 146 void ContentSuggestionsService::OnNewSuggestions( |
| 149 ContentSuggestionsProvider* provider, | 147 ContentSuggestionsProvider* provider, |
| 150 Category category, | 148 Category category, |
| 151 std::vector<ContentSuggestion> new_suggestions) { | 149 std::vector<ContentSuggestion> new_suggestions) { |
| 152 if (RegisterCategoryIfRequired(provider, category)) { | 150 if (RegisterCategoryIfRequired(provider, category)) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 providers_by_category_.erase(providers_it); | 183 providers_by_category_.erase(providers_it); |
| 186 categories_.erase( | 184 categories_.erase( |
| 187 std::find(categories_.begin(), categories_.end(), category)); | 185 std::find(categories_.begin(), categories_.end(), category)); |
| 188 } else { | 186 } else { |
| 189 RegisterCategoryIfRequired(provider, category); | 187 RegisterCategoryIfRequired(provider, category); |
| 190 DCHECK_EQ(new_status, provider->GetCategoryStatus(category)); | 188 DCHECK_EQ(new_status, provider->GetCategoryStatus(category)); |
| 191 } | 189 } |
| 192 NotifyCategoryStatusChanged(category); | 190 NotifyCategoryStatusChanged(category); |
| 193 } | 191 } |
| 194 | 192 |
| 195 void ContentSuggestionsService::OnProviderShutdown( | |
| 196 ContentSuggestionsProvider* provider) { | |
| 197 for (Category category : provider->GetProvidedCategories()) { | |
| 198 auto iterator = std::find(categories_.begin(), categories_.end(), category); | |
| 199 DCHECK(iterator != categories_.end()); | |
| 200 categories_.erase(iterator); | |
| 201 for (const ContentSuggestion& suggestion : | |
| 202 suggestions_by_category_[category]) { | |
| 203 id_category_map_.erase(suggestion.id()); | |
| 204 } | |
| 205 suggestions_by_category_.erase(category); | |
| 206 providers_by_category_.erase(category); | |
| 207 NotifyCategoryStatusChanged(category); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 bool ContentSuggestionsService::RegisterCategoryIfRequired( | 193 bool ContentSuggestionsService::RegisterCategoryIfRequired( |
| 212 ContentSuggestionsProvider* provider, | 194 ContentSuggestionsProvider* provider, |
| 213 Category category) { | 195 Category category) { |
| 214 auto it = providers_by_category_.find(category); | 196 auto it = providers_by_category_.find(category); |
| 215 if (it != providers_by_category_.end()) { | 197 if (it != providers_by_category_.end()) { |
| 216 DCHECK_EQ(it->second, provider); | 198 DCHECK_EQ(it->second, provider); |
| 217 return false; | 199 return false; |
| 218 } | 200 } |
| 219 | 201 |
| 220 providers_by_category_[category] = provider; | 202 providers_by_category_[category] = provider; |
| 221 categories_.push_back(category); | 203 categories_.push_back(category); |
| 222 std::sort(categories_.begin(), categories_.end(), | 204 std::sort(categories_.begin(), categories_.end(), |
| 223 [this](const Category& left, const Category& right) { | 205 [this](const Category& left, const Category& right) { |
| 224 return category_factory_.CompareCategories(left, right); | 206 return category_factory_.CompareCategories(left, right); |
| 225 }); | 207 }); |
| 226 if (IsCategoryStatusAvailable(provider->GetCategoryStatus(category))) { | 208 if (IsCategoryStatusAvailable(provider->GetCategoryStatus(category))) { |
| 227 suggestions_by_category_.insert( | 209 suggestions_by_category_.insert( |
| 228 std::make_pair(category, std::vector<ContentSuggestion>())); | 210 std::make_pair(category, std::vector<ContentSuggestion>())); |
| 229 } | 211 } |
| 230 return true; | 212 return true; |
| 231 } | 213 } |
| 232 | 214 |
| 233 void ContentSuggestionsService::NotifyCategoryStatusChanged(Category category) { | 215 void ContentSuggestionsService::NotifyCategoryStatusChanged(Category category) { |
| 234 FOR_EACH_OBSERVER( | 216 FOR_EACH_OBSERVER( |
| 235 Observer, observers_, | 217 Observer, observers_, |
| 236 OnCategoryStatusChanged(category, GetCategoryStatus(category))); | 218 OnCategoryStatusChanged(category, GetCategoryStatus(category))); |
| 237 } | 219 } |
| 238 | 220 |
| 239 } // namespace ntp_snippets | 221 } // namespace ntp_snippets |
| OLD | NEW |