api_bindings_system.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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
  3. // found in the LICENSE file.
  4. #include "extensions/renderer/bindings/api_bindings_system.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/values.h"
  8. #include "extensions/common/mojom/event_dispatcher.mojom.h"
  9. #include "extensions/renderer/bindings/api_binding_hooks.h"
  10. #include "extensions/renderer/bindings/api_binding_util.h"
  11. #include "extensions/renderer/bindings/api_response_validator.h"
  12. #include "extensions/renderer/bindings/interaction_provider.h"
  13. namespace extensions {
  14. APIBindingsSystem::APIBindingsSystem(
  15. GetAPISchemaMethod get_api_schema,
  16. BindingAccessChecker::APIAvailabilityCallback api_available,
  17. BindingAccessChecker::PromiseAvailabilityCallback promises_available,
  18. APIRequestHandler::SendRequestMethod send_request,
  19. std::unique_ptr<InteractionProvider> interaction_provider,
  20. APIEventListeners::ListenersUpdated event_listeners_changed,
  21. APIEventHandler::ContextOwnerIdGetter context_owner_getter,
  22. APIBinding::OnSilentRequest on_silent_request,
  23. binding::AddConsoleError add_console_error,
  24. APILastError last_error)
  25. : type_reference_map_(
  26. base::BindRepeating(&APIBindingsSystem::InitializeType,
  27. base::Unretained(this))),
  28. exception_handler_(std::move(add_console_error)),
  29. interaction_provider_(std::move(interaction_provider)),
  30. request_handler_(std::move(send_request),
  31. std::move(last_error),
  32. &exception_handler_,
  33. interaction_provider_.get()),
  34. event_handler_(std::move(event_listeners_changed),
  35. std::move(context_owner_getter),
  36. &exception_handler_),
  37. access_checker_(std::move(api_available), std::move(promises_available)),
  38. get_api_schema_(std::move(get_api_schema)),
  39. on_silent_request_(std::move(on_silent_request)) {
  40. if (binding::IsResponseValidationEnabled()) {
  41. request_handler_.SetResponseValidator(
  42. std::make_unique<APIResponseValidator>(&type_reference_map_));
  43. event_handler_.SetResponseValidator(
  44. std::make_unique<APIResponseValidator>(&type_reference_map_));
  45. }
  46. }
  47. APIBindingsSystem::~APIBindingsSystem() {}
  48. v8::Local<v8::Object> APIBindingsSystem::CreateAPIInstance(
  49. const std::string& api_name,
  50. v8::Local<v8::Context> context,
  51. APIBindingHooks** hooks_out) {
  52. std::unique_ptr<APIBinding>& binding = api_bindings_[api_name];
  53. if (!binding)
  54. binding = CreateNewAPIBinding(api_name);
  55. if (hooks_out)
  56. *hooks_out = binding->hooks();
  57. return binding->CreateInstance(context);
  58. }
  59. std::unique_ptr<APIBinding> APIBindingsSystem::CreateNewAPIBinding(
  60. const std::string& api_name) {
  61. const base::DictionaryValue& api_schema = get_api_schema_.Run(api_name);
  62. const base::ListValue* function_definitions = nullptr;
  63. api_schema.GetList("functions", &function_definitions);
  64. const base::ListValue* type_definitions = nullptr;
  65. api_schema.GetList("types", &type_definitions);
  66. const base::ListValue* event_definitions = nullptr;
  67. api_schema.GetList("events", &event_definitions);
  68. const base::DictionaryValue* property_definitions = nullptr;
  69. api_schema.GetDictionary("properties", &property_definitions);
  70. // Find the hooks for the API. If none exist, an empty set will be created so
  71. // we can use JS custom bindings.
  72. // TODO(devlin): Once all legacy custom bindings are converted, we don't have
  73. // to unconditionally pass in binding hooks.
  74. std::unique_ptr<APIBindingHooks> hooks;
  75. auto iter = binding_hooks_.find(api_name);
  76. if (iter != binding_hooks_.end()) {
  77. hooks = std::move(iter->second);
  78. binding_hooks_.erase(iter);
  79. } else {
  80. hooks = std::make_unique<APIBindingHooks>(api_name, &request_handler_);
  81. }
  82. return std::make_unique<APIBinding>(
  83. api_name, function_definitions, type_definitions, event_definitions,
  84. property_definitions,
  85. base::BindRepeating(&APIBindingsSystem::CreateCustomType,
  86. base::Unretained(this)),
  87. on_silent_request_, std::move(hooks), &type_reference_map_,
  88. &request_handler_, &event_handler_, &access_checker_);
  89. }
  90. void APIBindingsSystem::InitializeType(const std::string& type_name) {
  91. // In order to initialize the type, we just initialize the full binding. This
  92. // seems like a lot of work, but in practice, trying to extract out only the
  93. // types from the schema, and then update the reference map based on that, is
  94. // close enough to the same cost. Additionally, this happens lazily on API
  95. // use, and relatively few APIs specify types from another API. Finally, this
  96. // will also go away if/when we generate all these specifications.
  97. std::string::size_type dot = type_name.rfind('.');
  98. // The type name should be fully qualified (include the API name).
  99. DCHECK_NE(std::string::npos, dot) << type_name;
  100. DCHECK_LT(dot, type_name.size() - 1);
  101. std::string api_name = type_name.substr(0, dot);
  102. // If we've already instantiated the binding, the type should have been in
  103. // there.
  104. DCHECK(api_bindings_.find(api_name) == api_bindings_.end()) << api_name;
  105. api_bindings_[api_name] = CreateNewAPIBinding(api_name);
  106. }
  107. void APIBindingsSystem::CompleteRequest(int request_id,
  108. const base::Value::List& response,
  109. const std::string& error) {
  110. request_handler_.CompleteRequest(request_id, response, error);
  111. }
  112. void APIBindingsSystem::FireEventInContext(
  113. const std::string& event_name,
  114. v8::Local<v8::Context> context,
  115. const base::Value::List& response,
  116. mojom::EventFilteringInfoPtr filter) {
  117. event_handler_.FireEventInContext(event_name, context, response,
  118. std::move(filter));
  119. }
  120. APIBindingHooks* APIBindingsSystem::GetHooksForAPI(
  121. const std::string& api_name) {
  122. DCHECK(api_bindings_.empty())
  123. << "Hook registration must happen before creating any binding instances.";
  124. std::unique_ptr<APIBindingHooks>& hooks = binding_hooks_[api_name];
  125. if (!hooks)
  126. hooks = std::make_unique<APIBindingHooks>(api_name, &request_handler_);
  127. return hooks.get();
  128. }
  129. void APIBindingsSystem::RegisterCustomType(const std::string& type_name,
  130. CustomTypeHandler function) {
  131. DCHECK(custom_types_.find(type_name) == custom_types_.end())
  132. << "Custom type already registered: " << type_name;
  133. custom_types_[type_name] = std::move(function);
  134. }
  135. void APIBindingsSystem::WillReleaseContext(v8::Local<v8::Context> context) {
  136. binding::InvalidateContext(context);
  137. request_handler_.InvalidateContext(context);
  138. event_handler_.InvalidateContext(context);
  139. }
  140. v8::Local<v8::Object> APIBindingsSystem::CreateCustomType(
  141. v8::Isolate* isolate,
  142. const std::string& type_name,
  143. const std::string& property_name,
  144. const base::ListValue* property_values) {
  145. auto iter = custom_types_.find(type_name);
  146. DCHECK(iter != custom_types_.end()) << "Custom type not found: " << type_name;
  147. return iter->second.Run(isolate, property_name, property_values,
  148. &request_handler_, &event_handler_,
  149. &type_reference_map_, &access_checker_);
  150. }
  151. } // namespace extensions