File: api_signature.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (188 lines) | stat: -rw-r--r-- 7,731 bytes parent folder | download | duplicates (5)
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
177
178
179
180
181
182
183
184
185
186
187
188
// 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_SIGNATURE_H_
#define EXTENSIONS_RENDERER_BINDINGS_API_SIGNATURE_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "extensions/renderer/bindings/api_binding_types.h"
#include "extensions/renderer/bindings/binding_access_checker.h"
#include "v8/include/v8.h"

namespace extensions {
class APITypeReferenceMap;
class ArgumentSpec;
class BindingAccessChecker;

// Whether promises are allowed to be used for a given call to an API.
enum class PromisesAllowed {
  kAllowed,
  kDisallowed,
};

// A representation of the expected signature for an API, along with the
// ability to match provided arguments and convert them to base::Values.
// This is primarily used for API methods, but can also be used for API event
// signatures.
class APISignature {
 public:
  // Struct that bundles all the details about an asynchronous return.
  struct ReturnsAsync {
    ReturnsAsync();
    ~ReturnsAsync();

    // The list of expected arguments for the asynchronous return. Can be
    // nullopt if response validation isn't enabled, as it is only used when
    // validating a response from the API.
    std::optional<std::vector<std::unique_ptr<ArgumentSpec>>> signature;
    // Indicates if passing the callback when calling the API is optional for
    // contexts or APIs which do not support promises (passing the callback is
    // always inheriently optional if promises are supported).
    bool optional = false;
    // Indicates if this API supports allowing promises for the asynchronous
    // return. Note that this is distinct from whether an actual call to the API
    // is allowed to use the promise based form, as that also depends on if the
    // calling context being checked by the access_checker.
    binding::APIPromiseSupport promise_support =
        binding::APIPromiseSupport::kUnsupported;
  };

  APISignature(std::vector<std::unique_ptr<ArgumentSpec>> signature,
               std::unique_ptr<APISignature::ReturnsAsync> returns_async,
               BindingAccessChecker* access_checker);

  APISignature(const APISignature&) = delete;
  APISignature& operator=(const APISignature&) = delete;

  ~APISignature();

  // Creates an APISignature object from the raw Value representations of an
  // API schema.
  static std::unique_ptr<APISignature> CreateFromValues(
      const base::Value& specification_list,
      const base::Value* returns_async,
      BindingAccessChecker* access_checker);

  struct V8ParseResult {
    // Appease the Chromium style plugin (out of line ctor/dtor).
    V8ParseResult();
    ~V8ParseResult();
    V8ParseResult(V8ParseResult&& other);
    V8ParseResult& operator=(V8ParseResult&& other);

    bool succeeded() const { return arguments.has_value(); }

    // The parsed v8 arguments. These may differ from the original v8 arguments
    // since it will include null-filled optional arguments. Populated if
    // parsing was successful. Note that the callback, if any, is included in
    // this list.
    std::optional<v8::LocalVector<v8::Value>> arguments;

    // Whether the asynchronous response is handled by a callback or a promise.
    binding::AsyncResponseType async_type = binding::AsyncResponseType::kNone;

    // The parse error, if parsing failed.
    std::optional<std::string> error;
  };

  struct JSONParseResult {
    // Appease the Chromium style plugin (out of line ctor/dtor).
    JSONParseResult();
    ~JSONParseResult();
    JSONParseResult(JSONParseResult&& other);
    JSONParseResult& operator=(JSONParseResult&& other);

    bool succeeded() const { return arguments_list.has_value(); }

    // The parsed JSON arguments, with null-filled optional arguments filled in.
    // Populated if parsing was successful. Does not include the callback (if
    // any).
    std::optional<base::Value::List> arguments_list;

    // The callback, if one was provided.
    v8::Local<v8::Function> callback;

    // Whether the asynchronous response is handled by a callback or a promise.
    binding::AsyncResponseType async_type = binding::AsyncResponseType::kNone;

    // The parse error, if parsing failed.
    std::optional<std::string> error;
  };

  // Parses `arguments` against this signature, returning the result and
  // performing no argument conversion.
  V8ParseResult ParseArgumentsToV8(v8::Local<v8::Context> context,
                                   const v8::LocalVector<v8::Value>& arguments,
                                   const APITypeReferenceMap& type_refs) const;

  // Parses `arguments` against this signature, returning the result after
  // converting to base::Values.
  JSONParseResult ParseArgumentsToJSON(
      v8::Local<v8::Context> context,
      const v8::LocalVector<v8::Value>& arguments,
      const APITypeReferenceMap& type_refs) const;

  // Converts `arguments` to base::Values, ignoring the defined signature.
  // This is used when custom bindings modify the passed arguments to a form
  // that doesn't match the documented signature. Since we ignore the schema,
  // this parsing will never fail.
  JSONParseResult ConvertArgumentsIgnoringSchema(
      v8::Local<v8::Context> context,
      const v8::LocalVector<v8::Value>& arguments) const;

  // Validates the provided `arguments` as if they were returned as a response
  // to an API call. This validation is much stricter than the versions above,
  // since response arguments are not allowed to have optional inner parameters.
  bool ValidateResponse(v8::Local<v8::Context> context,
                        const v8::LocalVector<v8::Value>& arguments,
                        const APITypeReferenceMap& type_refs,
                        std::string* error) const;

  // Same as `ValidateResponse`, but verifies the given `arguments` against the
  // `signature_` instead of the `returns_async_` types. This can be used when
  // validating that APIs return proper values to an event (which has a
  // signature, but no return).
  bool ValidateCall(v8::Local<v8::Context> context,
                    const v8::LocalVector<v8::Value>& arguments,
                    const APITypeReferenceMap& type_refs,
                    std::string* error) const;

  // Returns a developer-readable string of the expected signature. For
  // instance, if this signature expects a string 'someStr' and an optional int
  // 'someInt', this would return "string someStr, optional integer someInt".
  std::string GetExpectedSignature() const;

  bool has_async_return() const { return returns_async_ != nullptr; }
  bool has_async_return_signature() const {
    return has_async_return() && returns_async_->signature.has_value();
  }

 private:
  // Checks if promises are allowed to be used for a call to an API from a given
  // `context`.
  PromisesAllowed CheckPromisesAllowed(v8::Local<v8::Context> context) const;

  // The list of expected arguments for the API signature.
  std::vector<std::unique_ptr<ArgumentSpec>> signature_;

  // The details of any asynchronous return an API method may have. This will be
  // nullptr if the the API doesn't have an asynchronous return.
  std::unique_ptr<APISignature::ReturnsAsync> returns_async_;

  // The associated access checker; required to outlive this object.
  raw_ptr<const BindingAccessChecker, DanglingUntriaged> access_checker_;

  // A developer-readable method signature string, lazily set.
  mutable std::string expected_signature_;
};

}  // namespace extensions

#endif  // EXTENSIONS_RENDERER_BINDINGS_API_SIGNATURE_H_