OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "extensions/common/extension_api.h" | 5 #include "extensions/common/extension_api.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <string> | 10 #include <string> |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 std::unique_ptr<base::ListValue> LoadSchemaList( | 48 std::unique_ptr<base::ListValue> LoadSchemaList( |
49 const std::string& name, | 49 const std::string& name, |
50 const base::StringPiece& schema) { | 50 const base::StringPiece& schema) { |
51 std::string error_message; | 51 std::string error_message; |
52 std::unique_ptr<base::Value> result(base::JSONReader::ReadAndReturnError( | 52 std::unique_ptr<base::Value> result(base::JSONReader::ReadAndReturnError( |
53 schema, | 53 schema, |
54 base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN, // options | 54 base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN, // options |
55 NULL, // error code | 55 NULL, // error code |
56 &error_message)); | 56 &error_message)); |
57 | 57 |
58 // Tracking down http://crbug.com/121424 | 58 #if DCHECK_IS_ON() |
59 char buf[128]; | 59 // |schema| comes from JSON hard-coded to the Chrome binary, so in principle |
60 base::snprintf(buf, arraysize(buf), "%s: (%d) '%s'", | 60 // failure to parse indicates we generated corrupted JSON, but in practice |
61 name.c_str(), | 61 // corruption of the Chrome binary (e.g. disk errors) can also break it. |
62 result.get() ? result->GetType() : -1, | 62 // See http://crbug.com/121424. |
63 error_message.c_str()); | 63 if (!result || !result->IsType(base::Value::TYPE_LIST)) { |
64 char buf[128]; | |
65 base::snprintf(buf, arraysize(buf), "%s: (%d) '%s'", | |
66 name.c_str(), | |
67 result.get() ? result->GetType() : -1, | |
68 error_message.c_str()); | |
64 | 69 |
65 CHECK(result.get()) << error_message << " for schema " << schema; | 70 DCHECK(result); |
66 CHECK(result->IsType(base::Value::TYPE_LIST)) << " for schema " << schema; | 71 DCHECK(result->IsType(base::Value::TYPE_LIST)); |
72 } | |
73 #endif // DCHECK_IS_ON() | |
74 | |
75 // From() returns null if pass a null or non-list value. | |
Devlin
2016/08/19 15:02:32
nit: "passed"
Wez
2016/08/19 18:22:15
Done.
| |
67 return base::ListValue::From(std::move(result)); | 76 return base::ListValue::From(std::move(result)); |
68 } | 77 } |
69 | 78 |
70 const base::DictionaryValue* FindListItem(const base::ListValue* list, | 79 const base::DictionaryValue* FindListItem(const base::ListValue* list, |
71 const std::string& property_name, | 80 const std::string& property_name, |
72 const std::string& property_value) { | 81 const std::string& property_value) { |
73 for (size_t i = 0; i < list->GetSize(); ++i) { | 82 for (size_t i = 0; i < list->GetSize(); ++i) { |
74 const base::DictionaryValue* item = NULL; | 83 const base::DictionaryValue* item = NULL; |
75 CHECK(list->GetDictionary(i, &item)) | 84 CHECK(list->GetDictionary(i, &item)) |
76 << property_value << "/" << property_name; | 85 << property_value << "/" << property_name; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 g_shared_instance_for_test = testing_api; | 216 g_shared_instance_for_test = testing_api; |
208 } | 217 } |
209 | 218 |
210 ExtensionAPI::OverrideSharedInstanceForTest::~OverrideSharedInstanceForTest() { | 219 ExtensionAPI::OverrideSharedInstanceForTest::~OverrideSharedInstanceForTest() { |
211 g_shared_instance_for_test = original_api_; | 220 g_shared_instance_for_test = original_api_; |
212 } | 221 } |
213 | 222 |
214 void ExtensionAPI::LoadSchema(const std::string& name, | 223 void ExtensionAPI::LoadSchema(const std::string& name, |
215 const base::StringPiece& schema) { | 224 const base::StringPiece& schema) { |
216 std::unique_ptr<base::ListValue> schema_list(LoadSchemaList(name, schema)); | 225 std::unique_ptr<base::ListValue> schema_list(LoadSchemaList(name, schema)); |
226 if (!schema_list) | |
227 return; | |
228 | |
217 std::string schema_namespace; | 229 std::string schema_namespace; |
218 extensions::ExtensionsClient* extensions_client = | 230 extensions::ExtensionsClient* extensions_client = |
219 extensions::ExtensionsClient::Get(); | 231 extensions::ExtensionsClient::Get(); |
220 DCHECK(extensions_client); | 232 DCHECK(extensions_client); |
221 while (!schema_list->empty()) { | 233 while (!schema_list->empty()) { |
222 std::unique_ptr<base::DictionaryValue> schema; | 234 std::unique_ptr<base::DictionaryValue> schema; |
223 { | 235 { |
224 std::unique_ptr<base::Value> val; | 236 std::unique_ptr<base::Value> val; |
225 schema_list->Erase(schema_list->begin(), &val); | 237 schema_list->Erase(schema_list->begin(), &val); |
226 schema = base::DictionaryValue::From(std::move(val)); | 238 schema = base::DictionaryValue::From(std::move(val)); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
324 LoadSchema(maybe_schema_resource->first, | 336 LoadSchema(maybe_schema_resource->first, |
325 ReadFromResource(maybe_schema_resource->second)); | 337 ReadFromResource(maybe_schema_resource->second)); |
326 } else if (default_configuration_initialized_ && | 338 } else if (default_configuration_initialized_ && |
327 extensions_client->IsAPISchemaGenerated(api_name)) { | 339 extensions_client->IsAPISchemaGenerated(api_name)) { |
328 LoadSchema(api_name, extensions_client->GetAPISchema(api_name)); | 340 LoadSchema(api_name, extensions_client->GetAPISchema(api_name)); |
329 } else { | 341 } else { |
330 return NULL; | 342 return NULL; |
331 } | 343 } |
332 | 344 |
333 maybe_schema = schemas_.find(api_name); | 345 maybe_schema = schemas_.find(api_name); |
334 CHECK(schemas_.end() != maybe_schema); | 346 // If the schema failed to load then return null for it, rather than |
347 // crashing, so that the browser can be notified of the problem. | |
348 // See http://crbug.com/121424. | |
349 if (schemas_.end() == maybe_schema) | |
350 return NULL; | |
351 | |
335 result = maybe_schema->second.get(); | 352 result = maybe_schema->second.get(); |
336 } | 353 } |
337 | 354 |
338 if (!child_name.empty()) | 355 if (!child_name.empty()) |
339 result = GetSchemaChild(result, child_name); | 356 result = GetSchemaChild(result, child_name); |
340 | 357 |
341 return result; | 358 return result; |
342 } | 359 } |
343 | 360 |
361 void ExtensionAPI::LoadSchemaListOrDie(const std::string& api) { | |
362 std::string api_name = GetAPINameFromFullName(api, NULL); | |
Devlin
2016/08/19 15:02:32
nullptr
Wez
2016/08/19 18:22:15
Sticking with NULL for consistency with the rest o
Devlin
2016/08/19 18:40:57
(Not blocking this change - feel free to ignore) I
| |
363 extensions::ExtensionsClient* extensions_client = | |
364 extensions::ExtensionsClient::Get(); | |
365 // IsAPISchemaGenerated() will return false for invalid |api| names. | |
366 if (!extensions_client->IsAPISchemaGenerated(api)) | |
Devlin
2016/08/19 15:02:32
We aren't checking the unloaded schemas here. Tha
Wez
2016/08/19 18:22:15
Ah, OK, so we need to check for un-generated (why
Devlin
2016/08/19 18:40:57
re unloaded, no idea - the whole concept doesn't m
| |
367 return; | |
368 | |
369 CHECK(LoadSchemaList(api_name, extensions_client->GetAPISchema(api_name))); | |
370 } | |
371 | |
344 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { | 372 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { |
345 std::string feature_type; | 373 std::string feature_type; |
346 std::string feature_name; | 374 std::string feature_name; |
347 SplitDependencyName(full_name, &feature_type, &feature_name); | 375 SplitDependencyName(full_name, &feature_type, &feature_name); |
348 | 376 |
349 FeatureProviderMap::iterator provider = | 377 FeatureProviderMap::iterator provider = |
350 dependency_providers_.find(feature_type); | 378 dependency_providers_.find(feature_type); |
351 if (provider == dependency_providers_.end()) | 379 if (provider == dependency_providers_.end()) |
352 return NULL; | 380 return NULL; |
353 | 381 |
(...skipping 29 matching lines...) Expand all Loading... | |
383 return result; | 411 return result; |
384 } | 412 } |
385 | 413 |
386 size_t last_dot_index = api_name_candidate.rfind('.'); | 414 size_t last_dot_index = api_name_candidate.rfind('.'); |
387 if (last_dot_index == std::string::npos) | 415 if (last_dot_index == std::string::npos) |
388 break; | 416 break; |
389 | 417 |
390 api_name_candidate = api_name_candidate.substr(0, last_dot_index); | 418 api_name_candidate = api_name_candidate.substr(0, last_dot_index); |
391 } | 419 } |
392 | 420 |
393 *child_name = ""; | 421 if (child_name) |
422 *child_name = ""; | |
423 | |
394 return std::string(); | 424 return std::string(); |
395 } | 425 } |
396 | 426 |
397 } // namespace extensions | 427 } // namespace extensions |
OLD | NEW |