123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- // 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_BINDINGS_API_REQUEST_HANDLER_H_
- #define EXTENSIONS_RENDERER_BINDINGS_API_REQUEST_HANDLER_H_
- #include <map>
- #include <memory>
- #include <set>
- #include "base/callback.h"
- #include "base/values.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 "third_party/abseil-cpp/absl/types/optional.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;
- std::unique_ptr<base::Value> 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,
- std::unique_ptr<base::Value> 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);
- void CompleteRequest(int request_id,
- const std::vector<v8::Local<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&&);
- v8::Isolate* isolate;
- v8::Global<v8::Context> context;
- std::string method_name;
- std::unique_ptr<AsyncResultHandler> async_handler;
- // Note: We can't use absl::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,
- const 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.
- ExceptionHandler* const 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 InteractionProvider* const interaction_provider_;
- };
- } // namespace extensions
- #endif // EXTENSIONS_RENDERER_BINDINGS_API_REQUEST_HANDLER_H_
|