Chromium Code Reviews| 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 |