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'", name.c_str(), |
| 66 result.get() ? result->GetType() : -1, |
| 67 error_message.c_str()); |
64 | 68 |
65 CHECK(result.get()) << error_message << " for schema " << schema; | 69 DCHECK(result); |
66 CHECK(result->IsType(base::Value::TYPE_LIST)) << " for schema " << schema; | 70 DCHECK(result->IsType(base::Value::TYPE_LIST)); |
| 71 } |
| 72 #endif // DCHECK_IS_ON() |
| 73 |
| 74 // From() returns null if passed a null or non-list value. |
67 return base::ListValue::From(std::move(result)); | 75 return base::ListValue::From(std::move(result)); |
68 } | 76 } |
69 | 77 |
70 const base::DictionaryValue* FindListItem(const base::ListValue* list, | 78 const base::DictionaryValue* FindListItem(const base::ListValue* list, |
71 const std::string& property_name, | 79 const std::string& property_name, |
72 const std::string& property_value) { | 80 const std::string& property_value) { |
73 for (size_t i = 0; i < list->GetSize(); ++i) { | 81 for (size_t i = 0; i < list->GetSize(); ++i) { |
74 const base::DictionaryValue* item = NULL; | 82 const base::DictionaryValue* item = NULL; |
75 CHECK(list->GetDictionary(i, &item)) | 83 CHECK(list->GetDictionary(i, &item)) |
76 << property_value << "/" << property_name; | 84 << 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; | 215 g_shared_instance_for_test = testing_api; |
208 } | 216 } |
209 | 217 |
210 ExtensionAPI::OverrideSharedInstanceForTest::~OverrideSharedInstanceForTest() { | 218 ExtensionAPI::OverrideSharedInstanceForTest::~OverrideSharedInstanceForTest() { |
211 g_shared_instance_for_test = original_api_; | 219 g_shared_instance_for_test = original_api_; |
212 } | 220 } |
213 | 221 |
214 void ExtensionAPI::LoadSchema(const std::string& name, | 222 void ExtensionAPI::LoadSchema(const std::string& name, |
215 const base::StringPiece& schema) { | 223 const base::StringPiece& schema) { |
216 std::unique_ptr<base::ListValue> schema_list(LoadSchemaList(name, schema)); | 224 std::unique_ptr<base::ListValue> schema_list(LoadSchemaList(name, schema)); |
| 225 if (!schema_list) |
| 226 return; |
| 227 |
217 std::string schema_namespace; | 228 std::string schema_namespace; |
218 extensions::ExtensionsClient* extensions_client = | 229 extensions::ExtensionsClient* extensions_client = |
219 extensions::ExtensionsClient::Get(); | 230 extensions::ExtensionsClient::Get(); |
220 DCHECK(extensions_client); | 231 DCHECK(extensions_client); |
221 while (!schema_list->empty()) { | 232 while (!schema_list->empty()) { |
222 std::unique_ptr<base::DictionaryValue> schema; | 233 std::unique_ptr<base::DictionaryValue> schema; |
223 { | 234 { |
224 std::unique_ptr<base::Value> val; | 235 std::unique_ptr<base::Value> val; |
225 schema_list->Erase(schema_list->begin(), &val); | 236 schema_list->Erase(schema_list->begin(), &val); |
226 schema = base::DictionaryValue::From(std::move(val)); | 237 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, | 335 LoadSchema(maybe_schema_resource->first, |
325 ReadFromResource(maybe_schema_resource->second)); | 336 ReadFromResource(maybe_schema_resource->second)); |
326 } else if (default_configuration_initialized_ && | 337 } else if (default_configuration_initialized_ && |
327 extensions_client->IsAPISchemaGenerated(api_name)) { | 338 extensions_client->IsAPISchemaGenerated(api_name)) { |
328 LoadSchema(api_name, extensions_client->GetAPISchema(api_name)); | 339 LoadSchema(api_name, extensions_client->GetAPISchema(api_name)); |
329 } else { | 340 } else { |
330 return NULL; | 341 return NULL; |
331 } | 342 } |
332 | 343 |
333 maybe_schema = schemas_.find(api_name); | 344 maybe_schema = schemas_.find(api_name); |
334 CHECK(schemas_.end() != maybe_schema); | 345 // If the schema failed to load then return null for it, rather than |
| 346 // crashing, so that the browser can be notified of the problem. |
| 347 // See http://crbug.com/121424. |
| 348 if (schemas_.end() == maybe_schema) |
| 349 return NULL; |
| 350 |
335 result = maybe_schema->second.get(); | 351 result = maybe_schema->second.get(); |
336 } | 352 } |
337 | 353 |
338 if (!child_name.empty()) | 354 if (!child_name.empty()) |
339 result = GetSchemaChild(result, child_name); | 355 result = GetSchemaChild(result, child_name); |
340 | 356 |
341 return result; | 357 return result; |
342 } | 358 } |
343 | 359 |
| 360 void ExtensionAPI::LoadSchemaListOrDie(const std::string& api) { |
| 361 std::string api_name = GetAPINameFromFullName(api, NULL); |
| 362 |
| 363 extensions::ExtensionsClient* extensions_client = |
| 364 extensions::ExtensionsClient::Get(); |
| 365 DCHECK(extensions_client); |
| 366 |
| 367 UnloadedSchemaMap::iterator maybe_schema_resource = |
| 368 unloaded_schemas_.find(api_name); |
| 369 if (maybe_schema_resource != unloaded_schemas_.end()) { |
| 370 CHECK(LoadSchemaList(api_name, |
| 371 ReadFromResource(maybe_schema_resource->second))); |
| 372 } else if (extensions_client->IsAPISchemaGenerated(api)) { |
| 373 CHECK(LoadSchemaList(api_name, extensions_client->GetAPISchema(api_name))); |
| 374 } |
| 375 } |
| 376 |
344 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { | 377 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { |
345 std::string feature_type; | 378 std::string feature_type; |
346 std::string feature_name; | 379 std::string feature_name; |
347 SplitDependencyName(full_name, &feature_type, &feature_name); | 380 SplitDependencyName(full_name, &feature_type, &feature_name); |
348 | 381 |
349 FeatureProviderMap::iterator provider = | 382 FeatureProviderMap::iterator provider = |
350 dependency_providers_.find(feature_type); | 383 dependency_providers_.find(feature_type); |
351 if (provider == dependency_providers_.end()) | 384 if (provider == dependency_providers_.end()) |
352 return NULL; | 385 return NULL; |
353 | 386 |
(...skipping 29 matching lines...) Expand all Loading... |
383 return result; | 416 return result; |
384 } | 417 } |
385 | 418 |
386 size_t last_dot_index = api_name_candidate.rfind('.'); | 419 size_t last_dot_index = api_name_candidate.rfind('.'); |
387 if (last_dot_index == std::string::npos) | 420 if (last_dot_index == std::string::npos) |
388 break; | 421 break; |
389 | 422 |
390 api_name_candidate = api_name_candidate.substr(0, last_dot_index); | 423 api_name_candidate = api_name_candidate.substr(0, last_dot_index); |
391 } | 424 } |
392 | 425 |
393 *child_name = ""; | 426 if (child_name) |
| 427 *child_name = ""; |
| 428 |
394 return std::string(); | 429 return std::string(); |
395 } | 430 } |
396 | 431 |
397 } // namespace extensions | 432 } // namespace extensions |
OLD | NEW |