Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: chrome/browser/metrics/metrics_log_serializer.cc

Issue 26646003: MetricsService: Send a hash of the UMA log in a header. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/metrics/metrics_log_serializer.h" 5 #include "chrome/browser/metrics/metrics_log_serializer.h"
6 6
7 #include <string>
8
7 #include "base/base64.h" 9 #include "base/base64.h"
8 #include "base/md5.h" 10 #include "base/md5.h"
9 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
10 #include "base/prefs/pref_service.h" 12 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/prefs/scoped_user_pref_update.h" 14 #include "chrome/browser/prefs/scoped_user_pref_update.h"
13 #include "chrome/common/pref_names.h" 15 #include "chrome/common/pref_names.h"
14 16
15 namespace { 17 namespace {
16 18
(...skipping 28 matching lines...) Expand all
45 return status; 47 return status;
46 } 48 }
47 49
48 } // namespace 50 } // namespace
49 51
50 52
51 MetricsLogSerializer::MetricsLogSerializer() {} 53 MetricsLogSerializer::MetricsLogSerializer() {}
52 54
53 MetricsLogSerializer::~MetricsLogSerializer() {} 55 MetricsLogSerializer::~MetricsLogSerializer() {}
54 56
55 void MetricsLogSerializer::SerializeLogs(const std::vector<std::string>& logs, 57 void MetricsLogSerializer::SerializeLogs(
56 MetricsLogManager::LogType log_type) { 58 const std::vector<MetricsLogManager::SerializedLog>& logs,
59 MetricsLogManager::LogType log_type) {
57 PrefService* local_state = g_browser_process->local_state(); 60 PrefService* local_state = g_browser_process->local_state();
58 DCHECK(local_state); 61 DCHECK(local_state);
59 const char* pref = NULL; 62 const char* pref = NULL;
60 size_t store_length_limit = 0; 63 size_t store_length_limit = 0;
61 switch (log_type) { 64 switch (log_type) {
62 case MetricsLogManager::INITIAL_LOG: 65 case MetricsLogManager::INITIAL_LOG:
63 pref = prefs::kMetricsInitialLogs; 66 pref = prefs::kMetricsInitialLogs;
64 store_length_limit = kInitialLogsPersistLimit; 67 store_length_limit = kInitialLogsPersistLimit;
65 break; 68 break;
66 case MetricsLogManager::ONGOING_LOG: 69 case MetricsLogManager::ONGOING_LOG:
67 pref = prefs::kMetricsOngoingLogs; 70 pref = prefs::kMetricsOngoingLogs;
68 store_length_limit = kOngoingLogsPersistLimit; 71 store_length_limit = kOngoingLogsPersistLimit;
69 break; 72 break;
70 case MetricsLogManager::NO_LOG: 73 case MetricsLogManager::NO_LOG:
71 NOTREACHED(); 74 NOTREACHED();
72 return; 75 return;
73 }; 76 };
74 77
75 ListPrefUpdate update(local_state, pref); 78 ListPrefUpdate update(local_state, pref);
76 WriteLogsToPrefList(logs, store_length_limit, kStorageByteLimitPerLogType, 79 WriteLogsToPrefList(logs, store_length_limit, kStorageByteLimitPerLogType,
77 update.Get()); 80 update.Get());
78 } 81 }
79 82
80 void MetricsLogSerializer::DeserializeLogs(MetricsLogManager::LogType log_type, 83 void MetricsLogSerializer::DeserializeLogs(
81 std::vector<std::string>* logs) { 84 MetricsLogManager::LogType log_type,
85 std::vector<MetricsLogManager::SerializedLog>* logs) {
82 DCHECK(logs); 86 DCHECK(logs);
83 PrefService* local_state = g_browser_process->local_state(); 87 PrefService* local_state = g_browser_process->local_state();
84 DCHECK(local_state); 88 DCHECK(local_state);
85 89
86 const char* pref; 90 const char* pref;
87 if (log_type == MetricsLogManager::INITIAL_LOG) 91 if (log_type == MetricsLogManager::INITIAL_LOG)
88 pref = prefs::kMetricsInitialLogs; 92 pref = prefs::kMetricsInitialLogs;
89 else 93 else
90 pref = prefs::kMetricsOngoingLogs; 94 pref = prefs::kMetricsOngoingLogs;
91 95
92 const ListValue* unsent_logs = local_state->GetList(pref); 96 const ListValue* unsent_logs = local_state->GetList(pref);
93 ReadLogsFromPrefList(*unsent_logs, logs); 97 ReadLogsFromPrefList(*unsent_logs, logs);
94 } 98 }
95 99
96 // static 100 // static
97 void MetricsLogSerializer::WriteLogsToPrefList( 101 void MetricsLogSerializer::WriteLogsToPrefList(
98 const std::vector<std::string>& local_list, 102 const std::vector<MetricsLogManager::SerializedLog>& local_list,
99 size_t list_length_limit, 103 size_t list_length_limit,
100 size_t byte_limit, 104 size_t byte_limit,
101 base::ListValue* list) { 105 base::ListValue* list) {
102 // One of the limit arguments must be non-zero. 106 // One of the limit arguments must be non-zero.
103 DCHECK(list_length_limit > 0 || byte_limit > 0); 107 DCHECK(list_length_limit > 0 || byte_limit > 0);
104 108
105 list->Clear(); 109 list->Clear();
106 if (local_list.size() == 0) 110 if (local_list.size() == 0)
107 return; 111 return;
108 112
109 size_t start = 0; 113 size_t start = 0;
110 // If there are too many logs, keep the most recent logs up to the length 114 // If there are too many logs, keep the most recent logs up to the length
111 // limit, and at least to the minimum number of bytes. 115 // limit, and at least to the minimum number of bytes.
112 if (local_list.size() > list_length_limit) { 116 if (local_list.size() > list_length_limit) {
113 start = local_list.size(); 117 start = local_list.size();
114 size_t bytes_used = 0; 118 size_t bytes_used = 0;
115 for (std::vector<std::string>::const_reverse_iterator 119 for (std::vector<MetricsLogManager::SerializedLog>::const_reverse_iterator
116 it = local_list.rbegin(); it != local_list.rend(); ++it) { 120 it = local_list.rbegin(); it != local_list.rend(); ++it) {
117 size_t log_size = it->length(); 121 size_t log_size = it->log_text.length();
118 if (bytes_used >= byte_limit && 122 if (bytes_used >= byte_limit &&
119 (local_list.size() - start) >= list_length_limit) 123 (local_list.size() - start) >= list_length_limit)
120 break; 124 break;
121 bytes_used += log_size; 125 bytes_used += log_size;
122 --start; 126 --start;
123 } 127 }
124 } 128 }
125 DCHECK_LT(start, local_list.size()); 129 DCHECK_LT(start, local_list.size());
126 if (start >= local_list.size()) 130 if (start >= local_list.size())
127 return; 131 return;
128 132
129 // Store size at the beginning of the list. 133 // Store size at the beginning of the list.
130 list->Append(Value::CreateIntegerValue(local_list.size() - start)); 134 list->Append(Value::CreateIntegerValue(local_list.size() - start));
131 135
132 base::MD5Context ctx; 136 base::MD5Context ctx;
133 base::MD5Init(&ctx); 137 base::MD5Init(&ctx);
134 std::string encoded_log; 138 std::string encoded_log;
135 for (std::vector<std::string>::const_iterator it = local_list.begin() + start; 139 std::vector<MetricsLogManager::SerializedLog>::const_iterator it;
Ilya Sherman 2013/10/16 18:26:14 nit: Please keep this scoped within the for loop.
Alexei Svitkine (slow) 2013/10/16 19:31:46 Done.
136 it != local_list.end(); ++it) { 140 for (it = local_list.begin() + start; it != local_list.end(); ++it) {
137 // We encode the compressed log as Value::CreateStringValue() expects to 141 // We encode the compressed log as Value::CreateStringValue() expects to
138 // take a valid UTF8 string. 142 // take a valid UTF8 string.
139 if (!base::Base64Encode(*it, &encoded_log)) { 143 if (!base::Base64Encode(it->log_text, &encoded_log)) {
140 list->Clear(); 144 list->Clear();
141 return; 145 return;
142 } 146 }
143 base::MD5Update(&ctx, encoded_log); 147 base::MD5Update(&ctx, encoded_log);
144 list->Append(Value::CreateStringValue(encoded_log)); 148 list->Append(Value::CreateStringValue(encoded_log));
145 } 149 }
146 150
147 // Append hash to the end of the list. 151 // Append hash to the end of the list.
148 base::MD5Digest digest; 152 base::MD5Digest digest;
149 base::MD5Final(&digest, &ctx); 153 base::MD5Final(&digest, &ctx);
150 list->Append(Value::CreateStringValue(base::MD5DigestToBase16(digest))); 154 list->Append(Value::CreateStringValue(base::MD5DigestToBase16(digest)));
151 DCHECK(list->GetSize() >= 3); // Minimum of 3 elements (size, data, hash). 155 DCHECK(list->GetSize() >= 3); // Minimum of 3 elements (size, data, hash).
152 } 156 }
153 157
154 // static 158 // static
155 MetricsLogSerializer::LogReadStatus MetricsLogSerializer::ReadLogsFromPrefList( 159 MetricsLogSerializer::LogReadStatus MetricsLogSerializer::ReadLogsFromPrefList(
156 const ListValue& list, 160 const ListValue& list,
157 std::vector<std::string>* local_list) { 161 std::vector<MetricsLogManager::SerializedLog>* local_list) {
158 if (list.GetSize() == 0) 162 if (list.GetSize() == 0)
159 return MakeRecallStatusHistogram(LIST_EMPTY); 163 return MakeRecallStatusHistogram(LIST_EMPTY);
160 if (list.GetSize() < 3) 164 if (list.GetSize() < 3)
161 return MakeRecallStatusHistogram(LIST_SIZE_TOO_SMALL); 165 return MakeRecallStatusHistogram(LIST_SIZE_TOO_SMALL);
162 166
163 // The size is stored at the beginning of the list. 167 // The size is stored at the beginning of the list.
164 int size; 168 int size;
165 bool valid = (*list.begin())->GetAsInteger(&size); 169 bool valid = (*list.begin())->GetAsInteger(&size);
166 if (!valid) 170 if (!valid)
167 return MakeRecallStatusHistogram(LIST_SIZE_MISSING); 171 return MakeRecallStatusHistogram(LIST_SIZE_MISSING);
(...skipping 19 matching lines...) Expand all
187 ++it, ++local_index) { 191 ++it, ++local_index) {
188 bool valid = (*it)->GetAsString(&encoded_log); 192 bool valid = (*it)->GetAsString(&encoded_log);
189 if (!valid) { 193 if (!valid) {
190 local_list->clear(); 194 local_list->clear();
191 return MakeRecallStatusHistogram(LOG_STRING_CORRUPTION); 195 return MakeRecallStatusHistogram(LOG_STRING_CORRUPTION);
192 } 196 }
193 197
194 base::MD5Update(&ctx, encoded_log); 198 base::MD5Update(&ctx, encoded_log);
195 199
196 DCHECK_LT(local_index, local_list->size()); 200 DCHECK_LT(local_index, local_list->size());
197 std::string& decoded_log = (*local_list)[local_index]; 201 MetricsLogManager::SerializedLog* decoded_log = &(*local_list)[local_index];
198 if (!base::Base64Decode(encoded_log, &decoded_log)) { 202 if (!base::Base64Decode(encoded_log, &decoded_log->log_text)) {
199 local_list->clear(); 203 local_list->clear();
200 return MakeRecallStatusHistogram(DECODE_FAIL); 204 return MakeRecallStatusHistogram(DECODE_FAIL);
201 } 205 }
206 decoded_log->UpdateHash();
202 } 207 }
203 208
204 // Verify checksum. 209 // Verify checksum.
205 base::MD5Digest digest; 210 base::MD5Digest digest;
206 base::MD5Final(&digest, &ctx); 211 base::MD5Final(&digest, &ctx);
207 std::string recovered_md5; 212 std::string recovered_md5;
208 // We store the hash at the end of the list. 213 // We store the hash at the end of the list.
209 valid = (*(list.end() - 1))->GetAsString(&recovered_md5); 214 valid = (*(list.end() - 1))->GetAsString(&recovered_md5);
210 if (!valid) { 215 if (!valid) {
211 local_list->clear(); 216 local_list->clear();
212 return MakeRecallStatusHistogram(CHECKSUM_STRING_CORRUPTION); 217 return MakeRecallStatusHistogram(CHECKSUM_STRING_CORRUPTION);
213 } 218 }
214 if (recovered_md5 != base::MD5DigestToBase16(digest)) { 219 if (recovered_md5 != base::MD5DigestToBase16(digest)) {
215 local_list->clear(); 220 local_list->clear();
216 return MakeRecallStatusHistogram(CHECKSUM_CORRUPTION); 221 return MakeRecallStatusHistogram(CHECKSUM_CORRUPTION);
217 } 222 }
218 return MakeRecallStatusHistogram(RECALL_SUCCESS); 223 return MakeRecallStatusHistogram(RECALL_SUCCESS);
219 } 224 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698