Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: extensions/common/extension_api.cc

Issue 2254383002: Signal extension API schema corruption to the browser process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698