Index: chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc |
diff --git a/chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc b/chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9025ae372fd4d85dd57d98d5df03099c8d396799 |
--- /dev/null |
+++ b/chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc |
@@ -0,0 +1,178 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/safe_browsing/incident_reporting/platform_state_store.h" |
+ |
+#include "base/values.h" |
+ |
+#if defined(USE_PLATFORM_STATE_STORE) |
+ |
+#include "base/metrics/histogram_macros.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "chrome/browser/safe_browsing/incident_reporting/state_store_data.pb.h" |
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h" |
+ |
+#endif // USE_PLATFORM_STATE_STORE |
+ |
+namespace safe_browsing { |
+namespace platform_state_store { |
+ |
+#if defined(USE_PLATFORM_STATE_STORE) |
+ |
+namespace { |
+ |
+using google::protobuf::RepeatedPtrField; |
+ |
+// Copies the (key, digest) pairs from |keys_and_digests| (a dict of string |
Cait (Slow)
2015/08/18 18:19:45
It might be helpful to explain at the beginning of
|
+// values) to the |incidents| protobuf. |
+void KeysAndDigestsToProtobuf( |
+ const base::DictionaryValue& keys_and_digests, |
+ RepeatedPtrField<StateStoreData::Incident>* incidents) { |
+ for (base::DictionaryValue::Iterator iter(keys_and_digests); !iter.IsAtEnd(); |
+ iter.Advance()) { |
+ const base::StringValue* digest_value = nullptr; |
+ if (!iter.value().GetAsString(&digest_value)) { |
+ NOTREACHED(); |
+ continue; |
+ } |
+ uint32_t digest = 0; |
+ if (!base::StringToUint(digest_value->GetString(), &digest)) { |
+ NOTREACHED(); |
+ continue; |
+ } |
+ StateStoreData::Incident* incident = incidents->Add(); |
+ incident->set_key(iter.key()); |
+ incident->set_digest(digest); |
+ } |
+} |
+ |
+// Copies the (type, dict) pairs from |incidents_sent| (a dict of dict values) |
+// to the |typed_incidents| protobuf. |
+void IncidentsSentToProtobuf( |
+ const base::DictionaryValue& incidents_sent, |
+ RepeatedPtrField<StateStoreData::TypedIncidents>* typed_incidents) { |
+ for (base::DictionaryValue::Iterator iter(incidents_sent); !iter.IsAtEnd(); |
+ iter.Advance()) { |
+ const base::DictionaryValue* keys_and_digests = nullptr; |
+ if (!iter.value().GetAsDictionary(&keys_and_digests)) { |
+ NOTREACHED(); |
+ continue; |
+ } |
+ if (keys_and_digests->empty()) |
+ continue; |
+ int incident_type = 0; |
+ if (!base::StringToInt(iter.key(), &incident_type)) { |
+ NOTREACHED(); |
+ continue; |
+ } |
+ StateStoreData::TypedIncidents* incidents = typed_incidents->Add(); |
+ incidents->set_type(incident_type); |
+ KeysAndDigestsToProtobuf(*keys_and_digests, incidents->mutable_incident()); |
+ } |
+} |
+ |
+// Copies the (key, digest) pairs for a specific incident type into |type_dict| |
+// (a dict of string values). |
+void RestoreOfTypeFromProtobuf( |
+ const RepeatedPtrField<StateStoreData::Incident>& incidents, |
+ base::DictionaryValue* type_dict) { |
+ for (const auto& incident : incidents) { |
+ if (!incident.has_key() || !incident.has_digest()) |
+ continue; |
+ type_dict->SetStringWithoutPathExpansion( |
+ incident.key(), base::UintToString(incident.digest())); |
+ } |
+} |
+ |
+// Copies the (type, dict) pairs into |value_dict| (a dict of dict values). |
+void RestoreFromProtobuf( |
+ const RepeatedPtrField<StateStoreData::TypedIncidents>& typed_incidents, |
+ base::DictionaryValue* value_dict) { |
+ for (const auto& incidents : typed_incidents) { |
+ if (!incidents.has_type() || incidents.incident_size() == 0) |
+ continue; |
+ std::string type_string(base::IntToString(incidents.type())); |
+ base::DictionaryValue* type_dict = nullptr; |
+ if (!value_dict->GetDictionaryWithoutPathExpansion(type_string, |
+ &type_dict)) { |
+ type_dict = new base::DictionaryValue(); |
+ value_dict->SetWithoutPathExpansion(type_string, type_dict); |
+ } |
+ RestoreOfTypeFromProtobuf(incidents.incident(), type_dict); |
+ } |
+} |
+ |
+} // namespace |
+ |
+#endif // USE_PLATFORM_STATE_STORE |
+ |
+scoped_ptr<base::DictionaryValue> Load(Profile* profile) { |
+#if defined(USE_PLATFORM_STATE_STORE) |
+ scoped_ptr<base::DictionaryValue> value_dict(new base::DictionaryValue()); |
+ std::string data; |
+ PlatformStateStoreLoadResult result = ReadStoreData(profile, &data); |
+ if (result == PlatformStateStoreLoadResult::SUCCESS) |
+ result = DeserializeIncidentsSent(data, value_dict.get()); |
+ switch (result) { |
+ case PlatformStateStoreLoadResult::SUCCESS: |
+ case PlatformStateStoreLoadResult::CLEARED_DATA: |
+ case PlatformStateStoreLoadResult::CLEARED_NO_DATA: |
+ // Return a (possibly empty) dictionary for the success cases. |
+ break; |
+ case PlatformStateStoreLoadResult::DATA_CLEAR_FAILED: |
+ case PlatformStateStoreLoadResult::OPEN_FAILED: |
+ case PlatformStateStoreLoadResult::READ_FAILED: |
+ case PlatformStateStoreLoadResult::PARSE_ERROR: |
+ // Return null for all error cases. |
+ value_dict.reset(); |
+ break; |
+ } |
+ UMA_HISTOGRAM_ENUMERATION( |
+ "SBIRS.PSSLoadResult", static_cast<uint32_t>(result), |
+ static_cast<uint32_t>(PlatformStateStoreLoadResult::NUM_RESULTS)); |
+ return value_dict.Pass(); |
+#else |
+ return scoped_ptr<base::DictionaryValue>(); |
+#endif |
+} |
+ |
+void Store(Profile* profile, const base::DictionaryValue* incidents_sent) { |
+#if defined(USE_PLATFORM_STATE_STORE) |
+ std::string data; |
+ SerializeIncidentsSent(incidents_sent, &data); |
+ UMA_HISTOGRAM_COUNTS("SBIRS.PSSDataStoreSize", data.size()); |
+ WriteStoreData(profile, data); |
+#endif |
+} |
+ |
+#if defined(USE_PLATFORM_STATE_STORE) |
+ |
+void SerializeIncidentsSent(const base::DictionaryValue* incidents_sent, |
+ std::string* data) { |
+ StateStoreData store_data; |
+ |
+ IncidentsSentToProtobuf(*incidents_sent, |
+ store_data.mutable_typed_incidents()); |
+ store_data.SerializeToString(data); |
+} |
+ |
+PlatformStateStoreLoadResult DeserializeIncidentsSent( |
+ const std::string& data, |
+ base::DictionaryValue* value_dict) { |
+ StateStoreData store_data; |
+ if (data.empty()) { |
+ value_dict->Clear(); |
+ return PlatformStateStoreLoadResult::SUCCESS; |
+ } |
+ if (!store_data.ParseFromString(data)) |
+ return PlatformStateStoreLoadResult::PARSE_ERROR; |
+ value_dict->Clear(); |
+ RestoreFromProtobuf(store_data.typed_incidents(), value_dict); |
+ return PlatformStateStoreLoadResult::SUCCESS; |
+} |
+ |
+#endif // USE_PLATFORM_STATE_STORE |
+ |
+} // namespace platform_state_store |
+} // namespace safe_browsing |