1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/suggestions/suggestions_store.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string>
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/base64.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/prefs/pref_service.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/time/time.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/suggestions/suggestions_pref_names.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace suggestions {
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SuggestionsStore::SuggestionsStore(PrefService* profile_prefs)
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : pref_service_(profile_prefs) {
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(profile_prefs);
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SuggestionsStore::~SuggestionsStore() {}
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SuggestionsStore::LoadSuggestions(SuggestionsProfile* suggestions) {
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(suggestions);
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string base64_suggestions_data =
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pref_service_->GetString(prefs::kSuggestionsData);
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (base64_suggestions_data.empty()) {
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    suggestions->Clear();
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If the decode process fails, assume the pref value is corrupt and clear it.
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string suggestions_data;
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!base::Base64Decode(base64_suggestions_data, &suggestions_data) ||
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      !suggestions->ParseFromString(suggestions_data)) {
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    VLOG(1) << "Suggestions data in profile pref is corrupt, clearing it.";
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    suggestions->Clear();
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ClearSuggestions();
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Filter expired suggestions and update the stored suggestions if at least
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // one was filtered. Return false if all suggestions are filtered.
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int unfiltered_size = suggestions->suggestions_size();
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  FilterExpiredSuggestions(suggestions);
486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (suggestions->suggestions_size() != unfiltered_size) {
496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!suggestions->suggestions_size()) {
506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      suggestions->Clear();
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ClearSuggestions();
526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else {
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      StoreSuggestions(*suggestions);
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SuggestionsStore::FilterExpiredSuggestions(
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SuggestionsProfile* suggestions) {
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SuggestionsProfile filtered_suggestions;
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int64 now_usec = (base::Time::NowFromSystemTime() - base::Time::UnixEpoch())
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      .ToInternalValue();
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (int i = 0; i < suggestions->suggestions_size(); ++i) {
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ChromeSuggestion* suggestion = suggestions->mutable_suggestions(i);
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!suggestion->has_expiry_ts() || suggestion->expiry_ts() > now_usec) {
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      filtered_suggestions.add_suggestions()->Swap(suggestion);
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  suggestions->Swap(&filtered_suggestions);
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SuggestionsStore::StoreSuggestions(const SuggestionsProfile& suggestions) {
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string suggestions_data;
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!suggestions.SerializeToString(&suggestions_data)) return false;
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string base64_suggestions_data;
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::Base64Encode(suggestions_data, &base64_suggestions_data);
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pref_service_->SetString(prefs::kSuggestionsData, base64_suggestions_data);
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SuggestionsStore::ClearSuggestions() {
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pref_service_->ClearPref(prefs::kSuggestionsData);
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SuggestionsStore::RegisterProfilePrefs(
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  registry->RegisterStringPref(
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      prefs::kSuggestionsData, std::string(),
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace suggestions
100