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 |