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

Side by Side Diff: extensions/renderer/bindings/api_binding.cc

Issue 2950353004: [Extensions Bindings] Check availability of custom API properties (Closed)
Patch Set: . Created 3 years, 5 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/renderer/bindings/api_binding.h" 5 #include "extensions/renderer/bindings/api_binding.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // The associated APIBinding. This raw pointer is safe because the 147 // The associated APIBinding. This raw pointer is safe because the
148 // EventData is only accessed from the callbacks associated with the 148 // EventData is only accessed from the callbacks associated with the
149 // APIBinding, and both the APIBinding and APIEventHandler are owned by the 149 // APIBinding, and both the APIBinding and APIEventHandler are owned by the
150 // same object (the APIBindingsSystem). 150 // same object (the APIBindingsSystem).
151 APIBinding* binding; 151 APIBinding* binding;
152 }; 152 };
153 153
154 struct APIBinding::CustomPropertyData { 154 struct APIBinding::CustomPropertyData {
155 CustomPropertyData(const std::string& type_name, 155 CustomPropertyData(const std::string& type_name,
156 const std::string& property_name, 156 const std::string& property_name,
157 const std::string& full_name,
157 const base::ListValue* property_values, 158 const base::ListValue* property_values,
159 const BindingAccessChecker* access_checker,
158 const CreateCustomType& create_custom_type) 160 const CreateCustomType& create_custom_type)
159 : type_name(type_name), 161 : type_name(type_name),
160 property_name(property_name), 162 property_name(property_name),
163 full_name(full_name),
161 property_values(property_values), 164 property_values(property_values),
165 access_checker(access_checker),
162 create_custom_type(create_custom_type) {} 166 create_custom_type(create_custom_type) {}
163 167
164 // The type of the property, e.g. 'storage.StorageArea'. 168 // The type of the property, e.g. 'storage.StorageArea'.
165 std::string type_name; 169 std::string type_name;
166 // The name of the property on the object, e.g. 'local' for 170 // The name of the property on the object, e.g. 'local' for
167 // chrome.storage.local. 171 // chrome.storage.local.
168 std::string property_name; 172 std::string property_name;
173 // The full name of the property for looking up the feature, e.g.
174 // chrome.storage.local.
175 std::string full_name;
176
169 // Values curried into this particular type from the schema. 177 // Values curried into this particular type from the schema.
170 const base::ListValue* property_values; 178 const base::ListValue* property_values;
171 179
180 const BindingAccessChecker* const access_checker;
181
172 CreateCustomType create_custom_type; 182 CreateCustomType create_custom_type;
173 }; 183 };
174 184
175 APIBinding::APIBinding(const std::string& api_name, 185 APIBinding::APIBinding(const std::string& api_name,
176 const base::ListValue* function_definitions, 186 const base::ListValue* function_definitions,
177 const base::ListValue* type_definitions, 187 const base::ListValue* type_definitions,
178 const base::ListValue* event_definitions, 188 const base::ListValue* event_definitions,
179 const base::DictionaryValue* property_definitions, 189 const base::DictionaryValue* property_definitions,
180 const CreateCustomType& create_custom_type, 190 const CreateCustomType& create_custom_type,
181 std::unique_ptr<APIBindingHooks> binding_hooks, 191 std::unique_ptr<APIBindingHooks> binding_hooks,
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 v8::ObjectTemplate::New(isolate); 404 v8::ObjectTemplate::New(isolate);
395 for (const auto& enum_entry : entry.second) { 405 for (const auto& enum_entry : entry.second) {
396 enum_object->Set(gin::StringToSymbol(isolate, enum_entry.second), 406 enum_object->Set(gin::StringToSymbol(isolate, enum_entry.second),
397 gin::StringToSymbol(isolate, enum_entry.first)); 407 gin::StringToSymbol(isolate, enum_entry.first));
398 } 408 }
399 object_template->Set(isolate, entry.first.c_str(), enum_object); 409 object_template->Set(isolate, entry.first.c_str(), enum_object);
400 } 410 }
401 411
402 if (property_definitions_) { 412 if (property_definitions_) {
403 DecorateTemplateWithProperties(isolate, object_template, 413 DecorateTemplateWithProperties(isolate, object_template,
404 *property_definitions_); 414 *property_definitions_, api_name_);
405 } 415 }
406 416
407 // Allow custom bindings a chance to tweak the template, such as to add 417 // Allow custom bindings a chance to tweak the template, such as to add
408 // additional properties or types. 418 // additional properties or types.
409 binding_hooks_->InitializeTemplate(isolate, object_template, *type_refs_); 419 binding_hooks_->InitializeTemplate(isolate, object_template, *type_refs_);
410 420
411 object_template_.Set(isolate, object_template); 421 object_template_.Set(isolate, object_template);
412 } 422 }
413 423
414 void APIBinding::DecorateTemplateWithProperties( 424 void APIBinding::DecorateTemplateWithProperties(
415 v8::Isolate* isolate, 425 v8::Isolate* isolate,
416 v8::Local<v8::ObjectTemplate> object_template, 426 v8::Local<v8::ObjectTemplate> object_template,
417 const base::DictionaryValue& properties) { 427 const base::DictionaryValue& properties,
428 const std::string& path) {
418 static const char kValueKey[] = "value"; 429 static const char kValueKey[] = "value";
419 for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd(); 430 for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
420 iter.Advance()) { 431 iter.Advance()) {
421 const base::DictionaryValue* dict = nullptr; 432 const base::DictionaryValue* dict = nullptr;
422 CHECK(iter.value().GetAsDictionary(&dict)); 433 CHECK(iter.value().GetAsDictionary(&dict));
423 bool optional = false; 434 bool optional = false;
424 if (dict->GetBoolean("optional", &optional)) { 435 if (dict->GetBoolean("optional", &optional)) {
425 // TODO(devlin): What does optional even mean here? It's only used, it 436 // TODO(devlin): What does optional even mean here? It's only used, it
426 // seems, for lastError and inIncognitoContext, which are both handled 437 // seems, for lastError and inIncognitoContext, which are both handled
427 // with custom bindings. Investigate, and remove. 438 // with custom bindings. Investigate, and remove.
428 continue; 439 continue;
429 } 440 }
430 441
431 v8::Local<v8::String> v8_key = gin::StringToSymbol(isolate, iter.key()); 442 v8::Local<v8::String> v8_key = gin::StringToSymbol(isolate, iter.key());
432 std::string ref; 443 std::string ref;
433 if (dict->GetString("$ref", &ref)) { 444 if (dict->GetString("$ref", &ref)) {
434 const base::ListValue* property_values = nullptr; 445 const base::ListValue* property_values = nullptr;
435 CHECK(dict->GetList("value", &property_values)); 446 CHECK(dict->GetList("value", &property_values));
436 auto property_data = base::MakeUnique<CustomPropertyData>( 447 auto property_data = base::MakeUnique<CustomPropertyData>(
437 ref, iter.key(), property_values, create_custom_type_); 448 ref, iter.key(),
449 base::StringPrintf("%s.%s", path.c_str(), iter.key().c_str()),
450 property_values, access_checker_, create_custom_type_);
438 object_template->SetLazyDataProperty( 451 object_template->SetLazyDataProperty(
439 v8_key, &APIBinding::GetCustomPropertyObject, 452 v8_key, &APIBinding::GetCustomPropertyObject,
440 v8::External::New(isolate, property_data.get())); 453 v8::External::New(isolate, property_data.get()));
441 custom_properties_.push_back(std::move(property_data)); 454 custom_properties_.push_back(std::move(property_data));
442 continue; 455 continue;
443 } 456 }
444 457
445 std::string type; 458 std::string type;
446 CHECK(dict->GetString("type", &type)); 459 CHECK(dict->GetString("type", &type));
447 if (type != "object" && !dict->HasKey(kValueKey)) { 460 if (type != "object" && !dict->HasKey(kValueKey)) {
(...skipping 12 matching lines...) Expand all
460 object_template->Set(v8_key, v8::Boolean::New(isolate, val)); 473 object_template->Set(v8_key, v8::Boolean::New(isolate, val));
461 } else if (type == "string") { 474 } else if (type == "string") {
462 std::string val; 475 std::string val;
463 CHECK(dict->GetString(kValueKey, &val)) << iter.key(); 476 CHECK(dict->GetString(kValueKey, &val)) << iter.key();
464 object_template->Set(v8_key, gin::StringToSymbol(isolate, val)); 477 object_template->Set(v8_key, gin::StringToSymbol(isolate, val));
465 } else if (type == "object" || !ref.empty()) { 478 } else if (type == "object" || !ref.empty()) {
466 v8::Local<v8::ObjectTemplate> property_template = 479 v8::Local<v8::ObjectTemplate> property_template =
467 v8::ObjectTemplate::New(isolate); 480 v8::ObjectTemplate::New(isolate);
468 const base::DictionaryValue* property_dict = nullptr; 481 const base::DictionaryValue* property_dict = nullptr;
469 CHECK(dict->GetDictionary("properties", &property_dict)); 482 CHECK(dict->GetDictionary("properties", &property_dict));
470 DecorateTemplateWithProperties(isolate, property_template, 483 DecorateTemplateWithProperties(
471 *property_dict); 484 isolate, property_template, *property_dict,
485 base::StringPrintf("%s.%s", path.c_str(), iter.key().c_str()));
472 object_template->Set(v8_key, property_template); 486 object_template->Set(v8_key, property_template);
473 } 487 }
474 } 488 }
475 } 489 }
476 490
477 // static 491 // static
478 void APIBinding::GetEventObject( 492 void APIBinding::GetEventObject(
479 v8::Local<v8::Name> property, 493 v8::Local<v8::Name> property,
480 const v8::PropertyCallbackInfo<v8::Value>& info) { 494 const v8::PropertyCallbackInfo<v8::Value>& info) {
481 v8::Isolate* isolate = info.GetIsolate(); 495 v8::Isolate* isolate = info.GetIsolate();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 v8::HandleScope handle_scope(isolate); 527 v8::HandleScope handle_scope(isolate);
514 v8::Local<v8::Context> context = info.Holder()->CreationContext(); 528 v8::Local<v8::Context> context = info.Holder()->CreationContext();
515 if (!IsContextValid(context)) 529 if (!IsContextValid(context))
516 return; 530 return;
517 531
518 v8::Context::Scope context_scope(context); 532 v8::Context::Scope context_scope(context);
519 CHECK(info.Data()->IsExternal()); 533 CHECK(info.Data()->IsExternal());
520 auto* property_data = 534 auto* property_data =
521 static_cast<CustomPropertyData*>(info.Data().As<v8::External>()->Value()); 535 static_cast<CustomPropertyData*>(info.Data().As<v8::External>()->Value());
522 536
537 // If the property isn't available to this context, do nothing.
538 // TODO(devlin): This is a little suboptimal. Two notable downsides:
539 // - This only applies to custom properties. This means that if an API has a
540 // property with a raw value, it won't be restricted. Currently, this isn't
541 // a problem, but it could be in the future.
542 // - The key remains in the parent object (though the value will be
543 // undefined).
544 // Given the rarity of these restricted properties, this is okay, but it would
545 // be nice if it were better.
546 if (!property_data->access_checker->HasAccess(context,
547 property_data->full_name)) {
548 return;
549 }
550
523 v8::Local<v8::Object> property = property_data->create_custom_type.Run( 551 v8::Local<v8::Object> property = property_data->create_custom_type.Run(
524 isolate, property_data->type_name, property_data->property_name, 552 isolate, property_data->type_name, property_data->property_name,
525 property_data->property_values); 553 property_data->property_values);
526 if (property.IsEmpty()) 554 if (property.IsEmpty())
527 return; 555 return;
528 556
529 info.GetReturnValue().Set(property); 557 info.GetReturnValue().Set(property);
530 } 558 }
531 559
532 void APIBinding::HandleCall(const std::string& name, 560 void APIBinding::HandleCall(const std::string& name,
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 arguments->ThrowTypeError(api_errors::InvocationError( 650 arguments->ThrowTypeError(api_errors::InvocationError(
623 name, signature->GetExpectedSignature(), error)); 651 name, signature->GetExpectedSignature(), error));
624 return; 652 return;
625 } 653 }
626 654
627 request_handler_->StartRequest(context, name, std::move(converted_arguments), 655 request_handler_->StartRequest(context, name, std::move(converted_arguments),
628 callback, custom_callback, thread); 656 callback, custom_callback, thread);
629 } 657 }
630 658
631 } // namespace extensions 659 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698