1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/data_reduction_proxy/browser/data_reduction_proxy_statistics_prefs.h"
6
7#include "base/bind.h"
8#include "base/location.h"
9#include "base/logging.h"
10#include "base/prefs/pref_service.h"
11#include "base/prefs/scoped_user_pref_update.h"
12#include "base/sequenced_task_runner.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/time/time.h"
15#include "base/values.h"
16
17namespace data_reduction_proxy {
18
19DataReductionProxyStatisticsPrefs::DataReductionProxyStatisticsPrefs(
20    PrefService* prefs,
21    scoped_refptr<base::SequencedTaskRunner> task_runner,
22    const base::TimeDelta& delay)
23    : pref_service_(prefs),
24      task_runner_(task_runner),
25      weak_factory_(this),
26      delay_(delay),
27      delayed_task_posted_(false) {
28  DCHECK(prefs);
29  DCHECK_GE(delay.InMilliseconds(), 0);
30  Init();
31}
32
33DataReductionProxyStatisticsPrefs::~DataReductionProxyStatisticsPrefs() {}
34
35void DataReductionProxyStatisticsPrefs::Init() {
36  if (delay_ == base::TimeDelta())
37    return;
38
39  // Init all int64 prefs.
40  InitInt64Pref(data_reduction_proxy::prefs::
41                kDailyHttpContentLengthLastUpdateDate);
42  InitInt64Pref(data_reduction_proxy::prefs::kHttpReceivedContentLength);
43  InitInt64Pref(data_reduction_proxy::prefs::kHttpOriginalContentLength);
44
45  // Init all list prefs.
46  InitListPref(data_reduction_proxy::prefs::
47               kDailyContentLengthHttpsWithDataReductionProxyEnabled);
48  InitListPref(data_reduction_proxy::prefs::
49               kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
50  InitListPref(data_reduction_proxy::prefs::
51               kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
52  InitListPref(data_reduction_proxy::prefs::
53               kDailyContentLengthUnknownWithDataReductionProxyEnabled);
54  InitListPref(data_reduction_proxy::prefs::
55               kDailyContentLengthViaDataReductionProxy);
56  InitListPref(data_reduction_proxy::prefs::
57               kDailyContentLengthWithDataReductionProxyEnabled);
58  InitListPref(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength);
59  InitListPref(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength);
60  InitListPref(data_reduction_proxy::prefs::
61               kDailyOriginalContentLengthViaDataReductionProxy);
62  InitListPref(data_reduction_proxy::prefs::
63               kDailyOriginalContentLengthWithDataReductionProxyEnabled);
64}
65
66void DataReductionProxyStatisticsPrefs::InitInt64Pref(const char* pref) {
67  int64 pref_value = pref_service_->GetInt64(pref);
68  pref_map_[pref] = pref_value;
69}
70
71void DataReductionProxyStatisticsPrefs::InitListPref(const char* pref) {
72  scoped_ptr<base::ListValue> pref_value = scoped_ptr<base::ListValue>(
73      pref_service_->GetList(pref)->DeepCopy());
74  list_pref_map_.add(pref, pref_value.Pass());
75}
76
77int64 DataReductionProxyStatisticsPrefs::GetInt64(const char* pref_path) {
78  if (delay_ == base::TimeDelta())
79    return pref_service_->GetInt64(pref_path);
80
81  DataReductionProxyPrefMap::iterator iter = pref_map_.find(pref_path);
82  return iter->second;
83}
84
85void DataReductionProxyStatisticsPrefs::SetInt64(const char* pref_path,
86                                                 int64 pref_value) {
87  if (delay_ == base::TimeDelta()) {
88    pref_service_->SetInt64(pref_path, pref_value);
89    return;
90  }
91
92  DelayedWritePrefs();
93  pref_map_[pref_path] = pref_value;
94}
95
96base::ListValue* DataReductionProxyStatisticsPrefs::GetList(
97    const char* pref_path) {
98  if (delay_ == base::TimeDelta())
99    return ListPrefUpdate(pref_service_, pref_path).Get();
100
101  DelayedWritePrefs();
102  return list_pref_map_.get(pref_path);
103}
104
105void DataReductionProxyStatisticsPrefs::WritePrefs() {
106  if (delay_ == base::TimeDelta())
107      return;
108
109  for (DataReductionProxyPrefMap::iterator iter = pref_map_.begin();
110       iter != pref_map_.end(); ++iter) {
111    pref_service_->SetInt64(iter->first, iter->second);
112  }
113
114  for (DataReductionProxyListPrefMap::iterator iter = list_pref_map_.begin();
115       iter != list_pref_map_.end(); ++iter) {
116    TransferList(*(iter->second),
117                 ListPrefUpdate(pref_service_, iter->first).Get());
118  }
119
120  delayed_task_posted_ = false;
121}
122
123void DataReductionProxyStatisticsPrefs::DelayedWritePrefs() {
124  // Only write after the first time posting the task.
125  if (delayed_task_posted_)
126    return;
127
128  task_runner_->PostDelayedTask(
129      FROM_HERE,
130      base::Bind(&DataReductionProxyStatisticsPrefs::WritePrefs,
131                 weak_factory_.GetWeakPtr()),
132                 delay_);
133
134  delayed_task_posted_ = true;
135}
136
137void DataReductionProxyStatisticsPrefs::TransferList(
138    const base::ListValue& from_list,
139    base::ListValue* to_list) {
140  to_list->Clear();
141  for (size_t i = 0; i < from_list.GetSize(); ++i) {
142    to_list->Set(i, new base::StringValue(base::Int64ToString(
143        GetListPrefInt64Value(from_list, i))));
144  }
145}
146
147int64 DataReductionProxyStatisticsPrefs::GetListPrefInt64Value(
148    const base::ListValue& list,
149    size_t index) {
150  std::string string_value;
151  if (!list.GetString(index, &string_value)) {
152    NOTREACHED();
153    return 0;
154  }
155
156  int64 value = 0;
157  bool rv = base::StringToInt64(string_value, &value);
158  DCHECK(rv);
159  return value;
160}
161
162}  // namespace data_reduction_proxy
163