Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/api_binding.h" | 5 #include "extensions/renderer/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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 | 157 |
| 158 CreateCustomType create_custom_type; | 158 CreateCustomType create_custom_type; |
| 159 }; | 159 }; |
| 160 | 160 |
| 161 APIBinding::APIBinding(const std::string& api_name, | 161 APIBinding::APIBinding(const std::string& api_name, |
| 162 const base::ListValue* function_definitions, | 162 const base::ListValue* function_definitions, |
| 163 const base::ListValue* type_definitions, | 163 const base::ListValue* type_definitions, |
| 164 const base::ListValue* event_definitions, | 164 const base::ListValue* event_definitions, |
| 165 const base::DictionaryValue* property_definitions, | 165 const base::DictionaryValue* property_definitions, |
| 166 const CreateCustomType& create_custom_type, | 166 const CreateCustomType& create_custom_type, |
| 167 const AvailabilityCallback& is_available, | |
| 167 std::unique_ptr<APIBindingHooks> binding_hooks, | 168 std::unique_ptr<APIBindingHooks> binding_hooks, |
| 168 APITypeReferenceMap* type_refs, | 169 APITypeReferenceMap* type_refs, |
| 169 APIRequestHandler* request_handler, | 170 APIRequestHandler* request_handler, |
| 170 APIEventHandler* event_handler) | 171 APIEventHandler* event_handler) |
| 171 : api_name_(api_name), | 172 : api_name_(api_name), |
| 172 property_definitions_(property_definitions), | 173 property_definitions_(property_definitions), |
| 173 create_custom_type_(create_custom_type), | 174 create_custom_type_(create_custom_type), |
| 175 is_available_(is_available), | |
| 174 binding_hooks_(std::move(binding_hooks)), | 176 binding_hooks_(std::move(binding_hooks)), |
| 175 type_refs_(type_refs), | 177 type_refs_(type_refs), |
| 176 request_handler_(request_handler), | 178 request_handler_(request_handler), |
| 177 event_handler_(event_handler), | 179 event_handler_(event_handler), |
| 178 weak_factory_(this) { | 180 weak_factory_(this) { |
| 179 // TODO(devlin): It might make sense to instantiate the object_template_ | 181 // TODO(devlin): It might make sense to instantiate the object_template_ |
| 180 // directly here, which would avoid the need to hold on to | 182 // directly here, which would avoid the need to hold on to |
| 181 // |property_definitions_| and |enums_|. However, there are *some* cases where | 183 // |property_definitions_| and |enums_|. However, there are *some* cases where |
| 182 // we don't immediately stamp out an API from the template following | 184 // we don't immediately stamp out an API from the template following |
| 183 // construction. | 185 // construction. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 std::move(name), std::move(full_name), supports_filters, | 292 std::move(name), std::move(full_name), supports_filters, |
| 291 supports_rules, std::move(rule_actions), std::move(rule_conditions), | 293 supports_rules, std::move(rule_actions), std::move(rule_conditions), |
| 292 this)); | 294 this)); |
| 293 } | 295 } |
| 294 } | 296 } |
| 295 } | 297 } |
| 296 | 298 |
| 297 APIBinding::~APIBinding() {} | 299 APIBinding::~APIBinding() {} |
| 298 | 300 |
| 299 v8::Local<v8::Object> APIBinding::CreateInstance( | 301 v8::Local<v8::Object> APIBinding::CreateInstance( |
| 300 v8::Local<v8::Context> context, | 302 v8::Local<v8::Context> context) { |
| 301 const AvailabilityCallback& is_available) { | |
| 302 DCHECK(IsContextValid(context)); | 303 DCHECK(IsContextValid(context)); |
| 303 v8::Isolate* isolate = context->GetIsolate(); | 304 v8::Isolate* isolate = context->GetIsolate(); |
| 304 if (object_template_.IsEmpty()) | 305 if (object_template_.IsEmpty()) |
| 305 InitializeTemplate(isolate); | 306 InitializeTemplate(isolate); |
| 306 DCHECK(!object_template_.IsEmpty()); | 307 DCHECK(!object_template_.IsEmpty()); |
| 307 | 308 |
| 308 v8::Local<v8::Object> object = | 309 v8::Local<v8::Object> object = |
| 309 object_template_.Get(isolate)->NewInstance(context).ToLocalChecked(); | 310 object_template_.Get(isolate)->NewInstance(context).ToLocalChecked(); |
| 310 | 311 |
| 311 // The object created from the template includes all methods, but some may | 312 // The object created from the template includes all methods, but some may |
| 312 // be unavailable in this context. Iterate over them and delete any that | 313 // be unavailable in this context. Iterate over them and delete any that |
| 313 // aren't available. | 314 // aren't available. |
| 314 // TODO(devlin): Ideally, we'd only do this check on the methods that are | 315 // TODO(devlin): Ideally, we'd only do this check on the methods that are |
| 315 // conditionally exposed. Or, we could have multiple templates for different | 316 // conditionally exposed. Or, we could have multiple templates for different |
| 316 // configurations, assuming there are a small number of possibilities. | 317 // configurations, assuming there are a small number of possibilities. |
| 317 // TODO(devlin): enums should always be exposed, but there may be events that | |
| 318 // are restricted. Investigate. | |
| 319 for (const auto& key_value : methods_) { | 318 for (const auto& key_value : methods_) { |
| 320 if (!is_available.Run(key_value.second->full_name)) { | 319 if (!is_available_.Run(context, key_value.second->full_name)) { |
| 321 v8::Maybe<bool> success = object->Delete( | 320 v8::Maybe<bool> success = object->Delete( |
| 322 context, gin::StringToSymbol(isolate, key_value.first)); | 321 context, gin::StringToSymbol(isolate, key_value.first)); |
| 323 CHECK(success.IsJust()); | 322 CHECK(success.IsJust()); |
| 324 CHECK(success.FromJust()); | 323 CHECK(success.FromJust()); |
| 325 } | 324 } |
| 326 } | 325 } |
| 327 for (const auto& event : events_) { | 326 for (const auto& event : events_) { |
| 328 if (!is_available.Run(event->full_name)) { | 327 if (!is_available_.Run(context, event->full_name)) { |
| 329 v8::Maybe<bool> success = object->Delete( | 328 v8::Maybe<bool> success = object->Delete( |
| 330 context, gin::StringToSymbol(isolate, event->exposed_name)); | 329 context, gin::StringToSymbol(isolate, event->exposed_name)); |
| 331 CHECK(success.IsJust()); | 330 CHECK(success.IsJust()); |
| 332 CHECK(success.FromJust()); | 331 CHECK(success.FromJust()); |
| 333 } | 332 } |
| 334 } | 333 } |
| 335 | 334 |
| 336 return object; | 335 return object; |
| 337 } | 336 } |
| 338 | 337 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 const APISignature* signature, | 504 const APISignature* signature, |
| 506 gin::Arguments* arguments) { | 505 gin::Arguments* arguments) { |
| 507 std::string error; | 506 std::string error; |
| 508 v8::Isolate* isolate = arguments->isolate(); | 507 v8::Isolate* isolate = arguments->isolate(); |
| 509 v8::HandleScope handle_scope(isolate); | 508 v8::HandleScope handle_scope(isolate); |
| 510 | 509 |
| 511 // Since this is called synchronously from the JS entry point, | 510 // Since this is called synchronously from the JS entry point, |
| 512 // GetCurrentContext() should always be correct. | 511 // GetCurrentContext() should always be correct. |
| 513 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 512 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| 514 | 513 |
| 514 if (!is_available_.Run(context, name)) { | |
| 515 // TODO(devlin): Do we need handle this for events as well? I'm not sure the | |
| 516 // currrent system does (though perhaps it should). Investigate. | |
| 517 isolate->ThrowException(v8::Exception::Error(gin::StringToSymbol( | |
|
jbroman
2017/05/24 18:09:47
super-nit: maybe StringToV8? (this doesn't seem li
Devlin
2017/05/24 19:10:08
Done.
| |
| 518 isolate, base::StringPrintf("'%s' is not available in this context.", | |
| 519 name.c_str())))); | |
| 520 return; | |
| 521 } | |
| 522 | |
| 515 std::vector<v8::Local<v8::Value>> argument_list = arguments->GetAll(); | 523 std::vector<v8::Local<v8::Value>> argument_list = arguments->GetAll(); |
| 516 | 524 |
| 517 bool invalid_invocation = false; | 525 bool invalid_invocation = false; |
| 518 v8::Local<v8::Function> custom_callback; | 526 v8::Local<v8::Function> custom_callback; |
| 519 bool updated_args = false; | 527 bool updated_args = false; |
| 520 { | 528 { |
| 521 v8::TryCatch try_catch(isolate); | 529 v8::TryCatch try_catch(isolate); |
| 522 APIBindingHooks::RequestResult hooks_result = binding_hooks_->RunHooks( | 530 APIBindingHooks::RequestResult hooks_result = binding_hooks_->RunHooks( |
| 523 name, context, signature, &argument_list, *type_refs_); | 531 name, context, signature, &argument_list, *type_refs_); |
| 524 | 532 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 588 name, signature->GetExpectedSignature(), error)); | 596 name, signature->GetExpectedSignature(), error)); |
| 589 return; | 597 return; |
| 590 } | 598 } |
| 591 | 599 |
| 592 request_handler_->StartRequest(context, name, std::move(converted_arguments), | 600 request_handler_->StartRequest(context, name, std::move(converted_arguments), |
| 593 callback, custom_callback, | 601 callback, custom_callback, |
| 594 binding::RequestThread::UI); | 602 binding::RequestThread::UI); |
| 595 } | 603 } |
| 596 | 604 |
| 597 } // namespace extensions | 605 } // namespace extensions |
| OLD | NEW |