| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/ntp_snippets_service.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 8 #include <utility> |
| 9 |
| 7 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 8 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 10 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 11 #include "base/location.h" | 14 #include "base/location.h" |
| 12 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 13 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/task_runner_util.h" | 17 #include "base/task_runner_util.h" |
| 15 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 16 #include "base/values.h" | 19 #include "base/values.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 base::TimeDelta GetFetchingIntervalWifi() { | 60 base::TimeDelta GetFetchingIntervalWifi() { |
| 58 return GetFetchingInterval(switches::kFetchingIntervalWifiSeconds, | 61 return GetFetchingInterval(switches::kFetchingIntervalWifiSeconds, |
| 59 kFetchingIntervalWifiSeconds); | 62 kFetchingIntervalWifiSeconds); |
| 60 } | 63 } |
| 61 | 64 |
| 62 base::TimeDelta GetFetchingIntervalFallback() { | 65 base::TimeDelta GetFetchingIntervalFallback() { |
| 63 return GetFetchingInterval(switches::kFetchingIntervalFallbackSeconds, | 66 return GetFetchingInterval(switches::kFetchingIntervalFallbackSeconds, |
| 64 kFetchingIntervalFallbackSeconds); | 67 kFetchingIntervalFallbackSeconds); |
| 65 } | 68 } |
| 66 | 69 |
| 67 std::vector<std::string> GetSuggestionsHosts( | 70 // Extracts the hosts from |suggestions| and returns them in a set. |
| 71 std::set<std::string> GetSuggestionsHosts( |
| 68 const SuggestionsProfile& suggestions) { | 72 const SuggestionsProfile& suggestions) { |
| 69 std::vector<std::string> hosts; | 73 std::set<std::string> hosts; |
| 70 for (int i = 0; i < suggestions.suggestions_size(); ++i) { | 74 for (int i = 0; i < suggestions.suggestions_size(); ++i) { |
| 71 const ChromeSuggestion& suggestion = suggestions.suggestions(i); | 75 const ChromeSuggestion& suggestion = suggestions.suggestions(i); |
| 72 GURL url(suggestion.url()); | 76 GURL url(suggestion.url()); |
| 73 if (url.is_valid()) | 77 if (url.is_valid()) |
| 74 hosts.push_back(url.host()); | 78 hosts.insert(url.host()); |
| 75 } | 79 } |
| 76 return hosts; | 80 return hosts; |
| 77 } | 81 } |
| 78 | 82 |
| 79 const char kContentInfo[] = "contentInfo"; | 83 const char kContentInfo[] = "contentInfo"; |
| 80 | 84 |
| 81 // Parses snippets from |list| and adds them to |snippets|. Returns true on | 85 // Parses snippets from |list| and adds them to |snippets|. Returns true on |
| 82 // success, false if anything went wrong. | 86 // success, false if anything went wrong. |
| 83 bool AddSnippetsFromListValue(const base::ListValue& list, | 87 bool AddSnippetsFromListValue(const base::ListValue& list, |
| 84 NTPSnippetsService::NTPSnippetStorage* snippets) { | 88 NTPSnippetsService::NTPSnippetStorage* snippets) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 snippets_fetcher_subscription_ = snippets_fetcher_->AddCallback(base::Bind( | 136 snippets_fetcher_subscription_ = snippets_fetcher_->AddCallback(base::Bind( |
| 133 &NTPSnippetsService::OnSnippetsDownloaded, base::Unretained(this))); | 137 &NTPSnippetsService::OnSnippetsDownloaded, base::Unretained(this))); |
| 134 } | 138 } |
| 135 | 139 |
| 136 NTPSnippetsService::~NTPSnippetsService() {} | 140 NTPSnippetsService::~NTPSnippetsService() {} |
| 137 | 141 |
| 138 // static | 142 // static |
| 139 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { | 143 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { |
| 140 registry->RegisterListPref(prefs::kSnippets); | 144 registry->RegisterListPref(prefs::kSnippets); |
| 141 registry->RegisterListPref(prefs::kDiscardedSnippets); | 145 registry->RegisterListPref(prefs::kDiscardedSnippets); |
| 146 registry->RegisterListPref(prefs::kSnippetHosts); |
| 142 } | 147 } |
| 143 | 148 |
| 144 void NTPSnippetsService::Init(bool enabled) { | 149 void NTPSnippetsService::Init(bool enabled) { |
| 145 if (enabled) { | 150 if (enabled) { |
| 146 // |suggestions_service_| can be null in tests. | 151 // |suggestions_service_| can be null in tests. |
| 147 if (suggestions_service_) { | 152 if (suggestions_service_) { |
| 148 suggestions_service_subscription_ = suggestions_service_->AddCallback( | 153 suggestions_service_subscription_ = suggestions_service_->AddCallback( |
| 149 base::Bind(&NTPSnippetsService::OnSuggestionsChanged, | 154 base::Bind(&NTPSnippetsService::OnSuggestionsChanged, |
| 150 base::Unretained(this))); | 155 base::Unretained(this))); |
| 151 } | 156 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 if (loaded_) | 211 if (loaded_) |
| 207 observer->NTPSnippetsServiceLoaded(this); | 212 observer->NTPSnippetsServiceLoaded(this); |
| 208 } | 213 } |
| 209 | 214 |
| 210 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { | 215 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { |
| 211 observers_.RemoveObserver(observer); | 216 observers_.RemoveObserver(observer); |
| 212 } | 217 } |
| 213 | 218 |
| 214 void NTPSnippetsService::OnSuggestionsChanged( | 219 void NTPSnippetsService::OnSuggestionsChanged( |
| 215 const SuggestionsProfile& suggestions) { | 220 const SuggestionsProfile& suggestions) { |
| 216 std::vector<std::string> hosts = GetSuggestionsHosts(suggestions); | 221 std::set<std::string> hosts = GetSuggestionsHosts(suggestions); |
| 222 if (hosts == GetSnippetHostsFromPrefs()) |
| 223 return; |
| 217 | 224 |
| 218 // Remove existing snippets that aren't in the suggestions anymore. | 225 // Remove existing snippets that aren't in the suggestions anymore. |
| 219 snippets_.erase( | 226 snippets_.erase( |
| 220 std::remove_if(snippets_.begin(), snippets_.end(), | 227 std::remove_if(snippets_.begin(), snippets_.end(), |
| 221 [&hosts](const scoped_ptr<NTPSnippet>& snippet) { | 228 [&hosts](const scoped_ptr<NTPSnippet>& snippet) { |
| 222 return std::find(hosts.begin(), hosts.end(), | 229 return !hosts.count(snippet->url().host()); |
| 223 snippet->url().host()) == hosts.end(); | |
| 224 }), | 230 }), |
| 225 snippets_.end()); | 231 snippets_.end()); |
| 226 | 232 |
| 227 StoreSnippetsToPrefs(); | 233 StoreSnippetsToPrefs(); |
| 234 StoreSnippetHostsToPrefs(hosts); |
| 228 | 235 |
| 229 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, | 236 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, |
| 230 NTPSnippetsServiceLoaded(this)); | 237 NTPSnippetsServiceLoaded(this)); |
| 231 | 238 |
| 232 FetchSnippetsImpl(hosts); | 239 FetchSnippetsImpl(hosts); |
| 233 } | 240 } |
| 234 | 241 |
| 235 void NTPSnippetsService::OnSnippetsDownloaded( | 242 void NTPSnippetsService::OnSnippetsDownloaded( |
| 236 const std::string& snippets_json) { | 243 const std::string& snippets_json) { |
| 237 parse_json_callback_.Run( | 244 parse_json_callback_.Run( |
| 238 snippets_json, base::Bind(&NTPSnippetsService::OnJsonParsed, | 245 snippets_json, base::Bind(&NTPSnippetsService::OnJsonParsed, |
| 239 weak_ptr_factory_.GetWeakPtr(), snippets_json), | 246 weak_ptr_factory_.GetWeakPtr(), snippets_json), |
| 240 base::Bind(&NTPSnippetsService::OnJsonError, | 247 base::Bind(&NTPSnippetsService::OnJsonError, |
| 241 weak_ptr_factory_.GetWeakPtr(), snippets_json)); | 248 weak_ptr_factory_.GetWeakPtr(), snippets_json)); |
| 242 } | 249 } |
| 243 | 250 |
| 244 void NTPSnippetsService::OnJsonParsed(const std::string& snippets_json, | 251 void NTPSnippetsService::OnJsonParsed(const std::string& snippets_json, |
| 245 scoped_ptr<base::Value> parsed) { | 252 scoped_ptr<base::Value> parsed) { |
| 246 LOG_IF(WARNING, !LoadFromValue(*parsed)) << "Received invalid snippets: " | 253 LOG_IF(WARNING, !LoadFromValue(*parsed)) << "Received invalid snippets: " |
| 247 << snippets_json; | 254 << snippets_json; |
| 248 } | 255 } |
| 249 | 256 |
| 250 void NTPSnippetsService::OnJsonError(const std::string& snippets_json, | 257 void NTPSnippetsService::OnJsonError(const std::string& snippets_json, |
| 251 const std::string& error) { | 258 const std::string& error) { |
| 252 LOG(WARNING) << "Received invalid JSON (" << error << "): " << snippets_json; | 259 LOG(WARNING) << "Received invalid JSON (" << error << "): " << snippets_json; |
| 253 } | 260 } |
| 254 | 261 |
| 255 void NTPSnippetsService::FetchSnippetsImpl( | 262 void NTPSnippetsService::FetchSnippetsImpl( |
| 256 const std::vector<std::string>& hosts) { | 263 const std::set<std::string>& hosts) { |
| 257 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 264 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 258 switches::kDontRestrict)) { | 265 switches::kDontRestrict)) { |
| 259 snippets_fetcher_->FetchSnippets(std::vector<std::string>()); | 266 snippets_fetcher_->FetchSnippets(std::set<std::string>()); |
| 260 return; | 267 return; |
| 261 } | 268 } |
| 262 if (!hosts.empty()) | 269 if (!hosts.empty()) |
| 263 snippets_fetcher_->FetchSnippets(hosts); | 270 snippets_fetcher_->FetchSnippets(hosts); |
| 264 } | 271 } |
| 265 | 272 |
| 266 bool NTPSnippetsService::LoadFromValue(const base::Value& value) { | 273 bool NTPSnippetsService::LoadFromValue(const base::Value& value) { |
| 267 const base::DictionaryValue* top_dict = nullptr; | 274 const base::DictionaryValue* top_dict = nullptr; |
| 268 if (!value.GetAsDictionary(&top_dict)) | 275 if (!value.GetAsDictionary(&top_dict)) |
| 269 return false; | 276 return false; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 *pref_service_->GetList(prefs::kDiscardedSnippets), | 336 *pref_service_->GetList(prefs::kDiscardedSnippets), |
| 330 &discarded_snippets_); | 337 &discarded_snippets_); |
| 331 DCHECK(success) << "Failed to parse discarded snippets from prefs"; | 338 DCHECK(success) << "Failed to parse discarded snippets from prefs"; |
| 332 } | 339 } |
| 333 | 340 |
| 334 void NTPSnippetsService::StoreDiscardedSnippetsToPrefs() { | 341 void NTPSnippetsService::StoreDiscardedSnippetsToPrefs() { |
| 335 pref_service_->Set(prefs::kDiscardedSnippets, | 342 pref_service_->Set(prefs::kDiscardedSnippets, |
| 336 *SnippetsToListValue(discarded_snippets_)); | 343 *SnippetsToListValue(discarded_snippets_)); |
| 337 } | 344 } |
| 338 | 345 |
| 346 std::set<std::string> NTPSnippetsService::GetSnippetHostsFromPrefs() const { |
| 347 std::set<std::string> hosts; |
| 348 const base::ListValue* list = pref_service_->GetList(prefs::kSnippetHosts); |
| 349 for (const base::Value* value : *list) { |
| 350 std::string str; |
| 351 bool success = value->GetAsString(&str); |
| 352 DCHECK(success) << "Failed to parse snippet host from prefs"; |
| 353 hosts.insert(std::move(str)); |
| 354 } |
| 355 return hosts; |
| 356 } |
| 357 |
| 358 void NTPSnippetsService::StoreSnippetHostsToPrefs( |
| 359 const std::set<std::string>& hosts) { |
| 360 base::ListValue list; |
| 361 for (const std::string& host : hosts) |
| 362 list.AppendString(host); |
| 363 pref_service_->Set(prefs::kSnippetHosts, list); |
| 364 } |
| 365 |
| 339 bool NTPSnippetsService::HasDiscardedSnippet(const GURL& url) const { | 366 bool NTPSnippetsService::HasDiscardedSnippet(const GURL& url) const { |
| 340 auto it = std::find_if(discarded_snippets_.begin(), discarded_snippets_.end(), | 367 auto it = std::find_if(discarded_snippets_.begin(), discarded_snippets_.end(), |
| 341 [&url](const scoped_ptr<NTPSnippet>& snippet) { | 368 [&url](const scoped_ptr<NTPSnippet>& snippet) { |
| 342 return snippet->url() == url; | 369 return snippet->url() == url; |
| 343 }); | 370 }); |
| 344 return it != discarded_snippets_.end(); | 371 return it != discarded_snippets_.end(); |
| 345 } | 372 } |
| 346 | 373 |
| 347 void NTPSnippetsService::RemoveExpiredSnippets() { | 374 void NTPSnippetsService::RemoveExpiredSnippets() { |
| 348 base::Time expiry = base::Time::Now(); | 375 base::Time expiry = base::Time::Now(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 379 if (snippet->expiry_date() < next_expiry) | 406 if (snippet->expiry_date() < next_expiry) |
| 380 next_expiry = snippet->expiry_date(); | 407 next_expiry = snippet->expiry_date(); |
| 381 } | 408 } |
| 382 DCHECK_GT(next_expiry, expiry); | 409 DCHECK_GT(next_expiry, expiry); |
| 383 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, | 410 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, |
| 384 base::Bind(&NTPSnippetsService::RemoveExpiredSnippets, | 411 base::Bind(&NTPSnippetsService::RemoveExpiredSnippets, |
| 385 base::Unretained(this))); | 412 base::Unretained(this))); |
| 386 } | 413 } |
| 387 | 414 |
| 388 } // namespace ntp_snippets | 415 } // namespace ntp_snippets |
| OLD | NEW |