Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/safe_browsing/incident_reporting/platform_state_store.h " | |
| 6 | |
| 7 #include "base/values.h" | |
| 8 | |
| 9 #if defined(USE_PLATFORM_STATE_STORE) | |
| 10 | |
| 11 #include "base/metrics/histogram_macros.h" | |
| 12 #include "base/strings/string_number_conversions.h" | |
| 13 #include "chrome/browser/safe_browsing/incident_reporting/state_store_data.pb.h" | |
| 14 #include "third_party/protobuf/src/google/protobuf/repeated_field.h" | |
| 15 | |
| 16 #endif // USE_PLATFORM_STATE_STORE | |
| 17 | |
| 18 namespace safe_browsing { | |
| 19 namespace platform_state_store { | |
| 20 | |
| 21 #if defined(USE_PLATFORM_STATE_STORE) | |
| 22 | |
| 23 namespace { | |
| 24 | |
| 25 using google::protobuf::RepeatedPtrField; | |
| 26 | |
| 27 // 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
| |
| 28 // values) to the |incidents| protobuf. | |
| 29 void KeysAndDigestsToProtobuf( | |
| 30 const base::DictionaryValue& keys_and_digests, | |
| 31 RepeatedPtrField<StateStoreData::Incident>* incidents) { | |
| 32 for (base::DictionaryValue::Iterator iter(keys_and_digests); !iter.IsAtEnd(); | |
| 33 iter.Advance()) { | |
| 34 const base::StringValue* digest_value = nullptr; | |
| 35 if (!iter.value().GetAsString(&digest_value)) { | |
| 36 NOTREACHED(); | |
| 37 continue; | |
| 38 } | |
| 39 uint32_t digest = 0; | |
| 40 if (!base::StringToUint(digest_value->GetString(), &digest)) { | |
| 41 NOTREACHED(); | |
| 42 continue; | |
| 43 } | |
| 44 StateStoreData::Incident* incident = incidents->Add(); | |
| 45 incident->set_key(iter.key()); | |
| 46 incident->set_digest(digest); | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 // Copies the (type, dict) pairs from |incidents_sent| (a dict of dict values) | |
| 51 // to the |typed_incidents| protobuf. | |
| 52 void IncidentsSentToProtobuf( | |
| 53 const base::DictionaryValue& incidents_sent, | |
| 54 RepeatedPtrField<StateStoreData::TypedIncidents>* typed_incidents) { | |
| 55 for (base::DictionaryValue::Iterator iter(incidents_sent); !iter.IsAtEnd(); | |
| 56 iter.Advance()) { | |
| 57 const base::DictionaryValue* keys_and_digests = nullptr; | |
| 58 if (!iter.value().GetAsDictionary(&keys_and_digests)) { | |
| 59 NOTREACHED(); | |
| 60 continue; | |
| 61 } | |
| 62 if (keys_and_digests->empty()) | |
| 63 continue; | |
| 64 int incident_type = 0; | |
| 65 if (!base::StringToInt(iter.key(), &incident_type)) { | |
| 66 NOTREACHED(); | |
| 67 continue; | |
| 68 } | |
| 69 StateStoreData::TypedIncidents* incidents = typed_incidents->Add(); | |
| 70 incidents->set_type(incident_type); | |
| 71 KeysAndDigestsToProtobuf(*keys_and_digests, incidents->mutable_incident()); | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 // Copies the (key, digest) pairs for a specific incident type into |type_dict| | |
| 76 // (a dict of string values). | |
| 77 void RestoreOfTypeFromProtobuf( | |
| 78 const RepeatedPtrField<StateStoreData::Incident>& incidents, | |
| 79 base::DictionaryValue* type_dict) { | |
| 80 for (const auto& incident : incidents) { | |
| 81 if (!incident.has_key() || !incident.has_digest()) | |
| 82 continue; | |
| 83 type_dict->SetStringWithoutPathExpansion( | |
| 84 incident.key(), base::UintToString(incident.digest())); | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 // Copies the (type, dict) pairs into |value_dict| (a dict of dict values). | |
| 89 void RestoreFromProtobuf( | |
| 90 const RepeatedPtrField<StateStoreData::TypedIncidents>& typed_incidents, | |
| 91 base::DictionaryValue* value_dict) { | |
| 92 for (const auto& incidents : typed_incidents) { | |
| 93 if (!incidents.has_type() || incidents.incident_size() == 0) | |
| 94 continue; | |
| 95 std::string type_string(base::IntToString(incidents.type())); | |
| 96 base::DictionaryValue* type_dict = nullptr; | |
| 97 if (!value_dict->GetDictionaryWithoutPathExpansion(type_string, | |
| 98 &type_dict)) { | |
| 99 type_dict = new base::DictionaryValue(); | |
| 100 value_dict->SetWithoutPathExpansion(type_string, type_dict); | |
| 101 } | |
| 102 RestoreOfTypeFromProtobuf(incidents.incident(), type_dict); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 } // namespace | |
| 107 | |
| 108 #endif // USE_PLATFORM_STATE_STORE | |
| 109 | |
| 110 scoped_ptr<base::DictionaryValue> Load(Profile* profile) { | |
| 111 #if defined(USE_PLATFORM_STATE_STORE) | |
| 112 scoped_ptr<base::DictionaryValue> value_dict(new base::DictionaryValue()); | |
| 113 std::string data; | |
| 114 PlatformStateStoreLoadResult result = ReadStoreData(profile, &data); | |
| 115 if (result == PlatformStateStoreLoadResult::SUCCESS) | |
| 116 result = DeserializeIncidentsSent(data, value_dict.get()); | |
| 117 switch (result) { | |
| 118 case PlatformStateStoreLoadResult::SUCCESS: | |
| 119 case PlatformStateStoreLoadResult::CLEARED_DATA: | |
| 120 case PlatformStateStoreLoadResult::CLEARED_NO_DATA: | |
| 121 // Return a (possibly empty) dictionary for the success cases. | |
| 122 break; | |
| 123 case PlatformStateStoreLoadResult::DATA_CLEAR_FAILED: | |
| 124 case PlatformStateStoreLoadResult::OPEN_FAILED: | |
| 125 case PlatformStateStoreLoadResult::READ_FAILED: | |
| 126 case PlatformStateStoreLoadResult::PARSE_ERROR: | |
| 127 // Return null for all error cases. | |
| 128 value_dict.reset(); | |
| 129 break; | |
| 130 } | |
| 131 UMA_HISTOGRAM_ENUMERATION( | |
| 132 "SBIRS.PSSLoadResult", static_cast<uint32_t>(result), | |
| 133 static_cast<uint32_t>(PlatformStateStoreLoadResult::NUM_RESULTS)); | |
| 134 return value_dict.Pass(); | |
| 135 #else | |
| 136 return scoped_ptr<base::DictionaryValue>(); | |
| 137 #endif | |
| 138 } | |
| 139 | |
| 140 void Store(Profile* profile, const base::DictionaryValue* incidents_sent) { | |
| 141 #if defined(USE_PLATFORM_STATE_STORE) | |
| 142 std::string data; | |
| 143 SerializeIncidentsSent(incidents_sent, &data); | |
| 144 UMA_HISTOGRAM_COUNTS("SBIRS.PSSDataStoreSize", data.size()); | |
| 145 WriteStoreData(profile, data); | |
| 146 #endif | |
| 147 } | |
| 148 | |
| 149 #if defined(USE_PLATFORM_STATE_STORE) | |
| 150 | |
| 151 void SerializeIncidentsSent(const base::DictionaryValue* incidents_sent, | |
| 152 std::string* data) { | |
| 153 StateStoreData store_data; | |
| 154 | |
| 155 IncidentsSentToProtobuf(*incidents_sent, | |
| 156 store_data.mutable_typed_incidents()); | |
| 157 store_data.SerializeToString(data); | |
| 158 } | |
| 159 | |
| 160 PlatformStateStoreLoadResult DeserializeIncidentsSent( | |
| 161 const std::string& data, | |
| 162 base::DictionaryValue* value_dict) { | |
| 163 StateStoreData store_data; | |
| 164 if (data.empty()) { | |
| 165 value_dict->Clear(); | |
| 166 return PlatformStateStoreLoadResult::SUCCESS; | |
| 167 } | |
| 168 if (!store_data.ParseFromString(data)) | |
| 169 return PlatformStateStoreLoadResult::PARSE_ERROR; | |
| 170 value_dict->Clear(); | |
| 171 RestoreFromProtobuf(store_data.typed_incidents(), value_dict); | |
| 172 return PlatformStateStoreLoadResult::SUCCESS; | |
| 173 } | |
| 174 | |
| 175 #endif // USE_PLATFORM_STATE_STORE | |
| 176 | |
| 177 } // namespace platform_state_store | |
| 178 } // namespace safe_browsing | |
| OLD | NEW |