Commit 862be486 authored by Devlin Cronin's avatar Devlin Cronin Committed by Commit Bot

[Extensions Bindings] Add promise support to APIBinding

Have APIBinding support promises if the API schema includes a
"supportsPromises" boolean. Note that currently none of the APIs include
this; this is just getting things wired up (and testable).

Add a unittest for the same.

Bug: 978538

Change-Id: I849e64fe1fb81633601cf4c846cd93d01010dcac
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1707768
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#685020}
parent e8f44fd6
......@@ -70,8 +70,14 @@ SignaturePair GetAPISignatureFromDictionary(const base::DictionaryValue* dict) {
const base::ListValue* params = nullptr;
CHECK(dict->GetList("parameters", &params));
bool supports_promises = false;
dict->GetBoolean("supportsPromises", &supports_promises);
SignaturePair result;
result.method_signature = std::make_unique<APISignature>(*params);
result.method_signature->set_promise_support(
supports_promises ? binding::PromiseSupport::kAllowed
: binding::PromiseSupport::kDisallowed);
// If response validation is enabled, parse the callback signature. Otherwise,
// there's no reason to, so don't bother.
if (result.method_signature->has_callback() &&
......@@ -686,9 +692,17 @@ void APIBinding::HandleCall(const std::string& name,
return;
}
request_handler_->StartRequest(context, name,
std::move(parse_result.arguments),
parse_result.callback, custom_callback);
if (parse_result.async_type == binding::AsyncResponseType::kPromise) {
int request_id = 0;
v8::Local<v8::Promise> promise;
std::tie(request_id, promise) = request_handler_->StartPromiseBasedRequest(
context, name, std::move(parse_result.arguments));
arguments->Return(promise);
} else {
request_handler_->StartRequest(context, name,
std::move(parse_result.arguments),
parse_result.callback, custom_callback);
}
}
} // namespace extensions
......@@ -1669,4 +1669,62 @@ TEST_F(APIBindingUnittest,
EXPECT_FALSE(type_refs().GetCallbackSignature("test.noParamCallback"));
}
// Tests promise-based APIs exposed on bindings.
TEST_F(APIBindingUnittest, PromiseBasedAPIs) {
constexpr char kFunctions[] =
R"([{
'name': 'supportsPromises',
'supportsPromises': true,
'parameters': [{
'name': 'int',
'type': 'integer'
}, {
'name': 'callback',
'type': 'function',
'parameters': [{
'name': 'strResult',
'type': 'string'
}]
}]
}])";
SetFunctions(kFunctions);
InitializeBinding();
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = MainContext();
v8::Local<v8::Object> binding_object = binding()->CreateInstance(context);
{
constexpr char kFunctionCall[] =
R"((function(api) {
this.apiResult = api.supportsPromises(3);
this.apiResult.then((strResult) => {
this.strResult = strResult;
});
}))";
v8::Local<v8::Function> promise_api_call =
FunctionFromString(context, kFunctionCall);
v8::Local<v8::Value> args[] = {binding_object};
RunFunctionOnGlobal(promise_api_call, context, base::size(args), args);
v8::Local<v8::Value> api_result =
GetPropertyFromObject(context->Global(), context, "apiResult");
ASSERT_FALSE(api_result.IsEmpty());
ASSERT_TRUE(api_result->IsPromise());
v8::Local<v8::Promise> promise = api_result.As<v8::Promise>();
EXPECT_EQ(v8::Promise::kPending, promise->State());
ASSERT_TRUE(last_request());
request_handler()->CompleteRequest(last_request()->request_id,
*ListValueFromString(R"(["foo"])"),
std::string());
EXPECT_EQ(v8::Promise::kFulfilled, promise->State());
EXPECT_EQ(R"("foo")", V8ToString(promise->Result(), context));
EXPECT_EQ(R"("foo")", GetStringPropertyFromObject(context->Global(),
context, "strResult"));
}
}
} // namespace extensions
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment