OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "services/catalog/entry.h" | 5 #include "services/catalog/entry.h" |
6 | 6 |
7 #include "base/values.h" | 7 #include "base/values.h" |
8 #include "services/catalog/store.h" | 8 #include "services/catalog/store.h" |
9 #include "services/shell/public/cpp/names.h" | 9 #include "services/shell/public/cpp/names.h" |
10 | 10 |
11 namespace catalog { | 11 namespace catalog { |
12 namespace { | 12 namespace { |
13 | 13 |
14 shell::CapabilitySpec BuildCapabilitiesV0(const base::DictionaryValue& value) { | 14 bool ReadStringSet(const base::ListValue& list_value, |
15 shell::CapabilitySpec capabilities; | |
16 base::DictionaryValue::Iterator it(value); | |
17 for (; !it.IsAtEnd(); it.Advance()) { | |
18 const base::ListValue* values = nullptr; | |
19 CHECK(it.value().GetAsList(&values)); | |
20 shell::CapabilityRequest spec; | |
21 for (auto i = values->begin(); i != values->end(); ++i) { | |
22 shell::Interface interface_name; | |
23 const base::Value* v = *i; | |
24 CHECK(v->GetAsString(&interface_name)); | |
25 spec.interfaces.insert(interface_name); | |
26 } | |
27 capabilities.required[it.key()] = spec; | |
28 } | |
29 return capabilities; | |
30 } | |
31 | |
32 void ReadStringSet(const base::ListValue& list_value, | |
33 std::set<std::string>* string_set) { | 15 std::set<std::string>* string_set) { |
34 DCHECK(string_set); | 16 DCHECK(string_set); |
35 for (auto i = list_value.begin(); i != list_value.end(); ++i) { | 17 for (auto i = list_value.begin(); i != list_value.end(); ++i) { |
36 std::string value; | 18 std::string value; |
37 const base::Value* value_value = *i; | 19 const base::Value* value_value = *i; |
38 CHECK(value_value->GetAsString(&value)); | 20 if (!value_value->GetAsString(&value)) { |
| 21 LOG(ERROR) << "Entry::Deserialize: list member must be a string"; |
| 22 return false; |
| 23 } |
39 string_set->insert(value); | 24 string_set->insert(value); |
40 } | 25 } |
| 26 return true; |
41 } | 27 } |
42 | 28 |
43 void ReadStringSetFromValue(const base::Value& value, | 29 bool ReadStringSetFromValue(const base::Value& value, |
44 std::set<std::string>* string_set) { | 30 std::set<std::string>* string_set) { |
45 const base::ListValue* list_value = nullptr; | 31 const base::ListValue* list_value = nullptr; |
46 CHECK(value.GetAsList(&list_value)); | 32 if (!value.GetAsList(&list_value)) { |
47 ReadStringSet(*list_value, string_set); | 33 LOG(ERROR) << "Entry::Deserialize: Value must be a list."; |
| 34 return false; |
| 35 } |
| 36 return ReadStringSet(*list_value, string_set); |
48 } | 37 } |
49 | 38 |
50 void ReadStringSetFromDictionary(const base::DictionaryValue& dictionary, | 39 bool ReadStringSetFromDictionary(const base::DictionaryValue& dictionary, |
51 const std::string& key, | 40 const std::string& key, |
52 std::set<std::string>* string_set) { | 41 std::set<std::string>* string_set) { |
53 const base::ListValue* list_value = nullptr; | 42 const base::ListValue* list_value = nullptr; |
54 if (dictionary.HasKey(key)) | 43 if (dictionary.HasKey(key) && !dictionary.GetList(key, &list_value)) { |
55 CHECK(dictionary.GetList(key, &list_value)); | 44 LOG(ERROR) << "Entry::Deserialize: " << key << " must be a list."; |
| 45 return false; |
| 46 } |
56 if (list_value) | 47 if (list_value) |
57 ReadStringSet(*list_value, string_set); | 48 return ReadStringSet(*list_value, string_set); |
| 49 return true; |
58 } | 50 } |
59 | 51 |
60 shell::CapabilitySpec BuildCapabilitiesV1(const base::DictionaryValue& value) { | 52 bool BuildCapabilities(const base::DictionaryValue& value, |
61 shell::CapabilitySpec capabilities; | 53 shell::CapabilitySpec* capabilities) { |
62 | 54 DCHECK(capabilities); |
63 const base::DictionaryValue* provided_value = nullptr; | 55 const base::DictionaryValue* provided_value = nullptr; |
64 if (value.HasKey(Store::kCapabilities_ProvidedKey)) { | 56 if (value.HasKey(Store::kCapabilities_ProvidedKey) && |
65 CHECK(value.GetDictionary(Store::kCapabilities_ProvidedKey, | 57 !value.GetDictionary(Store::kCapabilities_ProvidedKey, |
66 &provided_value)); | 58 &provided_value)) { |
| 59 LOG(ERROR) << "Entry::Deserialize: " << Store::kCapabilities_ProvidedKey |
| 60 << " must be a dictionary."; |
| 61 return false; |
67 } | 62 } |
68 if (provided_value) { | 63 if (provided_value) { |
69 shell::CapabilityRequest provided; | 64 shell::CapabilityRequest provided; |
70 base::DictionaryValue::Iterator it(*provided_value); | 65 base::DictionaryValue::Iterator it(*provided_value); |
71 for(; !it.IsAtEnd(); it.Advance()) { | 66 for(; !it.IsAtEnd(); it.Advance()) { |
72 shell::Interfaces interfaces; | 67 shell::Interfaces interfaces; |
73 ReadStringSetFromValue(it.value(), &interfaces); | 68 if (!ReadStringSetFromValue(it.value(), &interfaces)) { |
74 capabilities.provided[it.key()] = interfaces; | 69 LOG(ERROR) << "Entry::Deserialize: Invalid interface list in provided " |
| 70 << " classes dictionary"; |
| 71 return false; |
| 72 } |
| 73 capabilities->provided[it.key()] = interfaces; |
75 } | 74 } |
76 } | 75 } |
77 | 76 |
78 const base::DictionaryValue* required_value = nullptr; | 77 const base::DictionaryValue* required_value = nullptr; |
79 if (value.HasKey(Store::kCapabilities_RequiredKey)) { | 78 if (value.HasKey(Store::kCapabilities_RequiredKey) && |
80 CHECK(value.GetDictionary(Store::kCapabilities_RequiredKey, | 79 !value.GetDictionary(Store::kCapabilities_RequiredKey, |
81 &required_value)); | 80 &required_value)) { |
| 81 LOG(ERROR) << "Entry::Deserialize: " << Store::kCapabilities_RequiredKey |
| 82 << " must be a dictionary."; |
| 83 return false; |
82 } | 84 } |
83 if (required_value) { | 85 if (required_value) { |
84 base::DictionaryValue::Iterator it(*required_value); | 86 base::DictionaryValue::Iterator it(*required_value); |
85 for (; !it.IsAtEnd(); it.Advance()) { | 87 for (; !it.IsAtEnd(); it.Advance()) { |
86 shell::CapabilityRequest spec; | 88 shell::CapabilityRequest spec; |
87 const base::DictionaryValue* entry_value = nullptr; | 89 const base::DictionaryValue* entry_value = nullptr; |
88 CHECK(it.value().GetAsDictionary(&entry_value)); | 90 if (!it.value().GetAsDictionary(&entry_value)) { |
89 ReadStringSetFromDictionary( | 91 LOG(ERROR) << "Entry::Deserialize: " << Store::kCapabilities_RequiredKey |
90 *entry_value, Store::kCapabilities_ClassesKey, &spec.classes); | 92 << " must be a dictionary."; |
91 ReadStringSetFromDictionary( | 93 return false; |
92 *entry_value, Store::kCapabilities_InterfacesKey, &spec.interfaces); | 94 } |
93 capabilities.required[it.key()] = spec; | 95 if (!ReadStringSetFromDictionary( |
| 96 *entry_value, Store::kCapabilities_ClassesKey, &spec.classes)) { |
| 97 LOG(ERROR) << "Entry::Deserialize: Invalid classes list in required " |
| 98 << "capabilities dictionary."; |
| 99 return false; |
| 100 } |
| 101 if (!ReadStringSetFromDictionary(*entry_value, |
| 102 Store::kCapabilities_InterfacesKey, |
| 103 &spec.interfaces)) { |
| 104 LOG(ERROR) << "Entry::Deserialize: Invalid interfaces list in required " |
| 105 << "capabilities dictionary."; |
| 106 return false; |
| 107 } |
| 108 capabilities->required[it.key()] = spec; |
94 } | 109 } |
95 } | 110 } |
96 return capabilities; | 111 return true; |
97 } | 112 } |
98 | 113 |
99 } // namespace | 114 } // namespace |
100 | 115 |
101 Entry::Entry() {} | 116 Entry::Entry() {} |
102 Entry::Entry(const std::string& name) | 117 Entry::Entry(const std::string& name) |
103 : name_(name), qualifier_(shell::GetNamePath(name)), display_name_(name) {} | 118 : name_(name), qualifier_(shell::GetNamePath(name)), display_name_(name) {} |
104 Entry::Entry(const Entry& other) = default; | 119 Entry::Entry(const Entry& other) = default; |
105 Entry::~Entry() {} | 120 Entry::~Entry() {} |
106 | 121 |
(...skipping 29 matching lines...) Expand all Loading... |
136 } | 151 } |
137 spec->Set(Store::kCapabilities_RequiredKey, std::move(required)); | 152 spec->Set(Store::kCapabilities_RequiredKey, std::move(required)); |
138 | 153 |
139 value->Set(Store::kCapabilitiesKey, std::move(spec)); | 154 value->Set(Store::kCapabilitiesKey, std::move(spec)); |
140 return value; | 155 return value; |
141 } | 156 } |
142 | 157 |
143 // static | 158 // static |
144 std::unique_ptr<Entry> Entry::Deserialize(const base::DictionaryValue& value) { | 159 std::unique_ptr<Entry> Entry::Deserialize(const base::DictionaryValue& value) { |
145 std::unique_ptr<Entry> entry(new Entry); | 160 std::unique_ptr<Entry> entry(new Entry); |
| 161 |
| 162 // Manifest version. |
146 int manifest_version = 0; | 163 int manifest_version = 0; |
147 if (value.HasKey(Store::kManifestVersionKey)) | 164 if (!value.GetInteger(Store::kManifestVersionKey, &manifest_version)) { |
148 CHECK(value.GetInteger(Store::kManifestVersionKey, &manifest_version)); | 165 LOG(ERROR) << "Entry::Deserialize: " << Store::kManifestVersionKey |
| 166 << " must be an integer."; |
| 167 return nullptr; |
| 168 } |
| 169 if (manifest_version != 1) { |
| 170 LOG(ERROR) << "Entry::Deserialize: Unsupported value of " |
| 171 << Store::kManifestVersionKey << ":" << manifest_version; |
| 172 return nullptr; |
| 173 } |
| 174 |
| 175 // Name. |
149 std::string name_string; | 176 std::string name_string; |
150 if (!value.GetString(Store::kNameKey, &name_string)) { | 177 if (!value.GetString(Store::kNameKey, &name_string)) { |
151 LOG(ERROR) << "Entry::Deserialize: dictionary has no name key"; | 178 LOG(ERROR) << "Entry::Deserialize: dictionary has no " |
| 179 << Store::kNameKey << " key"; |
152 return nullptr; | 180 return nullptr; |
153 } | 181 } |
154 if (!shell::IsValidName(name_string)) { | 182 if (!shell::IsValidName(name_string)) { |
155 LOG(WARNING) << "Entry::Deserialize: " << name_string << " is not a valid " | 183 LOG(ERROR) << "Entry::Deserialize: " << name_string << " is not a valid " |
156 << "Mojo name"; | 184 << "Mojo name"; |
157 return nullptr; | 185 return nullptr; |
158 } | 186 } |
159 entry->set_name(name_string); | 187 entry->set_name(name_string); |
| 188 |
| 189 // Process group. |
160 if (value.HasKey(Store::kQualifierKey)) { | 190 if (value.HasKey(Store::kQualifierKey)) { |
161 std::string qualifier; | 191 std::string qualifier; |
162 CHECK(value.GetString(Store::kQualifierKey, &qualifier)); | 192 if (!value.GetString(Store::kQualifierKey, &qualifier)) { |
| 193 LOG(ERROR) << "Entry::Deserialize: " << Store::kQualifierKey << " must " |
| 194 << "be a string."; |
| 195 return nullptr; |
| 196 } |
163 entry->set_qualifier(qualifier); | 197 entry->set_qualifier(qualifier); |
164 } else { | 198 } else { |
165 entry->set_qualifier(shell::GetNamePath(name_string)); | 199 entry->set_qualifier(shell::GetNamePath(name_string)); |
166 } | 200 } |
| 201 |
| 202 // Human-readable name. |
167 std::string display_name; | 203 std::string display_name; |
168 if (!value.GetString(Store::kDisplayNameKey, &display_name)) { | 204 if (!value.GetString(Store::kDisplayNameKey, &display_name)) { |
169 LOG(WARNING) << "Entry::Deserialize: dictionary has no display_name key"; | 205 LOG(ERROR) << "Entry::Deserialize: dictionary has no " |
| 206 << Store::kDisplayNameKey << " key"; |
170 return nullptr; | 207 return nullptr; |
171 } | 208 } |
172 entry->set_display_name(display_name); | 209 entry->set_display_name(display_name); |
| 210 |
| 211 // Capability spec. |
173 const base::DictionaryValue* capabilities = nullptr; | 212 const base::DictionaryValue* capabilities = nullptr; |
174 if (!value.GetDictionary(Store::kCapabilitiesKey, &capabilities)) { | 213 if (!value.GetDictionary(Store::kCapabilitiesKey, &capabilities)) { |
175 LOG(WARNING) << "Entry::Description: dictionary has no capabilities key"; | 214 LOG(ERROR) << "Entry::Deserialize: dictionary has no " |
| 215 << Store::kCapabilitiesKey << " key"; |
176 return nullptr; | 216 return nullptr; |
177 } | 217 } |
178 if (manifest_version == 0) | 218 |
179 entry->set_capabilities(BuildCapabilitiesV0(*capabilities)); | 219 shell::CapabilitySpec spec; |
180 else | 220 if (!BuildCapabilities(*capabilities, &spec)) { |
181 entry->set_capabilities(BuildCapabilitiesV1(*capabilities)); | 221 LOG(ERROR) << "Entry::Deserialize: failed to build capability spec for " |
| 222 << entry->name(); |
| 223 return nullptr; |
| 224 } |
| 225 entry->set_capabilities(spec); |
182 | 226 |
183 if (value.HasKey(Store::kApplicationsKey)) { | 227 if (value.HasKey(Store::kApplicationsKey)) { |
184 const base::ListValue* applications = nullptr; | 228 const base::ListValue* applications = nullptr; |
185 value.GetList(Store::kApplicationsKey, &applications); | 229 value.GetList(Store::kApplicationsKey, &applications); |
186 for (size_t i = 0; i < applications->GetSize(); ++i) { | 230 for (size_t i = 0; i < applications->GetSize(); ++i) { |
187 const base::DictionaryValue* application = nullptr; | 231 const base::DictionaryValue* application = nullptr; |
188 applications->GetDictionary(i, &application); | 232 applications->GetDictionary(i, &application); |
189 std::unique_ptr<Entry> child = Entry::Deserialize(*application); | 233 std::unique_ptr<Entry> child = Entry::Deserialize(*application); |
190 if (child) { | 234 if (child) { |
191 child->set_package(entry.get()); | 235 child->set_package(entry.get()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 catalog::mojom::EntryPtr | 281 catalog::mojom::EntryPtr |
238 TypeConverter<catalog::mojom::EntryPtr, catalog::Entry>::Convert( | 282 TypeConverter<catalog::mojom::EntryPtr, catalog::Entry>::Convert( |
239 const catalog::Entry& input) { | 283 const catalog::Entry& input) { |
240 catalog::mojom::EntryPtr result(catalog::mojom::Entry::New()); | 284 catalog::mojom::EntryPtr result(catalog::mojom::Entry::New()); |
241 result->name = input.name(); | 285 result->name = input.name(); |
242 result->display_name = input.display_name(); | 286 result->display_name = input.display_name(); |
243 return result; | 287 return result; |
244 } | 288 } |
245 | 289 |
246 } // namespace mojo | 290 } // namespace mojo |
OLD | NEW |