api_signature.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  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. #include "extensions/renderer/bindings/api_signature.h"
  5. #include <algorithm>
  6. #include "base/containers/contains.h"
  7. #include "base/strings/string_util.h"
  8. #include "base/strings/stringprintf.h"
  9. #include "base/values.h"
  10. #include "content/public/renderer/v8_value_converter.h"
  11. #include "extensions/renderer/bindings/api_binding_util.h"
  12. #include "extensions/renderer/bindings/api_invocation_errors.h"
  13. #include "extensions/renderer/bindings/argument_spec.h"
  14. #include "gin/arguments.h"
  15. namespace extensions {
  16. namespace {
  17. // A list of API's which have a trailing function parameter that is not actually
  18. // meant to be treated like a traditional API success callback. For more details
  19. // see the comment where this is used in APISignature::CreateFromValues.
  20. constexpr const char* const kNonCallbackTrailingFunctionAPINames[] = {
  21. "test.listenForever",
  22. "test.listenOnce",
  23. "test.callbackPass",
  24. "test.callbackFail",
  25. "automation.addTreeChangeObserver",
  26. "automation.removeTreeChangeObserver",
  27. };
  28. std::vector<std::unique_ptr<ArgumentSpec>> ValueListToArgumentSpecs(
  29. const base::Value& specification_list,
  30. bool uses_returns_async) {
  31. std::vector<std::unique_ptr<ArgumentSpec>> signature;
  32. auto size = specification_list.GetList().size();
  33. // If the API specification uses the returns_async format we will be pushing a
  34. // callback onto the end of the argument spec list during the call to the ctor
  35. // later, so we make room for it now when we reserve the size.
  36. if (uses_returns_async)
  37. size++;
  38. signature.reserve(size);
  39. for (const auto& value : specification_list.GetList()) {
  40. CHECK(value.is_dict());
  41. signature.push_back(std::make_unique<ArgumentSpec>(value));
  42. }
  43. return signature;
  44. }
  45. std::unique_ptr<APISignature::ReturnsAsync> BuildReturnsAsyncFromValues(
  46. const base::Value& returns_async_spec,
  47. bool api_supports_promises) {
  48. auto returns_async = std::make_unique<APISignature::ReturnsAsync>();
  49. if (api_supports_promises)
  50. returns_async->promise_support = binding::APIPromiseSupport::kSupported;
  51. const base::Value* callback_optional =
  52. returns_async_spec.FindKeyOfType("optional", base::Value::Type::BOOLEAN);
  53. returns_async->optional = callback_optional && callback_optional->GetBool();
  54. // If response validation is enabled, parse the callback signature. Otherwise,
  55. // there's no reason to, so don't bother.
  56. if (binding::IsResponseValidationEnabled()) {
  57. const base::Value* callback_params =
  58. returns_async_spec.FindKeyOfType("parameters", base::Value::Type::LIST);
  59. if (callback_params) {
  60. returns_async->signature =
  61. ValueListToArgumentSpecs(*callback_params, false);
  62. }
  63. }
  64. return returns_async;
  65. }
  66. std::string ArgumentSpecsToString(
  67. const std::vector<std::unique_ptr<ArgumentSpec>>& argument_specs) {
  68. std::vector<std::string> pieces;
  69. pieces.reserve(argument_specs.size());
  70. const char* kOptionalPrefix = "optional ";
  71. for (const auto& spec : argument_specs) {
  72. pieces.push_back(
  73. base::StringPrintf("%s%s %s", spec->optional() ? kOptionalPrefix : "",
  74. spec->GetTypeName().c_str(), spec->name().c_str()));
  75. }
  76. return base::JoinString(pieces, ", ");
  77. }
  78. // A class to help with argument parsing. Note that this uses v8::Locals and
  79. // const&s because it's an implementation detail of the APISignature; this
  80. // should *only* be used directly on the stack!
  81. class ArgumentParser {
  82. public:
  83. ArgumentParser(v8::Local<v8::Context> context,
  84. const std::vector<std::unique_ptr<ArgumentSpec>>& signature,
  85. const std::vector<v8::Local<v8::Value>>& arguments,
  86. const APITypeReferenceMap& type_refs,
  87. PromisesAllowed promises_allowed)
  88. : context_(context),
  89. signature_(signature),
  90. provided_arguments_(arguments),
  91. type_refs_(type_refs),
  92. promises_allowed_(promises_allowed) {}
  93. ArgumentParser(const ArgumentParser&) = delete;
  94. ArgumentParser& operator=(const ArgumentParser&) = delete;
  95. protected:
  96. v8::Isolate* GetIsolate() { return context_->GetIsolate(); }
  97. // Common implementation for parsing arguments to either V8 values or
  98. // base::Values.
  99. bool ParseArgumentsImpl(bool signature_has_callback);
  100. std::string TakeError() { return std::move(error_); }
  101. binding::AsyncResponseType async_type() const { return async_type_; }
  102. private:
  103. // API methods can have multiple possible signatures. For instance, an API
  104. // method that takes (optional int, string) could be invoked with either
  105. // an int and string, or just a string. ResolveArguments() takes the
  106. // |provided| arguments and the |expected| signature, and populates |result|
  107. // with a normalized array of values such that each entry in |result| is
  108. // positionally correct with the signature. Omitted arguments will be
  109. // empty v8::Local<v8::Value> handles in the array.
  110. // |allow_omitted_final_argument| indicates that the final argument is allowed
  111. // to be omitted, even if it is not flagged as optional. This is used to allow
  112. // callers to omit the final "callback" argument if promises can be used
  113. // instead.
  114. // Returns true if the arguments were successfully resolved.
  115. // Note: This only checks arguments against their basic types, not other
  116. // values (like specific required properties or values).
  117. bool ResolveArguments(
  118. base::span<const v8::Local<v8::Value>> provided,
  119. base::span<const std::unique_ptr<ArgumentSpec>> expected,
  120. std::vector<v8::Local<v8::Value>>* result,
  121. size_t index,
  122. bool allow_omitted_final_argument);
  123. // Attempts to match the next argument to the given |spec|.
  124. // If the next argument does not match and |spec| is optional, uses a null
  125. // value.
  126. // Returns true on success.
  127. bool ParseArgument(const ArgumentSpec& spec, v8::Local<v8::Value> value);
  128. // Attempts to parse the callback from the given |spec|. Returns true on
  129. // success.
  130. bool ParseCallback(const ArgumentSpec& spec, v8::Local<v8::Value> value);
  131. // Adds a null value to the parsed arguments.
  132. virtual void AddNull() = 0;
  133. virtual void AddNullCallback() = 0;
  134. // Returns a base::Value to be populated during argument matching.
  135. virtual std::unique_ptr<base::Value>* GetBaseBuffer() = 0;
  136. // Returns a v8::Value to be populated during argument matching.
  137. virtual v8::Local<v8::Value>* GetV8Buffer() = 0;
  138. // Adds the argument parsed into the appropriate buffer.
  139. virtual void AddParsedArgument() = 0;
  140. // Adds the parsed callback.
  141. virtual void SetCallback(v8::Local<v8::Function> callback) = 0;
  142. v8::Local<v8::Context> context_;
  143. const std::vector<std::unique_ptr<ArgumentSpec>>& signature_;
  144. const std::vector<v8::Local<v8::Value>>& provided_arguments_;
  145. const APITypeReferenceMap& type_refs_;
  146. PromisesAllowed promises_allowed_;
  147. binding::AsyncResponseType async_type_ = binding::AsyncResponseType::kNone;
  148. std::string error_;
  149. // An error to pass while parsing arguments to avoid having to allocate a new
  150. // std::string on the stack multiple times.
  151. std::string parse_error_;
  152. };
  153. class V8ArgumentParser : public ArgumentParser {
  154. public:
  155. V8ArgumentParser(v8::Local<v8::Context> context,
  156. const std::vector<std::unique_ptr<ArgumentSpec>>& signature,
  157. const std::vector<v8::Local<v8::Value>>& arguments,
  158. const APITypeReferenceMap& type_refs,
  159. PromisesAllowed promises_allowed)
  160. : ArgumentParser(context,
  161. signature,
  162. arguments,
  163. type_refs,
  164. promises_allowed) {}
  165. V8ArgumentParser(const V8ArgumentParser&) = delete;
  166. V8ArgumentParser& operator=(const V8ArgumentParser&) = delete;
  167. APISignature::V8ParseResult ParseArguments(bool signature_has_callback);
  168. private:
  169. void AddNull() override { values_.push_back(v8::Null(GetIsolate())); }
  170. void AddNullCallback() override { values_.push_back(v8::Null(GetIsolate())); }
  171. std::unique_ptr<base::Value>* GetBaseBuffer() override { return nullptr; }
  172. v8::Local<v8::Value>* GetV8Buffer() override { return &last_arg_; }
  173. void AddParsedArgument() override {
  174. DCHECK(!last_arg_.IsEmpty());
  175. values_.push_back(last_arg_);
  176. last_arg_.Clear();
  177. }
  178. void SetCallback(v8::Local<v8::Function> callback) override {
  179. values_.push_back(callback);
  180. }
  181. v8::Local<v8::Value> last_arg_;
  182. std::vector<v8::Local<v8::Value>> values_;
  183. };
  184. class BaseValueArgumentParser : public ArgumentParser {
  185. public:
  186. BaseValueArgumentParser(
  187. v8::Local<v8::Context> context,
  188. const std::vector<std::unique_ptr<ArgumentSpec>>& signature,
  189. const std::vector<v8::Local<v8::Value>>& arguments,
  190. const APITypeReferenceMap& type_refs,
  191. PromisesAllowed promises_allowed)
  192. : ArgumentParser(context,
  193. signature,
  194. arguments,
  195. type_refs,
  196. promises_allowed) {}
  197. BaseValueArgumentParser(const BaseValueArgumentParser&) = delete;
  198. BaseValueArgumentParser& operator=(const BaseValueArgumentParser&) = delete;
  199. APISignature::JSONParseResult ParseArguments(bool signature_has_callback);
  200. private:
  201. void AddNull() override { list_value_.Append(base::Value()); }
  202. void AddNullCallback() override {
  203. // The base::Value conversion doesn't include the callback directly, so we
  204. // don't add a null parameter here.
  205. }
  206. std::unique_ptr<base::Value>* GetBaseBuffer() override { return &last_arg_; }
  207. v8::Local<v8::Value>* GetV8Buffer() override { return nullptr; }
  208. void AddParsedArgument() override {
  209. // The corresponding base::Value is expected to have been stored in
  210. // |last_arg_| already.
  211. DCHECK(last_arg_);
  212. list_value_.Append(base::Value::FromUniquePtrValue(std::move(last_arg_)));
  213. }
  214. void SetCallback(v8::Local<v8::Function> callback) override {
  215. callback_ = callback;
  216. }
  217. base::Value::List list_value_;
  218. std::unique_ptr<base::Value> last_arg_;
  219. v8::Local<v8::Function> callback_;
  220. };
  221. bool ArgumentParser::ParseArgumentsImpl(bool signature_has_callback) {
  222. if (provided_arguments_.size() > signature_.size()) {
  223. error_ = api_errors::NoMatchingSignature();
  224. return false;
  225. }
  226. // We allow the final argument to be omitted if the signature expects a
  227. // callback and promise-based APIs are supported. If the caller omits this
  228. // callback, the invocation is assumed to expect to a promise.
  229. bool allow_omitted_final_argument =
  230. signature_has_callback && promises_allowed_ == PromisesAllowed::kAllowed;
  231. std::vector<v8::Local<v8::Value>> resolved_arguments(signature_.size());
  232. if (!ResolveArguments(provided_arguments_, signature_, &resolved_arguments,
  233. 0u, allow_omitted_final_argument)) {
  234. error_ = api_errors::NoMatchingSignature();
  235. return false;
  236. }
  237. DCHECK_EQ(resolved_arguments.size(), signature_.size());
  238. size_t end_size =
  239. signature_has_callback ? signature_.size() - 1 : signature_.size();
  240. for (size_t i = 0; i < end_size; ++i) {
  241. if (!ParseArgument(*signature_[i], resolved_arguments[i]))
  242. return false;
  243. }
  244. if (signature_has_callback &&
  245. !ParseCallback(*signature_.back(), resolved_arguments.back())) {
  246. return false;
  247. }
  248. return true;
  249. }
  250. bool ArgumentParser::ResolveArguments(
  251. base::span<const v8::Local<v8::Value>> provided,
  252. base::span<const std::unique_ptr<ArgumentSpec>> expected,
  253. std::vector<v8::Local<v8::Value>>* result,
  254. size_t index,
  255. bool allow_omitted_final_argument) {
  256. // If the provided arguments and expected arguments are both empty, it means
  257. // we've successfully matched all provided arguments to the expected
  258. // signature.
  259. if (provided.empty() && expected.empty())
  260. return true;
  261. // If there are more provided arguments than expected arguments, there's no
  262. // possible signature that could match.
  263. if (provided.size() > expected.size())
  264. return false;
  265. DCHECK(!expected.empty());
  266. // If there are more provided arguments (and more expected arguments, as
  267. // guaranteed above), check if the next argument could match the next expected
  268. // argument.
  269. if (!provided.empty()) {
  270. // The argument could potentially match if it is either null or undefined
  271. // and an optional argument, or if it's the correct expected type.
  272. bool can_match = false;
  273. if (expected[0]->optional() && provided[0]->IsNullOrUndefined()) {
  274. can_match = true;
  275. // For null/undefined, just use an empty handle. It'll be normalized to
  276. // null in ParseArgument().
  277. (*result)[index] = v8::Local<v8::Value>();
  278. } else if (expected[0]->IsCorrectType(provided[0], type_refs_, &error_)) {
  279. can_match = true;
  280. (*result)[index] = provided[0];
  281. }
  282. // If the provided argument could potentially match the next expected
  283. // argument, assume it does, and try to match the remaining arguments.
  284. // This recursion is safe because it's bounded by the number of arguments
  285. // present in the signature. Additionally, though this is 2^n complexity,
  286. // <n> is bounded by the number of expected arguments, which is almost
  287. // always small. Further, it is only when parameters are optional, which is
  288. // also not the default.
  289. if (can_match &&
  290. ResolveArguments(provided.subspan(1), expected.subspan(1), result,
  291. index + 1, allow_omitted_final_argument)) {
  292. return true;
  293. }
  294. }
  295. // One of three cases happened:
  296. // - There are no more provided arguments.
  297. // - The next provided argument could not match the expected argument.
  298. // - The next provided argument could match the expected argument, but
  299. // subsequent arguments did not.
  300. // In all of these cases, if the expected argument was optional, assume it
  301. // was omitted, and try matching subsequent arguments.
  302. if (expected[0]->optional()) {
  303. // Assume the expected argument was omitted.
  304. (*result)[index] = v8::Local<v8::Value>();
  305. // See comments above for recursion notes.
  306. if (ResolveArguments(provided, expected.subspan(1), result, index + 1,
  307. allow_omitted_final_argument))
  308. return true;
  309. }
  310. // A required argument was not matched. There is only one case in which this
  311. // is allowed: a required callback has been left off of the provided arguments
  312. // when Promises are supported; if this is the case,
  313. // |allow_omitted_final_argument| is true and there should be no provided
  314. // arguments left.
  315. if (allow_omitted_final_argument && provided.size() == 0 &&
  316. expected.size() == 1) {
  317. (*result)[index] = v8::Local<v8::Value>();
  318. return true;
  319. }
  320. return false;
  321. }
  322. bool ArgumentParser::ParseArgument(const ArgumentSpec& spec,
  323. v8::Local<v8::Value> value) {
  324. if (value.IsEmpty()) {
  325. // ResolveArguments() should only allow empty values for optional arguments.
  326. DCHECK(spec.optional());
  327. AddNull();
  328. return true;
  329. }
  330. // ResolveArguments() should verify that all arguments are at least the
  331. // correct type.
  332. DCHECK(spec.IsCorrectType(value, type_refs_, &error_));
  333. if (!spec.ParseArgument(context_, value, type_refs_, GetBaseBuffer(),
  334. GetV8Buffer(), &parse_error_)) {
  335. error_ = api_errors::ArgumentError(spec.name(), parse_error_);
  336. return false;
  337. }
  338. AddParsedArgument();
  339. return true;
  340. }
  341. bool ArgumentParser::ParseCallback(const ArgumentSpec& spec,
  342. v8::Local<v8::Value> value) {
  343. if (value.IsEmpty()) {
  344. // Note: The null callback isn't exactly correct. See
  345. // https://crbug.com/1220910 for details.
  346. AddNullCallback();
  347. if (promises_allowed_ == PromisesAllowed::kAllowed) {
  348. // If the callback is omitted and promises are supported, assume the
  349. // async response type is a promise.
  350. async_type_ = binding::AsyncResponseType::kPromise;
  351. } else {
  352. // Otherwise, we should only get to this point if the callback argument is
  353. // optional.
  354. DCHECK(spec.optional());
  355. async_type_ = binding::AsyncResponseType::kNone;
  356. }
  357. return true;
  358. }
  359. // Note: callbacks are set through SetCallback() rather than through the
  360. // buffered argument.
  361. if (!spec.ParseArgument(context_, value, type_refs_, nullptr, nullptr,
  362. &parse_error_)) {
  363. error_ = api_errors::ArgumentError(spec.name(), parse_error_);
  364. return false;
  365. }
  366. SetCallback(value.As<v8::Function>());
  367. async_type_ = binding::AsyncResponseType::kCallback;
  368. return true;
  369. }
  370. APISignature::V8ParseResult V8ArgumentParser::ParseArguments(
  371. bool signature_has_callback) {
  372. APISignature::V8ParseResult result;
  373. if (!ParseArgumentsImpl(signature_has_callback)) {
  374. result.error = TakeError();
  375. } else {
  376. result.arguments = std::move(values_);
  377. result.async_type = async_type();
  378. }
  379. return result;
  380. }
  381. APISignature::JSONParseResult BaseValueArgumentParser::ParseArguments(
  382. bool signature_has_callback) {
  383. APISignature::JSONParseResult result;
  384. if (!ParseArgumentsImpl(signature_has_callback)) {
  385. result.error = TakeError();
  386. } else {
  387. result.arguments_list =
  388. std::make_unique<base::Value>(std::move(list_value_));
  389. result.callback = callback_;
  390. result.async_type = async_type();
  391. }
  392. return result;
  393. }
  394. // A helper method used to validate a signature for an internal caller (such as
  395. // a response to an API method or event arguments) to ensure it matches the
  396. // expected schema.
  397. bool ValidateSignatureForInternalCaller(
  398. v8::Local<v8::Context> context,
  399. const std::vector<v8::Local<v8::Value>>& arguments,
  400. const std::vector<std::unique_ptr<ArgumentSpec>>& expected,
  401. const APITypeReferenceMap& type_refs,
  402. std::string* error) {
  403. size_t expected_size = expected.size();
  404. size_t actual_size = arguments.size();
  405. if (actual_size > expected_size) {
  406. *error = api_errors::TooManyArguments();
  407. return false;
  408. }
  409. // Easy validation: arguments go in order, and must match the expected schema.
  410. // Anything less is failure.
  411. std::string parse_error;
  412. for (size_t i = 0; i < actual_size; ++i) {
  413. DCHECK(!arguments[i].IsEmpty());
  414. const ArgumentSpec& spec = *expected[i];
  415. if (arguments[i]->IsNullOrUndefined()) {
  416. if (!spec.optional()) {
  417. *error = api_errors::MissingRequiredArgument(spec.name().c_str());
  418. return false;
  419. }
  420. continue;
  421. }
  422. if (!spec.ParseArgument(context, arguments[i], type_refs, nullptr, nullptr,
  423. &parse_error)) {
  424. *error = api_errors::ArgumentError(spec.name(), parse_error);
  425. return false;
  426. }
  427. }
  428. // Responses may omit trailing optional parameters (which would then be
  429. // undefined for the caller).
  430. // NOTE(devlin): It might be nice to see if we could require all arguments to
  431. // be present, no matter what. For one, it avoids this loop, and it would also
  432. // unify what a "not found" value was (some APIs use undefined, some use
  433. // null).
  434. for (size_t i = actual_size; i < expected_size; ++i) {
  435. if (!expected[i]->optional()) {
  436. *error = api_errors::MissingRequiredArgument(expected[i]->name().c_str());
  437. return false;
  438. }
  439. }
  440. return true;
  441. }
  442. } // namespace
  443. APISignature::ReturnsAsync::ReturnsAsync() = default;
  444. APISignature::ReturnsAsync::~ReturnsAsync() = default;
  445. APISignature::V8ParseResult::V8ParseResult() = default;
  446. APISignature::V8ParseResult::~V8ParseResult() = default;
  447. APISignature::V8ParseResult::V8ParseResult(V8ParseResult&& other) = default;
  448. APISignature::V8ParseResult& APISignature::V8ParseResult::operator=(
  449. V8ParseResult&& other) = default;
  450. APISignature::JSONParseResult::JSONParseResult() = default;
  451. APISignature::JSONParseResult::~JSONParseResult() = default;
  452. APISignature::JSONParseResult::JSONParseResult(JSONParseResult&& other) =
  453. default;
  454. APISignature::JSONParseResult& APISignature::JSONParseResult::operator=(
  455. JSONParseResult&& other) = default;
  456. APISignature::APISignature(
  457. std::vector<std::unique_ptr<ArgumentSpec>> signature,
  458. std::unique_ptr<APISignature::ReturnsAsync> returns_async,
  459. BindingAccessChecker* access_checker)
  460. : signature_(std::move(signature)),
  461. returns_async_(std::move(returns_async)),
  462. access_checker_(access_checker) {
  463. if (returns_async_) {
  464. // TODO(tjudkins): Argument parsing during an API call currently expects any
  465. // potential callback to be part of the list of expected arguments, rather
  466. // than represented separately in the ReturnsAsync struct. It would be nice
  467. // to update that code to know about the ReturnsAsync struct instead.
  468. // That would also avoid the slightly-inefficient "dance" we have for APIs
  469. // that don't specify returns_async today, since we currently pop the
  470. // callback in CreateFromValues() and then re-add it here.
  471. auto callback = std::make_unique<ArgumentSpec>(ArgumentType::FUNCTION);
  472. callback->set_optional(returns_async_->optional);
  473. callback->set_name("callback");
  474. signature_.push_back(std::move(callback));
  475. if (returns_async_->promise_support ==
  476. binding::APIPromiseSupport::kSupported) {
  477. DCHECK(access_checker_)
  478. << "If an API supports promises, it needs to supply a "
  479. "BindingAccessChecker to be able to check if calling contexts are "
  480. "allowed to use promises";
  481. }
  482. }
  483. }
  484. APISignature::~APISignature() {}
  485. // static
  486. std::unique_ptr<APISignature> APISignature::CreateFromValues(
  487. const base::Value& spec_list,
  488. const base::Value* returns_async,
  489. BindingAccessChecker* access_checker,
  490. const std::string& api_name,
  491. bool is_event_signature) {
  492. bool uses_returns_async = returns_async != nullptr;
  493. auto argument_specs = ValueListToArgumentSpecs(spec_list, uses_returns_async);
  494. // Asynchronous returns for an API are either defined in the returns_async
  495. // part of the specification or as a trailing function argument.
  496. // TODO(crbug.com/1288583): There are a handful of APIs which have a trailing
  497. // function argument that is not a traditional callback. Once we have moved
  498. // all the asynchronous API schemas to use the returns_async format it will be
  499. // clear when this is the case, but for now we keep a list of the names of
  500. // these APIs to ensure we are handling them correctly.
  501. // This is irrelevant for event signatures.
  502. const base::Value* returns_async_spec = returns_async;
  503. if (!is_event_signature && !argument_specs.empty() &&
  504. argument_specs.back()->type() == ArgumentType::FUNCTION &&
  505. !base::Contains(kNonCallbackTrailingFunctionAPINames, api_name)) {
  506. DCHECK(!returns_async_spec);
  507. returns_async_spec = &spec_list.GetList().back();
  508. argument_specs.pop_back();
  509. }
  510. std::unique_ptr<APISignature::ReturnsAsync> returns_async_struct;
  511. if (returns_async_spec) {
  512. bool api_supports_promises = returns_async != nullptr;
  513. returns_async_struct =
  514. BuildReturnsAsyncFromValues(*returns_async_spec, api_supports_promises);
  515. }
  516. return std::make_unique<APISignature>(std::move(argument_specs),
  517. std::move(returns_async_struct),
  518. access_checker);
  519. }
  520. APISignature::V8ParseResult APISignature::ParseArgumentsToV8(
  521. v8::Local<v8::Context> context,
  522. const std::vector<v8::Local<v8::Value>>& arguments,
  523. const APITypeReferenceMap& type_refs) const {
  524. PromisesAllowed promises_allowed = CheckPromisesAllowed(context);
  525. return V8ArgumentParser(context, signature_, arguments, type_refs,
  526. promises_allowed)
  527. .ParseArguments(has_async_return());
  528. }
  529. APISignature::JSONParseResult APISignature::ParseArgumentsToJSON(
  530. v8::Local<v8::Context> context,
  531. const std::vector<v8::Local<v8::Value>>& arguments,
  532. const APITypeReferenceMap& type_refs) const {
  533. PromisesAllowed promises_allowed = CheckPromisesAllowed(context);
  534. return BaseValueArgumentParser(context, signature_, arguments, type_refs,
  535. promises_allowed)
  536. .ParseArguments(has_async_return());
  537. }
  538. APISignature::JSONParseResult APISignature::ConvertArgumentsIgnoringSchema(
  539. v8::Local<v8::Context> context,
  540. const std::vector<v8::Local<v8::Value>>& arguments) const {
  541. JSONParseResult result;
  542. size_t size = arguments.size();
  543. // TODO(devlin): This is what the current bindings do, but it's quite terribly
  544. // incorrect. We only hit this flow when an API method has a hook to update
  545. // the arguments post-validation, and in some cases, the arguments returned by
  546. // that hook do *not* match the signature of the API method (e.g.
  547. // fileSystem.getDisplayPath); see also note in api_bindings.cc for why this
  548. // is bad. But then here, we *rely* on the signature to determine whether or
  549. // not the last parameter is a callback, even though the hooks may not return
  550. // the arguments in the signature. This is very broken.
  551. if (has_async_return()) {
  552. CHECK(!arguments.empty());
  553. v8::Local<v8::Value> value = arguments.back();
  554. --size;
  555. // Bindings should ensure that the value here is appropriate, but see the
  556. // comment above for limitations.
  557. DCHECK(value->IsFunction() || value->IsUndefined() || value->IsNull());
  558. if (value->IsFunction()) {
  559. result.callback = value.As<v8::Function>();
  560. result.async_type = binding::AsyncResponseType::kCallback;
  561. } else if ((value->IsNull() || value->IsUndefined()) &&
  562. CheckPromisesAllowed(context) == PromisesAllowed::kAllowed) {
  563. result.async_type = binding::AsyncResponseType::kPromise;
  564. }
  565. }
  566. base::Value::List json;
  567. json.reserve(size);
  568. std::unique_ptr<content::V8ValueConverter> converter =
  569. content::V8ValueConverter::Create();
  570. converter->SetFunctionAllowed(true);
  571. converter->SetConvertNegativeZeroToInt(true);
  572. converter->SetStripNullFromObjects(true);
  573. for (size_t i = 0; i < size; ++i) {
  574. std::unique_ptr<base::Value> converted =
  575. converter->FromV8Value(arguments[i], context);
  576. if (!converted) {
  577. // JSON.stringify inserts non-serializable values as "null" when
  578. // handling arrays, and this behavior is emulated in V8ValueConverter for
  579. // array values. Since JS bindings parsed arguments from a single array,
  580. // it accepted unserializable argument entries (which were converted to
  581. // null). Duplicate that behavior here.
  582. converted = std::make_unique<base::Value>();
  583. }
  584. json.Append(base::Value::FromUniquePtrValue(std::move(converted)));
  585. }
  586. result.arguments_list = std::make_unique<base::Value>(std::move(json));
  587. return result;
  588. }
  589. bool APISignature::ValidateResponse(
  590. v8::Local<v8::Context> context,
  591. const std::vector<v8::Local<v8::Value>>& arguments,
  592. const APITypeReferenceMap& type_refs,
  593. std::string* error) const {
  594. DCHECK(returns_async_);
  595. DCHECK(returns_async_->signature);
  596. return ValidateSignatureForInternalCaller(
  597. context, arguments, *returns_async_->signature, type_refs, error);
  598. }
  599. bool APISignature::ValidateCall(
  600. v8::Local<v8::Context> context,
  601. const std::vector<v8::Local<v8::Value>>& arguments,
  602. const APITypeReferenceMap& type_refs,
  603. std::string* error) const {
  604. return ValidateSignatureForInternalCaller(context, arguments, signature_,
  605. type_refs, error);
  606. }
  607. std::string APISignature::GetExpectedSignature() const {
  608. if (!expected_signature_.empty() || signature_.empty())
  609. return expected_signature_;
  610. expected_signature_ = ArgumentSpecsToString(signature_);
  611. return expected_signature_;
  612. }
  613. PromisesAllowed APISignature::CheckPromisesAllowed(
  614. v8::Local<v8::Context> context) const {
  615. // Promises are only allowed if both the API supports promises and the context
  616. // is allowed to use promises.
  617. if (returns_async_ && returns_async_->promise_support ==
  618. binding::APIPromiseSupport::kSupported) {
  619. DCHECK(access_checker_);
  620. if (access_checker_->HasPromiseAccess(context))
  621. return PromisesAllowed::kAllowed;
  622. }
  623. return PromisesAllowed::kDisallowed;
  624. }
  625. } // namespace extensions