api_request_handler.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef EXTENSIONS_RENDERER_BINDINGS_API_REQUEST_HANDLER_H_
  5. #define EXTENSIONS_RENDERER_BINDINGS_API_REQUEST_HANDLER_H_
  6. #include <map>
  7. #include <memory>
  8. #include <set>
  9. #include "base/callback.h"
  10. #include "base/values.h"
  11. #include "extensions/renderer/bindings/api_binding_types.h"
  12. #include "extensions/renderer/bindings/api_last_error.h"
  13. #include "extensions/renderer/bindings/interaction_provider.h"
  14. #include "third_party/abseil-cpp/absl/types/optional.h"
  15. #include "v8/include/v8.h"
  16. namespace extensions {
  17. class APIResponseValidator;
  18. class ExceptionHandler;
  19. // A wrapper around a map for extension API calls. Contains all pending requests
  20. // and the associated context and callback. Designed to be used on a single
  21. // thread, but amongst multiple contexts.
  22. class APIRequestHandler {
  23. public:
  24. // TODO(devlin): We may want to coalesce this with the
  25. // ExtensionHostMsg_Request_Params IPC struct.
  26. struct Request {
  27. Request();
  28. Request(const Request&) = delete;
  29. Request& operator=(const Request&) = delete;
  30. ~Request();
  31. int request_id = -1;
  32. std::string method_name;
  33. bool has_async_response_handler = false;
  34. bool has_user_gesture = false;
  35. std::unique_ptr<base::Value> arguments_list;
  36. };
  37. // Details about a newly-added request to provide as a return to callers.
  38. // Contains the id of the request and if this is a promise based request, the
  39. // associated promise.
  40. struct RequestDetails {
  41. RequestDetails(int request_id, v8::Local<v8::Promise> promise);
  42. ~RequestDetails();
  43. RequestDetails(const RequestDetails& other);
  44. const int request_id;
  45. v8::Local<v8::Promise> promise;
  46. };
  47. using SendRequestMethod =
  48. base::RepeatingCallback<void(std::unique_ptr<Request>,
  49. v8::Local<v8::Context>)>;
  50. APIRequestHandler(SendRequestMethod send_request,
  51. APILastError last_error,
  52. ExceptionHandler* exception_handler,
  53. const InteractionProvider* interaction_provider);
  54. APIRequestHandler(const APIRequestHandler&) = delete;
  55. APIRequestHandler& operator=(const APIRequestHandler&) = delete;
  56. ~APIRequestHandler();
  57. // Begins the process of processing the request. If this is a promise based
  58. // request returns the associated promise, otherwise returns an empty promise.
  59. v8::Local<v8::Promise> StartRequest(
  60. v8::Local<v8::Context> context,
  61. const std::string& method,
  62. std::unique_ptr<base::Value> arguments_list,
  63. binding::AsyncResponseType async_type,
  64. v8::Local<v8::Function> callback,
  65. v8::Local<v8::Function> custom_callback,
  66. binding::ResultModifierFunction result_modifier);
  67. // Adds a pending request for the request handler to manage (and complete via
  68. // CompleteRequest). This is used by renderer-side implementations that
  69. // shouldn't be dispatched to the browser in the normal flow, but means other
  70. // classes don't have to worry about context invalidation. Returns the details
  71. // of the newly-added request.
  72. // Note: Unlike StartRequest(), this will not track user gesture state.
  73. RequestDetails AddPendingRequest(
  74. v8::Local<v8::Context> context,
  75. binding::AsyncResponseType async_type,
  76. v8::Local<v8::Function> callback,
  77. binding::ResultModifierFunction result_modifier);
  78. // Responds to the request with the given |request_id|, calling the callback
  79. // with the given |response| arguments.
  80. // Invalid ids are ignored.
  81. // Warning: This can run arbitrary JS code, so the |context| may be
  82. // invalidated after this!
  83. void CompleteRequest(int request_id,
  84. const base::Value::List& response_list,
  85. const std::string& error);
  86. void CompleteRequest(int request_id,
  87. const std::vector<v8::Local<v8::Value>>& response,
  88. const std::string& error);
  89. // Invalidates any requests that are associated with |context|.
  90. void InvalidateContext(v8::Local<v8::Context> context);
  91. void SetResponseValidator(std::unique_ptr<APIResponseValidator> validator);
  92. APILastError* last_error() { return &last_error_; }
  93. int last_sent_request_id() const { return last_sent_request_id_; }
  94. bool has_response_validator_for_testing() const {
  95. return response_validator_.get() != nullptr;
  96. }
  97. std::set<int> GetPendingRequestIdsForTesting() const;
  98. private:
  99. class ArgumentAdapter;
  100. class AsyncResultHandler;
  101. struct PendingRequest {
  102. PendingRequest(
  103. v8::Isolate* isolate,
  104. v8::Local<v8::Context> context,
  105. const std::string& method_name,
  106. std::unique_ptr<AsyncResultHandler> async_handler,
  107. std::unique_ptr<InteractionProvider::Token> user_gesture_token);
  108. ~PendingRequest();
  109. PendingRequest(PendingRequest&&);
  110. PendingRequest& operator=(PendingRequest&&);
  111. v8::Isolate* isolate;
  112. v8::Global<v8::Context> context;
  113. std::string method_name;
  114. std::unique_ptr<AsyncResultHandler> async_handler;
  115. // Note: We can't use absl::optional here for derived Token instances.
  116. std::unique_ptr<InteractionProvider::Token> user_gesture_token;
  117. };
  118. // Returns the next request ID to be used.
  119. int GetNextRequestId();
  120. // Creates and returns an AsyncResultHandler for a request if the request
  121. // requires an asynchronous response, otherwise returns null. Also populates
  122. // |promise_out| with the associated promise if this is a promise based
  123. // request.
  124. std::unique_ptr<AsyncResultHandler> GetAsyncResultHandler(
  125. v8::Local<v8::Context> context,
  126. binding::AsyncResponseType async_type,
  127. v8::Local<v8::Function> callback,
  128. v8::Local<v8::Function> custom_callback,
  129. binding::ResultModifierFunction result_modifier,
  130. v8::Local<v8::Promise>* promise_out);
  131. // Common implementation for completing a request.
  132. void CompleteRequestImpl(int request_id,
  133. const ArgumentAdapter& arguments,
  134. const std::string& error);
  135. // The next available request identifier.
  136. int next_request_id_ = 0;
  137. // The id of the last request we sent to the browser. This can be used as a
  138. // flag for whether or not a request was sent (if the last_sent_request_id_
  139. // changes).
  140. int last_sent_request_id_ = -1;
  141. // A map of all pending requests.
  142. std::map<int, PendingRequest> pending_requests_;
  143. SendRequestMethod send_request_;
  144. APILastError last_error_;
  145. // The exception handler for the bindings system; guaranteed to be valid
  146. // during this object's lifetime.
  147. ExceptionHandler* const exception_handler_;
  148. // The response validator used to check the responses for resolved requests.
  149. // Null if response validation is disabled.
  150. std::unique_ptr<APIResponseValidator> response_validator_;
  151. // Outlives |this|.
  152. const InteractionProvider* const interaction_provider_;
  153. };
  154. } // namespace extensions
  155. #endif // EXTENSIONS_RENDERER_BINDINGS_API_REQUEST_HANDLER_H_