1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
// 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_
|