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 | 482 v8::Local<v8::Object> result; |
jbroman
2017/02/13 19:41:27
nit: Does this variable still need to exist? Looks
Devlin
2017/02/14 04:57:08
Done.
| |
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); | 483 v8::Maybe<bool> has_property = apis->HasRealNamedProperty(context, api_name); |
473 if (!has_property.IsJust()) | 484 if (!has_property.IsJust()) |
474 return; | 485 return v8::Local<v8::Object>(); |
475 | 486 |
476 if (has_property.FromJust()) { | 487 if (has_property.FromJust()) { |
477 result = apis->GetRealNamedProperty(context, api_name).ToLocalChecked(); | 488 v8::Local<v8::Value> value = |
489 apis->GetRealNamedProperty(context, api_name).ToLocalChecked(); | |
490 DCHECK(value->IsObject()); | |
491 result = value.As<v8::Object>(); | |
478 } else { | 492 } else { |
479 ScriptContext* script_context = | 493 ScriptContext* script_context = |
480 ScriptContextSet::GetContextByV8Context(context); | 494 ScriptContextSet::GetContextByV8Context(context); |
481 std::string api_name_string; | 495 std::string api_name_string; |
482 CHECK(gin::Converter<std::string>::FromV8(isolate, api_name, | 496 CHECK(gin::Converter<std::string>::FromV8(isolate, api_name, |
483 &api_name_string)); | 497 &api_name_string)); |
484 | 498 |
485 v8::Local<v8::Object> root_binding = CreateFullBinding( | 499 v8::Local<v8::Object> root_binding = CreateFullBinding( |
486 context, script_context, &data->bindings_system->api_system_, | 500 context, script_context, &data->bindings_system->api_system_, |
487 FeatureProvider::GetAPIFeatures(), api_name_string, get_internal_api); | 501 FeatureProvider::GetAPIFeatures(), api_name_string, get_internal_api); |
488 if (root_binding.IsEmpty()) | 502 if (root_binding.IsEmpty()) |
489 return; | 503 return v8::Local<v8::Object>(); |
490 | 504 |
491 v8::Maybe<bool> success = | 505 v8::Maybe<bool> success = |
492 apis->CreateDataProperty(context, api_name, root_binding); | 506 apis->CreateDataProperty(context, api_name, root_binding); |
493 if (!success.IsJust() || !success.FromJust()) | 507 if (!success.IsJust() || !success.FromJust()) |
494 return; | 508 return v8::Local<v8::Object>(); |
495 | 509 |
496 result = root_binding; | 510 result = root_binding; |
497 } | 511 } |
498 | 512 |
499 info.GetReturnValue().Set(result); | 513 return result; |
514 } | |
515 | |
516 v8::Local<v8::Object> NativeExtensionBindingsSystem::GetRuntime( | |
517 v8::Local<v8::Context> context) { | |
518 return GetAPIHelper(context, | |
519 gin::StringToSymbol(context->GetIsolate(), "runtime")); | |
500 } | 520 } |
501 | 521 |
502 // static | 522 // static |
503 void NativeExtensionBindingsSystem::GetInternalAPI( | 523 void NativeExtensionBindingsSystem::GetInternalAPI( |
504 const v8::FunctionCallbackInfo<v8::Value>& info) { | 524 const v8::FunctionCallbackInfo<v8::Value>& info) { |
505 CHECK_EQ(1, info.Length()); | 525 CHECK_EQ(1, info.Length()); |
506 CHECK(info[0]->IsString()); | 526 CHECK(info[0]->IsString()); |
507 | 527 |
508 v8::Isolate* isolate = info.GetIsolate(); | 528 v8::Isolate* isolate = info.GetIsolate(); |
509 v8::HandleScope handle_scope(isolate); | 529 v8::HandleScope handle_scope(isolate); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
605 | 625 |
606 void NativeExtensionBindingsSystem::OnEventListenerChanged( | 626 void NativeExtensionBindingsSystem::OnEventListenerChanged( |
607 const std::string& event_name, | 627 const std::string& event_name, |
608 binding::EventListenersChanged change, | 628 binding::EventListenersChanged change, |
609 v8::Local<v8::Context> context) { | 629 v8::Local<v8::Context> context) { |
610 send_event_listener_ipc_.Run( | 630 send_event_listener_ipc_.Run( |
611 change, ScriptContextSet::GetContextByV8Context(context), event_name); | 631 change, ScriptContextSet::GetContextByV8Context(context), event_name); |
612 } | 632 } |
613 | 633 |
614 } // namespace extensions | 634 } // namespace extensions |
OLD | NEW |