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/native_extension_bindings_system.h" | 5 #include "extensions/renderer/native_extension_bindings_system.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "content/public/common/content_switches.h" | 9 #include "content/public/common/content_switches.h" |
10 #include "extensions/common/constants.h" | 10 #include "extensions/common/constants.h" |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 const SendEventListenerIPCMethod& send_event_listener_ipc) | 319 const SendEventListenerIPCMethod& send_event_listener_ipc) |
320 : send_request_ipc_(send_request_ipc), | 320 : send_request_ipc_(send_request_ipc), |
321 send_event_listener_ipc_(send_event_listener_ipc), | 321 send_event_listener_ipc_(send_event_listener_ipc), |
322 api_system_( | 322 api_system_( |
323 base::Bind(&CallJsFunction), | 323 base::Bind(&CallJsFunction), |
324 base::Bind(&CallJsFunctionSync), | 324 base::Bind(&CallJsFunctionSync), |
325 base::Bind(&GetAPISchema), | 325 base::Bind(&GetAPISchema), |
326 base::Bind(&NativeExtensionBindingsSystem::SendRequest, | 326 base::Bind(&NativeExtensionBindingsSystem::SendRequest, |
327 base::Unretained(this)), | 327 base::Unretained(this)), |
328 base::Bind(&NativeExtensionBindingsSystem::OnEventListenerChanged, | 328 base::Bind(&NativeExtensionBindingsSystem::OnEventListenerChanged, |
329 base::Unretained(this))), | 329 base::Unretained(this)), |
| 330 APILastError(base::Bind(&GetRuntime))), |
330 weak_factory_(this) {} | 331 weak_factory_(this) {} |
331 | 332 |
332 NativeExtensionBindingsSystem::~NativeExtensionBindingsSystem() {} | 333 NativeExtensionBindingsSystem::~NativeExtensionBindingsSystem() {} |
333 | 334 |
334 void NativeExtensionBindingsSystem::DidCreateScriptContext( | 335 void NativeExtensionBindingsSystem::DidCreateScriptContext( |
335 ScriptContext* context) {} | 336 ScriptContext* context) {} |
336 | 337 |
337 void NativeExtensionBindingsSystem::WillReleaseScriptContext( | 338 void NativeExtensionBindingsSystem::WillReleaseScriptContext( |
338 ScriptContext* context) {} | 339 ScriptContext* context) {} |
339 | 340 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 // expose this under the name of the feature (e.g., 'tabs'), but in some | 397 // expose this under the name of the feature (e.g., 'tabs'), but in some |
397 // cases, this will be a prefixed API, such as 'app.runtime'. Find what the | 398 // cases, this will be a prefixed API, such as 'app.runtime'. Find what the |
398 // property on the chrome object is named, and use that. So in the case of | 399 // property on the chrome object is named, and use that. So in the case of |
399 // 'app.runtime', we surface a getter for simply 'app'. | 400 // 'app.runtime', we surface a getter for simply 'app'. |
400 base::StringPiece accessor_name = | 401 base::StringPiece accessor_name = |
401 GetFirstDifferentAPIName(map_entry.first, base::StringPiece()); | 402 GetFirstDifferentAPIName(map_entry.first, base::StringPiece()); |
402 last_accessor = accessor_name; | 403 last_accessor = accessor_name; |
403 v8::Local<v8::String> api_name = | 404 v8::Local<v8::String> api_name = |
404 gin::StringToSymbol(v8_context->GetIsolate(), accessor_name); | 405 gin::StringToSymbol(v8_context->GetIsolate(), accessor_name); |
405 v8::Maybe<bool> success = chrome->SetAccessor( | 406 v8::Maybe<bool> success = chrome->SetAccessor( |
406 v8_context, api_name, &GetAPIHelper, nullptr, api_name); | 407 v8_context, api_name, &BindingAccessor, nullptr, api_name); |
407 if (!success.IsJust() || !success.FromJust()) { | 408 if (!success.IsJust() || !success.FromJust()) { |
408 LOG(ERROR) << "Failed to create API on Chrome object."; | 409 LOG(ERROR) << "Failed to create API on Chrome object."; |
409 return; | 410 return; |
410 } | 411 } |
411 } | 412 } |
412 } | 413 } |
413 | 414 |
414 void NativeExtensionBindingsSystem::DispatchEventInContext( | 415 void NativeExtensionBindingsSystem::DispatchEventInContext( |
415 const std::string& event_name, | 416 const std::string& event_name, |
416 const base::ListValue* event_args, | 417 const base::ListValue* event_args, |
417 const base::DictionaryValue* filtering_info, | 418 const base::DictionaryValue* filtering_info, |
418 ScriptContext* context) { | 419 ScriptContext* context) { |
419 v8::HandleScope handle_scope(context->isolate()); | 420 v8::HandleScope handle_scope(context->isolate()); |
420 v8::Context::Scope context_scope(context->v8_context()); | 421 v8::Context::Scope context_scope(context->v8_context()); |
421 // TODO(devlin): Take into account |filtering_info|. | 422 // TODO(devlin): Take into account |filtering_info|. |
422 api_system_.FireEventInContext(event_name, context->v8_context(), | 423 api_system_.FireEventInContext(event_name, context->v8_context(), |
423 *event_args); | 424 *event_args); |
424 } | 425 } |
425 | 426 |
426 void NativeExtensionBindingsSystem::HandleResponse( | 427 void NativeExtensionBindingsSystem::HandleResponse( |
427 int request_id, | 428 int request_id, |
428 bool success, | 429 bool success, |
429 const base::ListValue& response, | 430 const base::ListValue& response, |
430 const std::string& error) { | 431 const std::string& error) { |
431 api_system_.CompleteRequest(request_id, response); | 432 api_system_.CompleteRequest(request_id, response, error); |
432 } | 433 } |
433 | 434 |
434 RequestSender* NativeExtensionBindingsSystem::GetRequestSender() { | 435 RequestSender* NativeExtensionBindingsSystem::GetRequestSender() { |
435 return nullptr; | 436 return nullptr; |
436 } | 437 } |
437 | 438 |
438 // static | 439 void NativeExtensionBindingsSystem::BindingAccessor( |
439 void NativeExtensionBindingsSystem::GetAPIHelper( | |
440 v8::Local<v8::Name> name, | 440 v8::Local<v8::Name> name, |
441 const v8::PropertyCallbackInfo<v8::Value>& info) { | 441 const v8::PropertyCallbackInfo<v8::Value>& info) { |
442 v8::Isolate* isolate = info.GetIsolate(); | 442 v8::Isolate* isolate = info.GetIsolate(); |
443 v8::HandleScope handle_scope(isolate); | 443 v8::HandleScope handle_scope(isolate); |
444 v8::Local<v8::Context> context = info.Holder()->CreationContext(); | 444 v8::Local<v8::Context> context = info.Holder()->CreationContext(); |
| 445 |
| 446 // We use info.Data() to store a real name here instead of using the provided |
| 447 // one to handle any weirdness from the caller (non-existent strings, etc). |
| 448 v8::Local<v8::String> api_name = info.Data().As<v8::String>(); |
| 449 v8::Local<v8::Object> binding = GetAPIHelper(context, api_name); |
| 450 if (!binding.IsEmpty()) |
| 451 info.GetReturnValue().Set(binding); |
| 452 } |
| 453 |
| 454 // static |
| 455 v8::Local<v8::Object> NativeExtensionBindingsSystem::GetAPIHelper( |
| 456 v8::Local<v8::Context> context, |
| 457 v8::Local<v8::String> api_name) { |
445 BindingsSystemPerContextData* data = GetBindingsDataFromContext(context); | 458 BindingsSystemPerContextData* data = GetBindingsDataFromContext(context); |
446 if (!data) | 459 if (!data) |
447 return; | 460 return v8::Local<v8::Object>(); |
448 | 461 |
| 462 v8::Isolate* isolate = context->GetIsolate(); |
449 v8::Local<v8::Object> apis; | 463 v8::Local<v8::Object> apis; |
450 if (data->api_object.IsEmpty()) { | 464 if (data->api_object.IsEmpty()) { |
451 apis = v8::Object::New(isolate); | 465 apis = v8::Object::New(isolate); |
452 data->api_object = v8::Global<v8::Object>(isolate, apis); | 466 data->api_object = v8::Global<v8::Object>(isolate, apis); |
453 if (data->bindings_system->get_internal_api_.IsEmpty()) { | 467 if (data->bindings_system->get_internal_api_.IsEmpty()) { |
454 data->bindings_system->get_internal_api_.Set( | 468 data->bindings_system->get_internal_api_.Set( |
455 isolate, v8::FunctionTemplate::New( | 469 isolate, v8::FunctionTemplate::New( |
456 isolate, &NativeExtensionBindingsSystem::GetInternalAPI, | 470 isolate, &NativeExtensionBindingsSystem::GetInternalAPI, |
457 v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, | 471 v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, |
458 v8::ConstructorBehavior::kThrow)); | 472 v8::ConstructorBehavior::kThrow)); |
459 } | 473 } |
460 } else { | 474 } else { |
461 apis = data->api_object.Get(isolate); | 475 apis = data->api_object.Get(isolate); |
462 } | 476 } |
463 v8::Local<v8::Function> get_internal_api = | 477 v8::Local<v8::Function> get_internal_api = |
464 data->bindings_system->get_internal_api_.Get(isolate) | 478 data->bindings_system->get_internal_api_.Get(isolate) |
465 ->GetFunction(context) | 479 ->GetFunction(context) |
466 .ToLocalChecked(); | 480 .ToLocalChecked(); |
467 | 481 |
468 // We use info.Data() to store a real name here instead of using the provided | |
469 // one to handle any weirdness from the caller (non-existent strings, etc). | |
470 v8::Local<v8::String> api_name = info.Data().As<v8::String>(); | |
471 v8::Local<v8::Value> result; | |
472 v8::Maybe<bool> has_property = apis->HasRealNamedProperty(context, api_name); | 482 v8::Maybe<bool> has_property = apis->HasRealNamedProperty(context, api_name); |
473 if (!has_property.IsJust()) | 483 if (!has_property.IsJust()) |
474 return; | 484 return v8::Local<v8::Object>(); |
475 | 485 |
476 if (has_property.FromJust()) { | 486 if (has_property.FromJust()) { |
477 result = apis->GetRealNamedProperty(context, api_name).ToLocalChecked(); | 487 v8::Local<v8::Value> value = |
478 } else { | 488 apis->GetRealNamedProperty(context, api_name).ToLocalChecked(); |
479 ScriptContext* script_context = | 489 DCHECK(value->IsObject()); |
480 ScriptContextSet::GetContextByV8Context(context); | 490 return value.As<v8::Object>(); |
481 std::string api_name_string; | |
482 CHECK(gin::Converter<std::string>::FromV8(isolate, api_name, | |
483 &api_name_string)); | |
484 | |
485 v8::Local<v8::Object> root_binding = CreateFullBinding( | |
486 context, script_context, &data->bindings_system->api_system_, | |
487 FeatureProvider::GetAPIFeatures(), api_name_string, get_internal_api); | |
488 if (root_binding.IsEmpty()) | |
489 return; | |
490 | |
491 v8::Maybe<bool> success = | |
492 apis->CreateDataProperty(context, api_name, root_binding); | |
493 if (!success.IsJust() || !success.FromJust()) | |
494 return; | |
495 | |
496 result = root_binding; | |
497 } | 491 } |
498 | 492 |
499 info.GetReturnValue().Set(result); | 493 ScriptContext* script_context = |
| 494 ScriptContextSet::GetContextByV8Context(context); |
| 495 std::string api_name_string; |
| 496 CHECK( |
| 497 gin::Converter<std::string>::FromV8(isolate, api_name, &api_name_string)); |
| 498 |
| 499 v8::Local<v8::Object> root_binding = CreateFullBinding( |
| 500 context, script_context, &data->bindings_system->api_system_, |
| 501 FeatureProvider::GetAPIFeatures(), api_name_string, get_internal_api); |
| 502 if (root_binding.IsEmpty()) |
| 503 return v8::Local<v8::Object>(); |
| 504 |
| 505 v8::Maybe<bool> success = |
| 506 apis->CreateDataProperty(context, api_name, root_binding); |
| 507 if (!success.IsJust() || !success.FromJust()) |
| 508 return v8::Local<v8::Object>(); |
| 509 |
| 510 return root_binding; |
| 511 } |
| 512 |
| 513 v8::Local<v8::Object> NativeExtensionBindingsSystem::GetRuntime( |
| 514 v8::Local<v8::Context> context) { |
| 515 return GetAPIHelper(context, |
| 516 gin::StringToSymbol(context->GetIsolate(), "runtime")); |
500 } | 517 } |
501 | 518 |
502 // static | 519 // static |
503 void NativeExtensionBindingsSystem::GetInternalAPI( | 520 void NativeExtensionBindingsSystem::GetInternalAPI( |
504 const v8::FunctionCallbackInfo<v8::Value>& info) { | 521 const v8::FunctionCallbackInfo<v8::Value>& info) { |
505 CHECK_EQ(1, info.Length()); | 522 CHECK_EQ(1, info.Length()); |
506 CHECK(info[0]->IsString()); | 523 CHECK(info[0]->IsString()); |
507 | 524 |
508 v8::Isolate* isolate = info.GetIsolate(); | 525 v8::Isolate* isolate = info.GetIsolate(); |
509 v8::HandleScope handle_scope(isolate); | 526 v8::HandleScope handle_scope(isolate); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 | 622 |
606 void NativeExtensionBindingsSystem::OnEventListenerChanged( | 623 void NativeExtensionBindingsSystem::OnEventListenerChanged( |
607 const std::string& event_name, | 624 const std::string& event_name, |
608 binding::EventListenersChanged change, | 625 binding::EventListenersChanged change, |
609 v8::Local<v8::Context> context) { | 626 v8::Local<v8::Context> context) { |
610 send_event_listener_ipc_.Run( | 627 send_event_listener_ipc_.Run( |
611 change, ScriptContextSet::GetContextByV8Context(context), event_name); | 628 change, ScriptContextSet::GetContextByV8Context(context), event_name); |
612 } | 629 } |
613 | 630 |
614 } // namespace extensions | 631 } // namespace extensions |
OLD | NEW |