summaryrefslogtreecommitdiff
path: root/chromium/extensions/renderer/api_binding.h
blob: 870f8c12730d603c4865c7ff4e524c556bf8789d (plain)
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
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EXTENSIONS_RENDERER_API_BINDING_H_
#define EXTENSIONS_RENDERER_API_BINDING_H_

#include <map>
#include <memory>
#include <string>

#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "extensions/renderer/argument_spec.h"
#include "v8/include/v8.h"

namespace base {
class ListValue;
}

namespace gin {
class Arguments;
}

namespace extensions {
class APIBindingHooks;
class APIEventHandler;
class APIRequestHandler;
class APISignature;
class APITypeReferenceMap;

// 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::Callback<v8::Local<v8::Object>(v8::Local<v8::Context> context,
                                           const std::string& type_name,
                                           const std::string& property_name)>;

  // The callback for determining if a given API method (specified by |name|)
  // is available.
  using AvailabilityCallback = base::Callback<bool(const std::string& name)>;

  // The callback type for handling an API call.
  using HandlerCallback = base::Callback<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::ListValue* function_definitions,
             const base::ListValue* type_definitions,
             const base::ListValue* event_definitions,
             const base::DictionaryValue* property_definitions,
             const CreateCustomType& create_custom_type,
             std::unique_ptr<APIBindingHooks> binding_hooks,
             APITypeReferenceMap* type_refs,
             APIRequestHandler* request_handler,
             APIEventHandler* event_handler);
  ~APIBinding();

  // Returns a new v8::Object for the API this APIBinding represents.
  v8::Local<v8::Object> CreateInstance(
      v8::Local<v8::Context> context,
      v8::Isolate* isolate,
      const AvailabilityCallback& is_available);

  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|.
  void DecorateTemplateWithProperties(
      v8::Isolate* isolate,
      v8::Local<v8::ObjectTemplate> object_template,
      const base::DictionaryValue& properties);

  // 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 a call an API method with the given |name| 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.
  const base::DictionaryValue* property_definitions_;

  // The callback for constructing a custom type.
  CreateCustomType create_custom_type_;

  // The registered hooks for this API.
  std::unique_ptr<APIBindingHooks> binding_hooks_;

  // The reference map for all known types; required to outlive this object.
  const APITypeReferenceMap* type_refs_;

  // The associated request handler, shared between this and other bindings.
  // Required to outlive this object.
  APIRequestHandler* request_handler_;

  // 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_;

  DISALLOW_COPY_AND_ASSIGN(APIBinding);
};

}  // namespace extensions

#endif  // EXTENSIONS_RENDERER_API_BINDING_H_