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 #if DCHECK_IS_ON() | 58 // Tracking down http://crbug.com/121424 |
59 // |schema| comes from JSON hard-coded to the Chrome binary, so in principle | 59 char buf[128]; |
60 // failure to parse indicates we generated corrupted JSON, but in practice | 60 base::snprintf(buf, arraysize(buf), "%s: (%d) '%s'", |
61 // corruption of the Chrome binary (e.g. disk errors) can also break it. | 61 name.c_str(), |
62 // See http://crbug.com/121424. | 62 result.get() ? result->GetType() : -1, |
63 if (!result || !result->IsType(base::Value::TYPE_LIST)) { | 63 error_message.c_str()); |
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()); | |
68 | 64 |
69 DCHECK(result) << "JSON parse failed: " << buf; | 65 CHECK(result.get()) << error_message << " for schema " << schema; |
70 DCHECK(result->IsType(base::Value::TYPE_LIST)) << "JSON wrong type: " | 66 CHECK(result->IsType(base::Value::TYPE_LIST)) << " for schema " << schema; |
71 << buf; | |
72 } | |
73 #endif // DCHECK_IS_ON() | |
74 | |
75 // From() returns null if passed a null or non-list value. | |
76 return base::ListValue::From(std::move(result)); | 67 return base::ListValue::From(std::move(result)); |
77 } | 68 } |
78 | 69 |
79 const base::DictionaryValue* FindListItem(const base::ListValue* list, | 70 const base::DictionaryValue* FindListItem(const base::ListValue* list, |
80 const std::string& property_name, | 71 const std::string& property_name, |
81 const std::string& property_value) { | 72 const std::string& property_value) { |
82 for (size_t i = 0; i < list->GetSize(); ++i) { | 73 for (size_t i = 0; i < list->GetSize(); ++i) { |
83 const base::DictionaryValue* item = NULL; | 74 const base::DictionaryValue* item = NULL; |
84 CHECK(list->GetDictionary(i, &item)) | 75 CHECK(list->GetDictionary(i, &item)) |
85 << property_value << "/" << property_name; | 76 << property_value << "/" << property_name; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 g_shared_instance_for_test = testing_api; | 207 g_shared_instance_for_test = testing_api; |
217 } | 208 } |
218 | 209 |
219 ExtensionAPI::OverrideSharedInstanceForTest::~OverrideSharedInstanceForTest() { | 210 ExtensionAPI::OverrideSharedInstanceForTest::~OverrideSharedInstanceForTest() { |
220 g_shared_instance_for_test = original_api_; | 211 g_shared_instance_for_test = original_api_; |
221 } | 212 } |
222 | 213 |
223 void ExtensionAPI::LoadSchema(const std::string& name, | 214 void ExtensionAPI::LoadSchema(const std::string& name, |
224 const base::StringPiece& schema) { | 215 const base::StringPiece& schema) { |
225 std::unique_ptr<base::ListValue> schema_list(LoadSchemaList(name, schema)); | 216 std::unique_ptr<base::ListValue> schema_list(LoadSchemaList(name, schema)); |
226 if (!schema_list) | |
227 return; | |
228 | |
229 std::string schema_namespace; | 217 std::string schema_namespace; |
230 extensions::ExtensionsClient* extensions_client = | 218 extensions::ExtensionsClient* extensions_client = |
231 extensions::ExtensionsClient::Get(); | 219 extensions::ExtensionsClient::Get(); |
232 DCHECK(extensions_client); | 220 DCHECK(extensions_client); |
233 while (!schema_list->empty()) { | 221 while (!schema_list->empty()) { |
234 std::unique_ptr<base::DictionaryValue> schema; | 222 std::unique_ptr<base::DictionaryValue> schema; |
235 { | 223 { |
236 std::unique_ptr<base::Value> val; | 224 std::unique_ptr<base::Value> val; |
237 schema_list->Erase(schema_list->begin(), &val); | 225 schema_list->Erase(schema_list->begin(), &val); |
238 schema = base::DictionaryValue::From(std::move(val)); | 226 schema = base::DictionaryValue::From(std::move(val)); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 LoadSchema(maybe_schema_resource->first, | 324 LoadSchema(maybe_schema_resource->first, |
337 ReadFromResource(maybe_schema_resource->second)); | 325 ReadFromResource(maybe_schema_resource->second)); |
338 } else if (default_configuration_initialized_ && | 326 } else if (default_configuration_initialized_ && |
339 extensions_client->IsAPISchemaGenerated(api_name)) { | 327 extensions_client->IsAPISchemaGenerated(api_name)) { |
340 LoadSchema(api_name, extensions_client->GetAPISchema(api_name)); | 328 LoadSchema(api_name, extensions_client->GetAPISchema(api_name)); |
341 } else { | 329 } else { |
342 return NULL; | 330 return NULL; |
343 } | 331 } |
344 | 332 |
345 maybe_schema = schemas_.find(api_name); | 333 maybe_schema = schemas_.find(api_name); |
346 // If the schema failed to load then return null for it, rather than | 334 CHECK(schemas_.end() != maybe_schema); |
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 | |
352 result = maybe_schema->second.get(); | 335 result = maybe_schema->second.get(); |
353 } | 336 } |
354 | 337 |
355 if (!child_name.empty()) | 338 if (!child_name.empty()) |
356 result = GetSchemaChild(result, child_name); | 339 result = GetSchemaChild(result, child_name); |
357 | 340 |
358 return result; | 341 return result; |
359 } | 342 } |
360 | 343 |
361 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { | 344 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 return result; | 383 return result; |
401 } | 384 } |
402 | 385 |
403 size_t last_dot_index = api_name_candidate.rfind('.'); | 386 size_t last_dot_index = api_name_candidate.rfind('.'); |
404 if (last_dot_index == std::string::npos) | 387 if (last_dot_index == std::string::npos) |
405 break; | 388 break; |
406 | 389 |
407 api_name_candidate = api_name_candidate.substr(0, last_dot_index); | 390 api_name_candidate = api_name_candidate.substr(0, last_dot_index); |
408 } | 391 } |
409 | 392 |
410 if (child_name) | 393 *child_name = ""; |
411 *child_name = ""; | |
412 | |
413 return std::string(); | 394 return std::string(); |
414 } | 395 } |
415 | 396 |
416 } // namespace extensions | 397 } // namespace extensions |
OLD | NEW |