File: api_request_handler.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (199 lines) | stat: -rw-r--r-- 7,247 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
189
190
191
192
193
194
195
196
197
198
199
// 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_REQUEST_HANDLER_H_
#define EXTENSIONS_RENDERER_BINDINGS_API_REQUEST_HANDLER_H_

#include <map>
#include <memory>
#include <optional>
#include <set>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "extensions/common/mojom/extra_response_data.mojom.h"
#include "extensions/renderer/bindings/api_binding_types.h"
#include "extensions/renderer/bindings/api_last_error.h"
#include "extensions/renderer/bindings/interaction_provider.h"
#include "v8/include/v8.h"

namespace extensions {
class APIResponseValidator;
class ExceptionHandler;

// A wrapper around a map for extension API calls. Contains all pending requests
// and the associated context and callback. Designed to be used on a single
// thread, but amongst multiple contexts.
class APIRequestHandler {
 public:
  // TODO(devlin): We may want to coalesce this with the
  // ExtensionHostMsg_Request_Params IPC struct.
  struct Request {
    Request();

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

    ~Request();

    int request_id = -1;
    std::string method_name;
    bool has_async_response_handler = false;
    bool has_user_gesture = false;
    base::Value::List arguments_list;
  };

  // Details about a newly-added request to provide as a return to callers.
  // Contains the id of the request and if this is a promise based request, the
  // associated promise.
  struct RequestDetails {
    RequestDetails(int request_id, v8::Local<v8::Promise> promise);
    ~RequestDetails();
    RequestDetails(const RequestDetails& other);

    const int request_id;
    v8::Local<v8::Promise> promise;
  };

  using SendRequestMethod =
      base::RepeatingCallback<void(std::unique_ptr<Request>,
                                   v8::Local<v8::Context>)>;

  APIRequestHandler(SendRequestMethod send_request,
                    APILastError last_error,
                    ExceptionHandler* exception_handler,
                    const InteractionProvider* interaction_provider);

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

  ~APIRequestHandler();

  // Begins the process of processing the request. If this is a promise based
  // request returns the associated promise, otherwise returns an empty promise.
  v8::Local<v8::Promise> StartRequest(
      v8::Local<v8::Context> context,
      const std::string& method,
      base::Value::List arguments_list,
      binding::AsyncResponseType async_type,
      v8::Local<v8::Function> callback,
      v8::Local<v8::Function> custom_callback,
      binding::ResultModifierFunction result_modifier);

  // Adds a pending request for the request handler to manage (and complete via
  // CompleteRequest). This is used by renderer-side implementations that
  // shouldn't be dispatched to the browser in the normal flow, but means other
  // classes don't have to worry about context invalidation. Returns the details
  // of the newly-added request.
  // Note: Unlike StartRequest(), this will not track user gesture state.
  RequestDetails AddPendingRequest(
      v8::Local<v8::Context> context,
      binding::AsyncResponseType async_type,
      v8::Local<v8::Function> callback,
      binding::ResultModifierFunction result_modifier);

  // Responds to the request with the given `request_id`, calling the callback
  // with the given `response` arguments.
  // Invalid ids are ignored.
  // Warning: This can run arbitrary JS code, so the `context` may be
  // invalidated after this!
  void CompleteRequest(int request_id,
                       const base::Value::List& response_list,
                       const std::string& error,
                       mojom::ExtraResponseDataPtr extra_data = nullptr);
  void CompleteRequest(int request_id,
                       const v8::LocalVector<v8::Value>& response,
                       const std::string& error);

  // Invalidates any requests that are associated with `context`.
  void InvalidateContext(v8::Local<v8::Context> context);

  void SetResponseValidator(std::unique_ptr<APIResponseValidator> validator);

  APILastError* last_error() { return &last_error_; }
  int last_sent_request_id() const { return last_sent_request_id_; }
  bool has_response_validator_for_testing() const {
    return response_validator_.get() != nullptr;
  }

  std::set<int> GetPendingRequestIdsForTesting() const;

 private:
  class ArgumentAdapter;
  class AsyncResultHandler;

  struct PendingRequest {
    PendingRequest(
        v8::Isolate* isolate,
        v8::Local<v8::Context> context,
        const std::string& method_name,
        std::unique_ptr<AsyncResultHandler> async_handler,
        std::unique_ptr<InteractionProvider::Token> user_gesture_token);

    ~PendingRequest();
    PendingRequest(PendingRequest&&);
    PendingRequest& operator=(PendingRequest&&);

    raw_ptr<v8::Isolate> isolate;
    v8::Global<v8::Context> context;
    std::string method_name;

    std::unique_ptr<AsyncResultHandler> async_handler;

    // Note: We can't use std::optional here for derived Token instances.
    std::unique_ptr<InteractionProvider::Token> user_gesture_token;
  };

  // Returns the next request ID to be used.
  int GetNextRequestId();

  // Creates and returns an AsyncResultHandler for a request if the request
  // requires an asynchronous response, otherwise returns null. Also populates
  // `promise_out` with the associated promise if this is a promise based
  // request.
  std::unique_ptr<AsyncResultHandler> GetAsyncResultHandler(
      v8::Local<v8::Context> context,
      binding::AsyncResponseType async_type,
      v8::Local<v8::Function> callback,
      v8::Local<v8::Function> custom_callback,
      binding::ResultModifierFunction result_modifier,
      v8::Local<v8::Promise>* promise_out);

  // Common implementation for completing a request.
  void CompleteRequestImpl(int request_id,
                           ArgumentAdapter arguments,
                           const std::string& error);

  // The next available request identifier.
  int next_request_id_ = 0;

  // The id of the last request we sent to the browser. This can be used as a
  // flag for whether or not a request was sent (if the last_sent_request_id_
  // changes).
  int last_sent_request_id_ = -1;

  // A map of all pending requests.
  std::map<int, PendingRequest> pending_requests_;

  SendRequestMethod send_request_;

  APILastError last_error_;

  // The exception handler for the bindings system; guaranteed to be valid
  // during this object's lifetime.
  const raw_ptr<ExceptionHandler> exception_handler_;

  // The response validator used to check the responses for resolved requests.
  // Null if response validation is disabled.
  std::unique_ptr<APIResponseValidator> response_validator_;

  // Outlives `this`.
  const raw_ptr<const InteractionProvider, DanglingUntriaged>
      interaction_provider_;
};

}  // namespace extensions

#endif  // EXTENSIONS_RENDERER_BINDINGS_API_REQUEST_HANDLER_H_