| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef EXTENSIONS_RENDERER_BINDINGS_API_BINDING_H_ |
| #define EXTENSIONS_RENDERER_BINDINGS_API_BINDING_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include "base/containers/flat_set.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/values.h" |
| #include "extensions/renderer/bindings/argument_spec.h" |
| #include "v8/include/v8.h" |
| |
| namespace gin { |
| class Arguments; |
| } |
| |
| namespace extensions { |
| class APIBindingHooks; |
| class APIEventHandler; |
| class APIRequestHandler; |
| class APISignature; |
| class APITypeReferenceMap; |
| class BindingAccessChecker; |
| |
| namespace binding { |
| enum class RequestThread; |
| } |
| |
| // A class that vends v8::Objects for extension APIs. These APIs have function |
| // interceptors for all exposed methods, which call back into the APIBinding. |
| // The APIBinding then matches the calling arguments against an expected method |
| // signature, throwing an error if they don't match. |
| // There should only need to be a single APIBinding object for each API, and |
| // each can vend multiple v8::Objects for different contexts. |
| // This object is designed to be one-per-isolate, but used across separate |
| // contexts. |
| class APIBinding { |
| public: |
| using CreateCustomType = base::RepeatingCallback<v8::Local<v8::Object>( |
| v8::Isolate* isolate, |
| const std::string& type_name, |
| const std::string& property_name, |
| const base::Value::List* property_values)>; |
| |
| // Called when a request is handled without notifying the browser. |
| using OnSilentRequest = base::RepeatingCallback<void( |
| v8::Local<v8::Context>, |
| const std::string& name, |
| const v8::LocalVector<v8::Value>& arguments)>; |
| |
| // The callback type for handling an API call. |
| using HandlerCallback = base::RepeatingCallback<void(gin::Arguments*)>; |
| |
| // The APITypeReferenceMap is required to outlive this object. |
| // `function_definitions`, `type_definitions` and `event_definitions` |
| // may be null if the API does not specify any of that category. |
| APIBinding(const std::string& name, |
| const base::Value::List* function_definitions, |
| const base::Value::List* type_definitions, |
| const base::Value::List* event_definitions, |
| const base::Value::Dict* property_definitions, |
| CreateCustomType create_custom_type, |
| OnSilentRequest on_silent_request, |
| std::unique_ptr<APIBindingHooks> binding_hooks, |
| APITypeReferenceMap* type_refs, |
| APIRequestHandler* request_handler, |
| APIEventHandler* event_handler, |
| BindingAccessChecker* access_checker); |
| |
| APIBinding(const APIBinding&) = delete; |
| APIBinding& operator=(const APIBinding&) = delete; |
| |
| ~APIBinding(); |
| |
| // Returns a new v8::Object for the API this APIBinding represents. |
| v8::Local<v8::Object> CreateInstance(v8::Local<v8::Context> context); |
| |
| APIBindingHooks* hooks() { return binding_hooks_.get(); } |
| |
| private: |
| // Initializes the object_template_ for this API. Called lazily when the |
| // first instance is created. |
| void InitializeTemplate(v8::Isolate* isolate); |
| |
| // Decorates `object_template` with the properties specified by `properties`. |
| // `is_root` is used to determine whether to add the properties to |
| // `root_properties_`. |
| void DecorateTemplateWithProperties( |
| v8::Isolate* isolate, |
| v8::Local<v8::ObjectTemplate> object_template, |
| const base::Value::Dict& properties, |
| bool is_root); |
| |
| // Handler for getting the v8::Object associated with an event on the API. |
| static void GetEventObject(v8::Local<v8::Name>, |
| const v8::PropertyCallbackInfo<v8::Value>& info); |
| |
| // Handler for getting the v8::Object associated with a custom property on the |
| // API. |
| static void GetCustomPropertyObject( |
| v8::Local<v8::Name> property, |
| const v8::PropertyCallbackInfo<v8::Value>& info); |
| |
| // Handles calling of an API method with the given `name` on the given |
| // `thread` and matches the arguments against `signature`. |
| void HandleCall(const std::string& name, |
| const APISignature* signature, |
| gin::Arguments* args); |
| |
| // The root name of the API, e.g. "tabs" for chrome.tabs. |
| std::string api_name_; |
| |
| // A map from method name to method data. |
| struct MethodData; |
| std::map<std::string, std::unique_ptr<MethodData>> methods_; |
| |
| // The events associated with this API. |
| struct EventData; |
| std::vector<std::unique_ptr<EventData>> events_; |
| |
| // The custom properties on the API; these are rare. |
| struct CustomPropertyData; |
| std::vector<std::unique_ptr<CustomPropertyData>> custom_properties_; |
| |
| // The pair for enum entry is <original, js-ified>. JS enum entries use |
| // SCREAMING_STYLE (whereas our API enums are just inconsistent). |
| using EnumEntry = std::pair<std::string, std::string>; |
| // A map of <name, values> for the enums on this API. |
| std::map<std::string, std::vector<EnumEntry>> enums_; |
| |
| // The associated properties of the API, if any. |
| raw_ptr<const base::Value::Dict> property_definitions_; |
| // The names of all the "root properties" added to the API; i.e., properties |
| // exposed on the API object itself. |
| base::flat_set<std::string> root_properties_; |
| |
| // The callback for constructing a custom type. |
| CreateCustomType create_custom_type_; |
| |
| OnSilentRequest on_silent_request_; |
| |
| // The registered hooks for this API. |
| std::unique_ptr<APIBindingHooks> binding_hooks_; |
| |
| // The reference map for all known types; required to outlive this object. |
| raw_ptr<APITypeReferenceMap> type_refs_; |
| |
| // The associated request handler, shared between this and other bindings. |
| // Required to outlive this object. |
| raw_ptr<APIRequestHandler, DanglingUntriaged> request_handler_; |
| |
| // The associated event handler, shared between this and other bindings. |
| // Required to outlive this object. |
| raw_ptr<APIEventHandler, DanglingUntriaged> event_handler_; |
| |
| // The associated access checker; required to outlive this object. |
| const raw_ptr<const BindingAccessChecker, DanglingUntriaged> access_checker_; |
| |
| // The template for this API. Note: some methods may only be available in |
| // certain contexts, but this template contains all methods. Those that are |
| // unavailable are removed after object instantiation. |
| v8::Eternal<v8::ObjectTemplate> object_template_; |
| |
| base::WeakPtrFactory<APIBinding> weak_factory_{this}; |
| }; |
| |
| } // namespace extensions |
| |
| #endif // EXTENSIONS_RENDERER_BINDINGS_API_BINDING_H_ |