api_signature_unittest.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. // Copyright 2017 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 "base/values.h"
  6. #include "extensions/renderer/bindings/api_binding_test.h"
  7. #include "extensions/renderer/bindings/api_binding_test_util.h"
  8. #include "extensions/renderer/bindings/api_invocation_errors.h"
  9. #include "extensions/renderer/bindings/api_type_reference_map.h"
  10. #include "extensions/renderer/bindings/argument_spec.h"
  11. #include "extensions/renderer/bindings/argument_spec_builder.h"
  12. #include "extensions/renderer/bindings/binding_access_checker.h"
  13. #include "extensions/renderer/bindings/returns_async_builder.h"
  14. #include "gin/converter.h"
  15. #include "gin/dictionary.h"
  16. namespace extensions {
  17. using api_errors::ArgumentError;
  18. using api_errors::InvalidType;
  19. using api_errors::kTypeBoolean;
  20. using api_errors::kTypeInteger;
  21. using api_errors::kTypeString;
  22. using api_errors::NoMatchingSignature;
  23. namespace {
  24. using SpecVector = std::vector<std::unique_ptr<ArgumentSpec>>;
  25. using ReturnsAsync = APISignature::ReturnsAsync;
  26. std::unique_ptr<APISignature> OneString() {
  27. SpecVector specs;
  28. specs.push_back(ArgumentSpecBuilder(ArgumentType::STRING, "string").Build());
  29. return std::make_unique<APISignature>(
  30. std::move(specs), nullptr /*returns_async*/, nullptr /*access_checker*/);
  31. }
  32. SpecVector StringAndIntSpec() {
  33. SpecVector specs;
  34. specs.push_back(ArgumentSpecBuilder(ArgumentType::STRING, "string").Build());
  35. specs.push_back(ArgumentSpecBuilder(ArgumentType::INTEGER, "int").Build());
  36. return specs;
  37. }
  38. std::unique_ptr<APISignature> StringAndInt() {
  39. return std::make_unique<APISignature>(StringAndIntSpec(),
  40. nullptr /*returns_async*/,
  41. nullptr /*access_checker*/);
  42. }
  43. SpecVector StringOptionalIntAndBoolSpec() {
  44. SpecVector specs;
  45. specs.push_back(ArgumentSpecBuilder(ArgumentType::STRING, "string").Build());
  46. specs.push_back(
  47. ArgumentSpecBuilder(ArgumentType::INTEGER, "int").MakeOptional().Build());
  48. specs.push_back(ArgumentSpecBuilder(ArgumentType::BOOLEAN, "bool").Build());
  49. return specs;
  50. }
  51. std::unique_ptr<APISignature> StringOptionalIntAndBool() {
  52. return std::make_unique<APISignature>(StringOptionalIntAndBoolSpec(),
  53. nullptr /*returns_async*/,
  54. nullptr /*access_checker*/);
  55. }
  56. SpecVector StringAndOptionalIntSpec() {
  57. SpecVector specs;
  58. specs.push_back(ArgumentSpecBuilder(ArgumentType::STRING, "string").Build());
  59. specs.push_back(
  60. ArgumentSpecBuilder(ArgumentType::INTEGER, "int").MakeOptional().Build());
  61. return specs;
  62. }
  63. std::unique_ptr<APISignature> OneObject() {
  64. SpecVector specs;
  65. specs.push_back(
  66. ArgumentSpecBuilder(ArgumentType::OBJECT, "obj")
  67. .AddProperty("prop1",
  68. ArgumentSpecBuilder(ArgumentType::STRING).Build())
  69. .AddProperty(
  70. "prop2",
  71. ArgumentSpecBuilder(ArgumentType::STRING).MakeOptional().Build())
  72. .Build());
  73. return std::make_unique<APISignature>(
  74. std::move(specs), nullptr /*returns_async*/, nullptr /*access_checker*/);
  75. }
  76. std::unique_ptr<APISignature> NoArgs() {
  77. return std::make_unique<APISignature>(SpecVector(), nullptr /*returns_async*/,
  78. nullptr /*access_checker*/);
  79. }
  80. std::unique_ptr<APISignature> IntAndCallback() {
  81. SpecVector specs;
  82. specs.push_back(ArgumentSpecBuilder(ArgumentType::INTEGER, "int").Build());
  83. return std::make_unique<APISignature>(std::move(specs),
  84. ReturnsAsyncBuilder().Build(), nullptr);
  85. }
  86. std::unique_ptr<APISignature> IntAndOptionalCallback() {
  87. SpecVector specs;
  88. specs.push_back(ArgumentSpecBuilder(ArgumentType::INTEGER, "int").Build());
  89. return std::make_unique<APISignature>(
  90. std::move(specs), ReturnsAsyncBuilder().MakeOptional().Build(), nullptr);
  91. }
  92. std::unique_ptr<APISignature> OptionalIntAndCallback() {
  93. SpecVector specs;
  94. specs.push_back(
  95. ArgumentSpecBuilder(ArgumentType::INTEGER, "int").MakeOptional().Build());
  96. return std::make_unique<APISignature>(std::move(specs),
  97. ReturnsAsyncBuilder().Build(), nullptr);
  98. }
  99. std::unique_ptr<APISignature> OptionalCallback() {
  100. return std::make_unique<APISignature>(
  101. SpecVector(), ReturnsAsyncBuilder().MakeOptional().Build(), nullptr);
  102. }
  103. std::unique_ptr<APISignature> IntAnyOptionalObjectOptionalCallback() {
  104. SpecVector specs;
  105. specs.push_back(ArgumentSpecBuilder(ArgumentType::INTEGER, "int").Build());
  106. specs.push_back(ArgumentSpecBuilder(ArgumentType::ANY, "any").Build());
  107. specs.push_back(
  108. ArgumentSpecBuilder(ArgumentType::OBJECT, "obj")
  109. .AddProperty(
  110. "prop",
  111. ArgumentSpecBuilder(ArgumentType::INTEGER).MakeOptional().Build())
  112. .MakeOptional()
  113. .Build());
  114. return std::make_unique<APISignature>(
  115. std::move(specs), ReturnsAsyncBuilder().MakeOptional().Build(), nullptr);
  116. }
  117. std::unique_ptr<APISignature> RefObj() {
  118. SpecVector specs;
  119. specs.push_back(
  120. ArgumentSpecBuilder(ArgumentType::REF, "obj").SetRef("refObj").Build());
  121. return std::make_unique<APISignature>(
  122. std::move(specs), nullptr /*returns_async*/, nullptr /*access_checker*/);
  123. }
  124. std::unique_ptr<APISignature> RefEnum() {
  125. SpecVector specs;
  126. specs.push_back(
  127. ArgumentSpecBuilder(ArgumentType::REF, "enum").SetRef("refEnum").Build());
  128. return std::make_unique<APISignature>(
  129. std::move(specs), nullptr /*returns_async*/, nullptr /*access_checker*/);
  130. }
  131. std::unique_ptr<APISignature> OptionalObjectAndOptionalCallback() {
  132. SpecVector specs;
  133. specs.push_back(
  134. ArgumentSpecBuilder(ArgumentType::OBJECT, "obj")
  135. .AddProperty(
  136. "prop1",
  137. ArgumentSpecBuilder(ArgumentType::INTEGER).MakeOptional().Build())
  138. .MakeOptional()
  139. .Build());
  140. return std::make_unique<APISignature>(
  141. std::move(specs), ReturnsAsyncBuilder().MakeOptional().Build(),
  142. nullptr /*access_checker*/);
  143. }
  144. std::unique_ptr<APISignature> OptionalIntAndNumber() {
  145. SpecVector specs;
  146. specs.push_back(
  147. ArgumentSpecBuilder(ArgumentType::INTEGER, "int").MakeOptional().Build());
  148. specs.push_back(ArgumentSpecBuilder(ArgumentType::DOUBLE, "num").Build());
  149. return std::make_unique<APISignature>(
  150. std::move(specs), nullptr /*returns_async*/, nullptr /*access_checker*/);
  151. }
  152. std::unique_ptr<APISignature> OptionalIntAndInt() {
  153. SpecVector specs;
  154. specs.push_back(
  155. ArgumentSpecBuilder(ArgumentType::INTEGER, "int").MakeOptional().Build());
  156. specs.push_back(ArgumentSpecBuilder(ArgumentType::INTEGER, "int2").Build());
  157. return std::make_unique<APISignature>(
  158. std::move(specs), nullptr /*returns_async*/, nullptr /*access_checker*/);
  159. }
  160. std::vector<v8::Local<v8::Value>> StringToV8Vector(
  161. v8::Local<v8::Context> context,
  162. const char* args) {
  163. v8::Local<v8::Value> v8_args = V8ValueFromScriptSource(context, args);
  164. EXPECT_FALSE(v8_args.IsEmpty());
  165. EXPECT_TRUE(v8_args->IsArray());
  166. std::vector<v8::Local<v8::Value>> vector_args;
  167. EXPECT_TRUE(gin::ConvertFromV8(context->GetIsolate(), v8_args, &vector_args));
  168. return vector_args;
  169. }
  170. } // namespace
  171. class APISignatureTest : public APIBindingTest {
  172. public:
  173. APISignatureTest()
  174. : type_refs_(APITypeReferenceMap::InitializeTypeCallback()) {}
  175. APISignatureTest(const APISignatureTest&) = delete;
  176. APISignatureTest& operator=(const APISignatureTest&) = delete;
  177. ~APISignatureTest() override = default;
  178. void SetUp() override {
  179. APIBindingTest::SetUp();
  180. std::unique_ptr<ArgumentSpec> ref_obj_spec =
  181. ArgumentSpecBuilder(ArgumentType::OBJECT)
  182. .AddProperty("prop1",
  183. ArgumentSpecBuilder(ArgumentType::STRING).Build())
  184. .AddProperty("prop2", ArgumentSpecBuilder(ArgumentType::INTEGER)
  185. .MakeOptional()
  186. .Build())
  187. .Build();
  188. type_refs_.AddSpec("refObj", std::move(ref_obj_spec));
  189. type_refs_.AddSpec("refEnum", ArgumentSpecBuilder(ArgumentType::STRING)
  190. .SetEnums({"alpha", "beta"})
  191. .Build());
  192. }
  193. void ExpectPass(const APISignature& signature,
  194. base::StringPiece arg_values,
  195. base::StringPiece expected_parsed_args,
  196. binding::AsyncResponseType expected_response_type) {
  197. RunTest(signature, arg_values, expected_parsed_args, expected_response_type,
  198. true, std::string());
  199. }
  200. void ExpectFailure(const APISignature& signature,
  201. base::StringPiece arg_values,
  202. const std::string& expected_error) {
  203. RunTest(signature, arg_values, base::StringPiece(),
  204. binding::AsyncResponseType::kNone, false, expected_error);
  205. }
  206. void ExpectResponsePass(const APISignature& signature,
  207. base::StringPiece arg_values) {
  208. RunResponseTest(signature, arg_values, absl::nullopt);
  209. }
  210. void ExpectResponseFailure(const APISignature& signature,
  211. base::StringPiece arg_values,
  212. const std::string& expected_error) {
  213. RunResponseTest(signature, arg_values, expected_error);
  214. }
  215. const APITypeReferenceMap& type_refs() const { return type_refs_; }
  216. private:
  217. void RunTest(const APISignature& signature,
  218. base::StringPiece arg_values,
  219. base::StringPiece expected_parsed_args,
  220. binding::AsyncResponseType expected_response_type,
  221. bool should_succeed,
  222. const std::string& expected_error) {
  223. SCOPED_TRACE(arg_values);
  224. v8::Local<v8::Context> context = MainContext();
  225. v8::Local<v8::Value> v8_args = V8ValueFromScriptSource(context, arg_values);
  226. ASSERT_FALSE(v8_args.IsEmpty());
  227. ASSERT_TRUE(v8_args->IsArray());
  228. std::vector<v8::Local<v8::Value>> vector_args;
  229. ASSERT_TRUE(gin::ConvertFromV8(isolate(), v8_args, &vector_args));
  230. APISignature::JSONParseResult parse_result =
  231. signature.ParseArgumentsToJSON(context, vector_args, type_refs_);
  232. ASSERT_EQ(should_succeed, !!parse_result.arguments_list);
  233. ASSERT_NE(should_succeed, parse_result.error.has_value());
  234. EXPECT_EQ(expected_response_type, parse_result.async_type);
  235. EXPECT_EQ(expected_response_type == binding::AsyncResponseType::kCallback,
  236. !parse_result.callback.IsEmpty());
  237. if (should_succeed) {
  238. EXPECT_EQ(ReplaceSingleQuotes(expected_parsed_args),
  239. ValueToString(*parse_result.arguments_list));
  240. } else {
  241. EXPECT_EQ(expected_error, *parse_result.error);
  242. }
  243. }
  244. void RunResponseTest(const APISignature& signature,
  245. base::StringPiece arg_values,
  246. absl::optional<std::string> expected_error) {
  247. SCOPED_TRACE(arg_values);
  248. v8::Local<v8::Context> context = MainContext();
  249. v8::Local<v8::Value> v8_args = V8ValueFromScriptSource(context, arg_values);
  250. ASSERT_FALSE(v8_args.IsEmpty());
  251. ASSERT_TRUE(v8_args->IsArray());
  252. std::vector<v8::Local<v8::Value>> vector_args;
  253. ASSERT_TRUE(gin::ConvertFromV8(isolate(), v8_args, &vector_args));
  254. std::string error;
  255. bool should_succeed = !expected_error;
  256. bool success =
  257. signature.ValidateResponse(context, vector_args, type_refs_, &error);
  258. EXPECT_EQ(should_succeed, success) << error;
  259. ASSERT_EQ(should_succeed, error.empty());
  260. if (!should_succeed)
  261. EXPECT_EQ(*expected_error, error);
  262. }
  263. APITypeReferenceMap type_refs_;
  264. };
  265. TEST_F(APISignatureTest, BasicSignatureParsing) {
  266. v8::HandleScope handle_scope(isolate());
  267. {
  268. SCOPED_TRACE("OneString");
  269. auto signature = OneString();
  270. ExpectPass(*signature, "['foo']", "['foo']",
  271. binding::AsyncResponseType::kNone);
  272. ExpectPass(*signature, "['']", "['']", binding::AsyncResponseType::kNone);
  273. ExpectFailure(*signature, "[1]", NoMatchingSignature());
  274. ExpectFailure(*signature, "[]", NoMatchingSignature());
  275. ExpectFailure(*signature, "[{}]", NoMatchingSignature());
  276. ExpectFailure(*signature, "['foo', 'bar']", NoMatchingSignature());
  277. }
  278. {
  279. SCOPED_TRACE("StringAndInt");
  280. auto signature = StringAndInt();
  281. ExpectPass(*signature, "['foo', 42]", "['foo',42]",
  282. binding::AsyncResponseType::kNone);
  283. ExpectPass(*signature, "['foo', -1]", "['foo',-1]",
  284. binding::AsyncResponseType::kNone);
  285. ExpectFailure(*signature, "[1]", NoMatchingSignature());
  286. ExpectFailure(*signature, "['foo'];", NoMatchingSignature());
  287. ExpectFailure(*signature, "[1, 'foo']", NoMatchingSignature());
  288. ExpectFailure(*signature, "['foo', 'foo']", NoMatchingSignature());
  289. ExpectFailure(*signature, "['foo', '1']", NoMatchingSignature());
  290. ExpectFailure(*signature, "['foo', 2.3]", NoMatchingSignature());
  291. }
  292. {
  293. SCOPED_TRACE("StringOptionalIntAndBool");
  294. auto signature = StringOptionalIntAndBool();
  295. ExpectPass(*signature, "['foo', 42, true]", "['foo',42,true]",
  296. binding::AsyncResponseType::kNone);
  297. ExpectPass(*signature, "['foo', true]", "['foo',null,true]",
  298. binding::AsyncResponseType::kNone);
  299. ExpectFailure(*signature, "['foo', 'bar', true]", NoMatchingSignature());
  300. }
  301. {
  302. SCOPED_TRACE("OneObject");
  303. auto signature = OneObject();
  304. ExpectPass(*signature, "[{prop1: 'foo'}]", "[{'prop1':'foo'}]",
  305. binding::AsyncResponseType::kNone);
  306. ExpectFailure(*signature,
  307. "[{ get prop1() { throw new Error('Badness'); } }]",
  308. ArgumentError("obj", api_errors::ScriptThrewError()));
  309. }
  310. {
  311. SCOPED_TRACE("NoArgs");
  312. auto signature = NoArgs();
  313. ExpectPass(*signature, "[]", "[]", binding::AsyncResponseType::kNone);
  314. ExpectFailure(*signature, "[0]", NoMatchingSignature());
  315. ExpectFailure(*signature, "['']", NoMatchingSignature());
  316. ExpectFailure(*signature, "[null]", NoMatchingSignature());
  317. ExpectFailure(*signature, "[undefined]", NoMatchingSignature());
  318. }
  319. {
  320. SCOPED_TRACE("IntAndCallback");
  321. auto signature = IntAndCallback();
  322. ExpectPass(*signature, "[1, function() {}]", "[1]",
  323. binding::AsyncResponseType::kCallback);
  324. ExpectFailure(*signature, "[function() {}]", NoMatchingSignature());
  325. ExpectFailure(*signature, "[1]", NoMatchingSignature());
  326. }
  327. {
  328. SCOPED_TRACE("OptionalIntAndCallback");
  329. auto signature = OptionalIntAndCallback();
  330. ExpectPass(*signature, "[1, function() {}]", "[1]",
  331. binding::AsyncResponseType::kCallback);
  332. ExpectPass(*signature, "[function() {}]", "[null]",
  333. binding::AsyncResponseType::kCallback);
  334. ExpectFailure(*signature, "[1]", NoMatchingSignature());
  335. }
  336. {
  337. SCOPED_TRACE("OptionalCallback");
  338. auto signature = OptionalCallback();
  339. ExpectPass(*signature, "[function() {}]", "[]",
  340. binding::AsyncResponseType::kCallback);
  341. ExpectPass(*signature, "[]", "[]", binding::AsyncResponseType::kNone);
  342. ExpectPass(*signature, "[undefined]", "[]",
  343. binding::AsyncResponseType::kNone);
  344. ExpectFailure(*signature, "[0]", NoMatchingSignature());
  345. }
  346. {
  347. SCOPED_TRACE("IntAnyOptionalObjectOptionalCallback");
  348. auto signature = IntAnyOptionalObjectOptionalCallback();
  349. ExpectPass(*signature, "[4, {foo: 'bar'}, function() {}]",
  350. "[4,{'foo':'bar'},null]", binding::AsyncResponseType::kCallback);
  351. ExpectPass(*signature, "[4, {foo: 'bar'}]", "[4,{'foo':'bar'},null]",
  352. binding::AsyncResponseType::kNone);
  353. ExpectPass(*signature, "[4, {foo: 'bar'}, {}]", "[4,{'foo':'bar'},{}]",
  354. binding::AsyncResponseType::kNone);
  355. ExpectFailure(*signature, "[4, function() {}]",
  356. ArgumentError("any", api_errors::UnserializableValue()));
  357. ExpectFailure(*signature, "[4]", NoMatchingSignature());
  358. }
  359. {
  360. SCOPED_TRACE("OptionalObjectAndCOptionalallback");
  361. auto signature = OptionalObjectAndOptionalCallback();
  362. ExpectPass(*signature, "[{prop1: 1}]", "[{'prop1':1}]",
  363. binding::AsyncResponseType::kNone);
  364. ExpectPass(*signature, "[]", "[null]", binding::AsyncResponseType::kNone);
  365. ExpectPass(*signature, "[null]", "[null]",
  366. binding::AsyncResponseType::kNone);
  367. ExpectFailure(*signature, "[{prop1: 'str'}]",
  368. ArgumentError("obj", api_errors::PropertyError(
  369. "prop1", InvalidType(kTypeInteger,
  370. kTypeString))));
  371. ExpectFailure(*signature, "[{prop1: 'str'}, function() {}]",
  372. ArgumentError("obj", api_errors::PropertyError(
  373. "prop1", InvalidType(kTypeInteger,
  374. kTypeString))));
  375. }
  376. {
  377. SCOPED_TRACE("OptionalIntAndNumber");
  378. auto signature = OptionalIntAndNumber();
  379. ExpectPass(*signature, "[1.0, 1.0]", "[1,1.0]",
  380. binding::AsyncResponseType::kNone);
  381. ExpectPass(*signature, "[1, 1]", "[1,1.0]",
  382. binding::AsyncResponseType::kNone);
  383. ExpectPass(*signature, "[1.0]", "[null,1.0]",
  384. binding::AsyncResponseType::kNone);
  385. ExpectPass(*signature, "[1]", "[null,1.0]",
  386. binding::AsyncResponseType::kNone);
  387. ExpectFailure(*signature, "[1.0, null]", NoMatchingSignature());
  388. ExpectFailure(*signature, "[1, null]", NoMatchingSignature());
  389. }
  390. {
  391. SCOPED_TRACE("OptionalIntAndInt");
  392. auto signature = OptionalIntAndInt();
  393. ExpectPass(*signature, "[1.0, 1.0]", "[1,1]",
  394. binding::AsyncResponseType::kNone);
  395. ExpectPass(*signature, "[1, 1]", "[1,1]",
  396. binding::AsyncResponseType::kNone);
  397. ExpectPass(*signature, "[1.0]", "[null,1]",
  398. binding::AsyncResponseType::kNone);
  399. ExpectPass(*signature, "[1]", "[null,1]",
  400. binding::AsyncResponseType::kNone);
  401. ExpectFailure(*signature, "[1.0, null]", NoMatchingSignature());
  402. ExpectFailure(*signature, "[1, null]", NoMatchingSignature());
  403. }
  404. }
  405. TEST_F(APISignatureTest, TypeRefsTest) {
  406. v8::HandleScope handle_scope(isolate());
  407. {
  408. auto signature = RefObj();
  409. ExpectPass(*signature, "[{prop1: 'foo'}]", "[{'prop1':'foo'}]",
  410. binding::AsyncResponseType::kNone);
  411. ExpectPass(*signature, "[{prop1: 'foo', prop2: 2}]",
  412. "[{'prop1':'foo','prop2':2}]",
  413. binding::AsyncResponseType::kNone);
  414. ExpectFailure(*signature, "[{prop1: 'foo', prop2: 'a'}]",
  415. ArgumentError("obj", api_errors::PropertyError(
  416. "prop2", InvalidType(kTypeInteger,
  417. kTypeString))));
  418. }
  419. {
  420. auto signature = RefEnum();
  421. ExpectPass(*signature, "['alpha']", "['alpha']",
  422. binding::AsyncResponseType::kNone);
  423. ExpectPass(*signature, "['beta']", "['beta']",
  424. binding::AsyncResponseType::kNone);
  425. ExpectFailure(
  426. *signature, "['gamma']",
  427. ArgumentError("enum", api_errors::InvalidEnumValue({"alpha", "beta"})));
  428. }
  429. }
  430. TEST_F(APISignatureTest, ExpectedSignature) {
  431. EXPECT_EQ("string string", OneString()->GetExpectedSignature());
  432. EXPECT_EQ("string string, integer int",
  433. StringAndInt()->GetExpectedSignature());
  434. EXPECT_EQ("string string, optional integer int, boolean bool",
  435. StringOptionalIntAndBool()->GetExpectedSignature());
  436. EXPECT_EQ("object obj", OneObject()->GetExpectedSignature());
  437. EXPECT_EQ("", NoArgs()->GetExpectedSignature());
  438. EXPECT_EQ("integer int, function callback",
  439. IntAndCallback()->GetExpectedSignature());
  440. EXPECT_EQ("optional integer int, function callback",
  441. OptionalIntAndCallback()->GetExpectedSignature());
  442. EXPECT_EQ("optional function callback",
  443. OptionalCallback()->GetExpectedSignature());
  444. EXPECT_EQ(
  445. "integer int, any any, optional object obj, optional function callback",
  446. IntAnyOptionalObjectOptionalCallback()->GetExpectedSignature());
  447. EXPECT_EQ("refObj obj", RefObj()->GetExpectedSignature());
  448. EXPECT_EQ("refEnum enum", RefEnum()->GetExpectedSignature());
  449. }
  450. TEST_F(APISignatureTest, ParseIgnoringSchema) {
  451. v8::HandleScope handle_scope(isolate());
  452. v8::Local<v8::Context> context = MainContext();
  453. {
  454. // Test with providing an optional callback.
  455. auto signature = IntAndOptionalCallback();
  456. std::vector<v8::Local<v8::Value>> v8_args =
  457. StringToV8Vector(context, "[1, function() {}]");
  458. APISignature::JSONParseResult parse_result =
  459. signature->ConvertArgumentsIgnoringSchema(context, v8_args);
  460. EXPECT_FALSE(parse_result.error);
  461. ASSERT_TRUE(parse_result.arguments_list);
  462. EXPECT_EQ("[1]", ValueToString(*parse_result.arguments_list));
  463. EXPECT_FALSE(parse_result.callback.IsEmpty());
  464. EXPECT_EQ(binding::AsyncResponseType::kCallback, parse_result.async_type);
  465. }
  466. {
  467. // Test with omitting the optional callback.
  468. auto signature = IntAndOptionalCallback();
  469. std::vector<v8::Local<v8::Value>> v8_args =
  470. StringToV8Vector(context, "[1, null]");
  471. v8::Local<v8::Function> callback;
  472. std::unique_ptr<base::ListValue> parsed;
  473. APISignature::JSONParseResult parse_result =
  474. signature->ConvertArgumentsIgnoringSchema(context, v8_args);
  475. EXPECT_FALSE(parse_result.error);
  476. ASSERT_TRUE(parse_result.arguments_list);
  477. EXPECT_EQ("[1]", ValueToString(*parse_result.arguments_list));
  478. EXPECT_TRUE(parse_result.callback.IsEmpty());
  479. EXPECT_EQ(binding::AsyncResponseType::kNone, parse_result.async_type);
  480. }
  481. {
  482. // Test with providing something completely different than the spec, which
  483. // is (unfortunately) allowed and used.
  484. auto signature = OneString();
  485. std::vector<v8::Local<v8::Value>> v8_args =
  486. StringToV8Vector(context, "[{not: 'a string'}]");
  487. APISignature::JSONParseResult parse_result =
  488. signature->ConvertArgumentsIgnoringSchema(context, v8_args);
  489. EXPECT_FALSE(parse_result.error);
  490. ASSERT_TRUE(parse_result.arguments_list);
  491. EXPECT_EQ(R"([{"not":"a string"}])",
  492. ValueToString(*parse_result.arguments_list));
  493. EXPECT_TRUE(parse_result.callback.IsEmpty());
  494. EXPECT_EQ(binding::AsyncResponseType::kNone, parse_result.async_type);
  495. }
  496. {
  497. auto signature = OneObject();
  498. std::vector<v8::Local<v8::Value>> v8_args = StringToV8Vector(
  499. context, "[{prop1: 'foo', other: 'bar', nullProp: null}]");
  500. APISignature::JSONParseResult parse_result =
  501. signature->ConvertArgumentsIgnoringSchema(context, v8_args);
  502. EXPECT_FALSE(parse_result.error);
  503. ASSERT_TRUE(parse_result.arguments_list);
  504. EXPECT_EQ(R"([{"other":"bar","prop1":"foo"}])",
  505. ValueToString(*parse_result.arguments_list));
  506. EXPECT_TRUE(parse_result.callback.IsEmpty());
  507. EXPECT_EQ(binding::AsyncResponseType::kNone, parse_result.async_type);
  508. }
  509. {
  510. // Unserializable arguments are inserted as "null" in the argument list in
  511. // order to match existing JS bindings behavior.
  512. // See https://crbug.com/924045.
  513. auto signature = OneString();
  514. std::vector<v8::Local<v8::Value>> v8_args =
  515. StringToV8Vector(context, "[1, undefined, 1/0]");
  516. APISignature::JSONParseResult parse_result =
  517. signature->ConvertArgumentsIgnoringSchema(context, v8_args);
  518. EXPECT_FALSE(parse_result.error);
  519. ASSERT_TRUE(parse_result.arguments_list);
  520. EXPECT_EQ("[1,null,null]", ValueToString(*parse_result.arguments_list));
  521. EXPECT_TRUE(parse_result.callback.IsEmpty());
  522. EXPECT_EQ(binding::AsyncResponseType::kNone, parse_result.async_type);
  523. }
  524. }
  525. TEST_F(APISignatureTest, ParseIgnoringSchemaWithPromises) {
  526. v8::HandleScope handle_scope(isolate());
  527. v8::Local<v8::Context> context = MainContext();
  528. bool context_allows_promises = true;
  529. auto promises_available = base::BindRepeating(
  530. [](bool* flag, v8::Local<v8::Context> context) { return *flag; },
  531. &context_allows_promises);
  532. auto api_available =
  533. base::BindRepeating([](v8::Local<v8::Context> context,
  534. const std::string& name) { return true; });
  535. BindingAccessChecker access_checker(api_available, promises_available);
  536. SpecVector specs;
  537. specs.push_back(ArgumentSpecBuilder(ArgumentType::INTEGER, "int").Build());
  538. auto int_and_optional_callback = std::make_unique<APISignature>(
  539. std::move(specs),
  540. ReturnsAsyncBuilder().MakeOptional().AddPromiseSupport().Build(),
  541. &access_checker);
  542. {
  543. // Test with providing an optional callback.
  544. std::vector<v8::Local<v8::Value>> v8_args =
  545. StringToV8Vector(context, "[1, function() {}]");
  546. APISignature::JSONParseResult parse_result =
  547. int_and_optional_callback->ConvertArgumentsIgnoringSchema(context,
  548. v8_args);
  549. EXPECT_FALSE(parse_result.error);
  550. ASSERT_TRUE(parse_result.arguments_list);
  551. EXPECT_EQ("[1]", ValueToString(*parse_result.arguments_list));
  552. EXPECT_FALSE(parse_result.callback.IsEmpty());
  553. EXPECT_TRUE(parse_result.callback->IsFunction());
  554. EXPECT_EQ(binding::AsyncResponseType::kCallback, parse_result.async_type);
  555. }
  556. {
  557. // Test with omitting the optional callback.
  558. std::vector<v8::Local<v8::Value>> v8_args =
  559. StringToV8Vector(context, "[1, null]");
  560. v8::Local<v8::Function> callback;
  561. std::unique_ptr<base::ListValue> parsed;
  562. APISignature::JSONParseResult parse_result =
  563. int_and_optional_callback->ConvertArgumentsIgnoringSchema(context,
  564. v8_args);
  565. EXPECT_FALSE(parse_result.error);
  566. ASSERT_TRUE(parse_result.arguments_list);
  567. EXPECT_EQ("[1]", ValueToString(*parse_result.arguments_list));
  568. EXPECT_TRUE(parse_result.callback.IsEmpty());
  569. EXPECT_EQ(binding::AsyncResponseType::kPromise, parse_result.async_type);
  570. }
  571. {
  572. // Test with providing something completely different than the spec, which
  573. // is (unfortunately) allowed and used.
  574. std::vector<v8::Local<v8::Value>> v8_args =
  575. StringToV8Vector(context, "[{not: 'an int'}, null]");
  576. APISignature::JSONParseResult parse_result =
  577. int_and_optional_callback->ConvertArgumentsIgnoringSchema(context,
  578. v8_args);
  579. EXPECT_FALSE(parse_result.error);
  580. ASSERT_TRUE(parse_result.arguments_list);
  581. EXPECT_EQ(R"([{"not":"an int"}])",
  582. ValueToString(*parse_result.arguments_list));
  583. EXPECT_TRUE(parse_result.callback.IsEmpty());
  584. EXPECT_EQ(binding::AsyncResponseType::kPromise, parse_result.async_type);
  585. }
  586. {
  587. // If promises are not available and the optional callback is omitted, we
  588. // should not get a promise response type.
  589. context_allows_promises = false;
  590. std::vector<v8::Local<v8::Value>> v8_args =
  591. StringToV8Vector(context, "[1, null]");
  592. v8::Local<v8::Function> callback;
  593. std::unique_ptr<base::ListValue> parsed;
  594. APISignature::JSONParseResult parse_result =
  595. int_and_optional_callback->ConvertArgumentsIgnoringSchema(context,
  596. v8_args);
  597. EXPECT_FALSE(parse_result.error);
  598. ASSERT_TRUE(parse_result.arguments_list);
  599. EXPECT_EQ("[1]", ValueToString(*parse_result.arguments_list));
  600. EXPECT_TRUE(parse_result.callback.IsEmpty());
  601. EXPECT_EQ(binding::AsyncResponseType::kNone, parse_result.async_type);
  602. }
  603. }
  604. TEST_F(APISignatureTest, ParseArgumentsToV8) {
  605. v8::HandleScope handle_scope(isolate());
  606. v8::Local<v8::Context> context = MainContext();
  607. // Test that parsing a signature returns values that are free of tricky
  608. // getters. This is more thoroughly tested in the ArgumentSpec conversion
  609. // unittests, but verify that it applies to signature parsing.
  610. auto signature = OneObject();
  611. constexpr char kTrickyArgs[] = R"(
  612. [{
  613. get prop1() {
  614. if (this.got)
  615. return 'bar';
  616. this.got = true;
  617. return 'foo';
  618. },
  619. prop2: 'baz'
  620. }])";
  621. std::vector<v8::Local<v8::Value>> args =
  622. StringToV8Vector(context, kTrickyArgs);
  623. APISignature::V8ParseResult parse_result =
  624. signature->ParseArgumentsToV8(context, args, type_refs());
  625. ASSERT_TRUE(parse_result.arguments);
  626. ASSERT_EQ(1u, parse_result.arguments->size());
  627. ASSERT_TRUE((*parse_result.arguments)[0]->IsObject());
  628. gin::Dictionary dict(isolate(),
  629. (*parse_result.arguments)[0].As<v8::Object>());
  630. std::string prop1;
  631. ASSERT_TRUE(dict.Get("prop1", &prop1));
  632. EXPECT_EQ("foo", prop1);
  633. std::string prop2;
  634. ASSERT_TRUE(dict.Get("prop2", &prop2));
  635. EXPECT_EQ("baz", prop2);
  636. }
  637. // Tests that unspecified optional callback is filled with NullCallback in
  638. // APISignature.
  639. //
  640. // Regression test for https://crbug.com/1218569.
  641. TEST_F(APISignatureTest, ParseArgumentsToV8WithUnspecifiedOptionalCallback) {
  642. v8::HandleScope handle_scope(isolate());
  643. v8::Local<v8::Context> context = MainContext();
  644. bool context_allows_promises = true;
  645. auto promises_available = base::BindRepeating(
  646. [](bool* flag, v8::Local<v8::Context> context) { return *flag; },
  647. &context_allows_promises);
  648. auto api_available =
  649. base::BindRepeating([](v8::Local<v8::Context> context,
  650. const std::string& name) { return true; });
  651. BindingAccessChecker access_checker(api_available, promises_available);
  652. SpecVector specs;
  653. specs.push_back(ArgumentSpecBuilder(ArgumentType::INTEGER, "int").Build());
  654. auto signature = std::make_unique<APISignature>(
  655. std::move(specs),
  656. ReturnsAsyncBuilder().MakeOptional().AddPromiseSupport().Build(),
  657. &access_checker);
  658. std::vector<v8::Local<v8::Value>> args =
  659. StringToV8Vector(context, R"([1337])");
  660. APISignature::V8ParseResult parse_result =
  661. signature->ParseArgumentsToV8(context, args, type_refs());
  662. ASSERT_TRUE(parse_result.arguments);
  663. ASSERT_EQ(2u, parse_result.arguments->size());
  664. int int_value = -1;
  665. gin::ConvertFromV8(context->GetIsolate(), (*parse_result.arguments)[0],
  666. &int_value);
  667. EXPECT_EQ(1337, int_value);
  668. ASSERT_FALSE((*parse_result.arguments)[1].IsEmpty());
  669. EXPECT_TRUE((*parse_result.arguments)[1]->IsNull());
  670. }
  671. // Tests response validation, which is stricter than typical validation.
  672. TEST_F(APISignatureTest, ValidateResponse) {
  673. v8::HandleScope handle_scope(isolate());
  674. {
  675. auto signature = std::make_unique<APISignature>(
  676. SpecVector(), ReturnsAsyncBuilder(StringAndIntSpec()).Build(), nullptr);
  677. ExpectResponsePass(*signature, "['hello', 42]");
  678. ExpectResponseFailure(
  679. *signature, "['hello', 'goodbye']",
  680. ArgumentError("int", InvalidType(kTypeInteger, kTypeString)));
  681. }
  682. {
  683. auto signature = std::make_unique<APISignature>(
  684. SpecVector(),
  685. ReturnsAsyncBuilder(StringOptionalIntAndBoolSpec()).Build(), nullptr);
  686. ExpectResponsePass(*signature, "['hello', 42, true]");
  687. ExpectResponsePass(*signature, "['hello', null, true]");
  688. // Responses are not allowed to omit optional inner parameters.
  689. ExpectResponseFailure(
  690. *signature, "['hello', true]",
  691. ArgumentError("int", InvalidType(kTypeInteger, kTypeBoolean)));
  692. }
  693. {
  694. auto signature = std::make_unique<APISignature>(
  695. SpecVector(), ReturnsAsyncBuilder(StringAndOptionalIntSpec()).Build(),
  696. nullptr);
  697. // Responses *are* allowed to omit optional trailing parameters (which will
  698. // then be `undefined` to the caller).
  699. ExpectResponsePass(*signature, "['hello']");
  700. ExpectResponseFailure(
  701. *signature, "['hello', true]",
  702. ArgumentError("int", InvalidType(kTypeInteger, kTypeBoolean)));
  703. }
  704. }
  705. // Tests signature parsing when promise-based responses are supported.
  706. TEST_F(APISignatureTest, PromisesSupport) {
  707. v8::HandleScope handle_scope(isolate());
  708. auto api_available =
  709. base::BindRepeating([](v8::Local<v8::Context> context,
  710. const std::string& name) { return true; });
  711. // Set up a boolean we can flip to simulate if a context supports promises.
  712. // For clarity, this should be explicitly set before each testcase below.
  713. bool context_allows_promises = true;
  714. auto promises_available = base::BindRepeating(
  715. [](bool* flag, v8::Local<v8::Context> context) { return *flag; },
  716. &context_allows_promises);
  717. BindingAccessChecker access_checker(api_available, promises_available);
  718. {
  719. // Test a signature with a required callback.
  720. context_allows_promises = true;
  721. auto required_callback_signature = std::make_unique<APISignature>(
  722. SpecVector(), ReturnsAsyncBuilder().Build(), &access_checker);
  723. // By default, APIs don't support promises, and passing in no arguments
  724. // should fail.
  725. ExpectFailure(*required_callback_signature, "[]", NoMatchingSignature());
  726. }
  727. {
  728. // If we allow promises on the API, parsing the arguments should succeed
  729. // (with a promise-based response type) if the context supports promises.
  730. context_allows_promises = true;
  731. auto required_callback_signature = std::make_unique<APISignature>(
  732. SpecVector(), ReturnsAsyncBuilder().AddPromiseSupport().Build(),
  733. &access_checker);
  734. ExpectPass(*required_callback_signature, "[]", "[]",
  735. binding::AsyncResponseType::kPromise);
  736. // Ensure that the promise support allowing the final argument to be
  737. // optional doesn't mean we can ignore it entirely if it doesn't match the
  738. // signature. See: http://crbug.com/1350315
  739. ExpectFailure(*required_callback_signature, "['foo']",
  740. NoMatchingSignature());
  741. // If the context doesn't support promises, parsing should fail if the
  742. // required callback is left off.
  743. context_allows_promises = false;
  744. ExpectFailure(*required_callback_signature, "[]", NoMatchingSignature());
  745. }
  746. {
  747. // Next, try an optional callback.
  748. context_allows_promises = true;
  749. auto optional_callback_signature = std::make_unique<APISignature>(
  750. SpecVector(), ReturnsAsyncBuilder().MakeOptional().Build(),
  751. &access_checker);
  752. // Even if promises aren't supported, parsing should succeed, because the
  753. // callback is optional.
  754. ExpectPass(*optional_callback_signature, "[]", "[]",
  755. binding::AsyncResponseType::kNone);
  756. }
  757. {
  758. // If we allow promises on the API, parsing the arguments should succeed,
  759. // with a promise-based response type.
  760. context_allows_promises = true;
  761. auto optional_callback_signature = std::make_unique<APISignature>(
  762. SpecVector(),
  763. ReturnsAsyncBuilder().MakeOptional().AddPromiseSupport().Build(),
  764. &access_checker);
  765. ExpectPass(*optional_callback_signature, "[]", "[]",
  766. binding::AsyncResponseType::kPromise);
  767. // If the context doesn't support promises, the call should still pass, but
  768. // there shouldn't be a promise response type.
  769. context_allows_promises = false;
  770. ExpectPass(*optional_callback_signature, "[]", "[]",
  771. binding::AsyncResponseType::kNone);
  772. }
  773. }
  774. } // namespace extensions