| Index: extensions/renderer/bindings/api_binding_unittest.cc
|
| diff --git a/extensions/renderer/bindings/api_binding_unittest.cc b/extensions/renderer/bindings/api_binding_unittest.cc
|
| index 73e1ab3d84ed74d0e83b90fbac2068531be5b8cb..b8e52c2228cc88fa70b773414a8a174151156456 100644
|
| --- a/extensions/renderer/bindings/api_binding_unittest.cc
|
| +++ b/extensions/renderer/bindings/api_binding_unittest.cc
|
| @@ -20,6 +20,7 @@
|
| #include "gin/arguments.h"
|
| #include "gin/converter.h"
|
| #include "gin/public/context_holder.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
|
| #include "v8/include/v8.h"
|
| @@ -80,6 +81,11 @@ void OnEventListenersChanged(const std::string& event_name,
|
| bool was_manual,
|
| v8::Local<v8::Context> context) {}
|
|
|
| +void DoNothingWithSilentRequest(
|
| + v8::Local<v8::Context> context,
|
| + const std::string& call_name,
|
| + const std::vector<v8::Local<v8::Value>>& arguments) {}
|
| +
|
| } // namespace
|
|
|
| class APIBindingUnittest : public APIBindingTest {
|
| @@ -150,6 +156,10 @@ class APIBindingUnittest : public APIBindingTest {
|
| create_custom_type_ = callback;
|
| }
|
|
|
| + void SetOnSilentRequest(const APIBinding::OnSilentRequest& callback) {
|
| + on_silent_request_ = callback;
|
| + }
|
| +
|
| void SetAvailabilityCallback(
|
| const BindingAccessChecker::AvailabilityCallback& callback) {
|
| availability_callback_ = callback;
|
| @@ -162,6 +172,8 @@ class APIBindingUnittest : public APIBindingTest {
|
| }
|
| if (binding_hooks_delegate_)
|
| binding_hooks_->SetDelegate(std::move(binding_hooks_delegate_));
|
| + if (!on_silent_request_)
|
| + on_silent_request_ = base::Bind(&DoNothingWithSilentRequest);
|
| if (!availability_callback_)
|
| availability_callback_ = base::Bind(&AllowAllFeatures);
|
| event_handler_ = base::MakeUnique<APIEventHandler>(
|
| @@ -173,8 +185,8 @@ class APIBindingUnittest : public APIBindingTest {
|
| binding_ = base::MakeUnique<APIBinding>(
|
| kBindingName, binding_functions_.get(), binding_types_.get(),
|
| binding_events_.get(), binding_properties_.get(), create_custom_type_,
|
| - std::move(binding_hooks_), &type_refs_, request_handler_.get(),
|
| - event_handler_.get(), access_checker_.get());
|
| + on_silent_request_, std::move(binding_hooks_), &type_refs_,
|
| + request_handler_.get(), event_handler_.get(), access_checker_.get());
|
| EXPECT_EQ(!binding_types_.get(), type_refs_.empty());
|
| }
|
|
|
| @@ -243,6 +255,7 @@ class APIBindingUnittest : public APIBindingTest {
|
| std::unique_ptr<APIBindingHooks> binding_hooks_;
|
| std::unique_ptr<APIBindingHooksDelegate> binding_hooks_delegate_;
|
| APIBinding::CreateCustomType create_custom_type_;
|
| + APIBinding::OnSilentRequest on_silent_request_;
|
| BindingAccessChecker::AvailabilityCallback availability_callback_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(APIBindingUnittest);
|
| @@ -1301,4 +1314,188 @@ TEST_F(APIBindingUnittest, HooksTemplateInitializer) {
|
| GetStringPropertyFromObject(binding_object, context, "oneString"));
|
| }
|
|
|
| +// Test that running hooks returning different results correctly sends requests
|
| +// or notifies of silent requests.
|
| +TEST_F(APIBindingUnittest, TestSendingRequestsAndSilentRequestsWithHooks) {
|
| + SetFunctions(
|
| + "[{"
|
| + " 'name': 'modifyArgs',"
|
| + " 'parameters': []"
|
| + "}, {"
|
| + " 'name': 'invalidInvocation',"
|
| + " 'parameters': []"
|
| + "}, {"
|
| + " 'name': 'throwException',"
|
| + " 'parameters': []"
|
| + "}, {"
|
| + " 'name': 'dontHandle',"
|
| + " 'parameters': []"
|
| + "}, {"
|
| + " 'name': 'handle',"
|
| + " 'parameters': []"
|
| + "}, {"
|
| + " 'name': 'handleAndSendRequest',"
|
| + " 'parameters': []"
|
| + "}, {"
|
| + " 'name': 'handleWithArgs',"
|
| + " 'parameters': [{"
|
| + " 'name': 'first',"
|
| + " 'type': 'string'"
|
| + " }, {"
|
| + " 'name': 'second',"
|
| + " 'type': 'integer'"
|
| + " }]"
|
| + "}]");
|
| +
|
| + using RequestResult = APIBindingHooks::RequestResult;
|
| +
|
| + auto basic_handler = [](RequestResult::ResultCode code, const APISignature*,
|
| + v8::Local<v8::Context> context,
|
| + std::vector<v8::Local<v8::Value>>* arguments,
|
| + const APITypeReferenceMap& map) {
|
| + return RequestResult(code);
|
| + };
|
| +
|
| + auto hooks = base::MakeUnique<APIBindingHooksTestDelegate>();
|
| + hooks->AddHandler(
|
| + "test.modifyArgs",
|
| + base::Bind(basic_handler, RequestResult::ARGUMENTS_UPDATED));
|
| + hooks->AddHandler(
|
| + "test.invalidInvocation",
|
| + base::Bind(basic_handler, RequestResult::INVALID_INVOCATION));
|
| + hooks->AddHandler("test.dontHandle",
|
| + base::Bind(basic_handler, RequestResult::NOT_HANDLED));
|
| + hooks->AddHandler("test.handle",
|
| + base::Bind(basic_handler, RequestResult::HANDLED));
|
| + hooks->AddHandler(
|
| + "test.throwException",
|
| + base::Bind([](const APISignature*, v8::Local<v8::Context> context,
|
| + std::vector<v8::Local<v8::Value>>* arguments,
|
| + const APITypeReferenceMap& map) {
|
| + context->GetIsolate()->ThrowException(
|
| + gin::StringToV8(context->GetIsolate(), "some error"));
|
| + return RequestResult(RequestResult::THROWN);
|
| + }));
|
| + hooks->AddHandler(
|
| + "test.handleWithArgs",
|
| + base::Bind([](const APISignature*, v8::Local<v8::Context> context,
|
| + std::vector<v8::Local<v8::Value>>* arguments,
|
| + const APITypeReferenceMap& map) {
|
| + arguments->push_back(v8::Integer::New(context->GetIsolate(), 42));
|
| + return RequestResult(RequestResult::HANDLED);
|
| + }));
|
| +
|
| + auto handle_and_send_request =
|
| + [](APIRequestHandler* handler, const APISignature*,
|
| + v8::Local<v8::Context> context,
|
| + std::vector<v8::Local<v8::Value>>* arguments,
|
| + const APITypeReferenceMap& map) {
|
| + handler->StartRequest(
|
| + context, "test.handleAndSendRequest",
|
| + base::MakeUnique<base::ListValue>(), v8::Local<v8::Function>(),
|
| + v8::Local<v8::Function>(), binding::RequestThread::UI);
|
| + return RequestResult(RequestResult::HANDLED);
|
| + };
|
| + hooks->AddHandler("test.handleAndSendRequest",
|
| + base::Bind(handle_and_send_request, request_handler()));
|
| +
|
| + SetHooksDelegate(std::move(hooks));
|
| +
|
| + auto on_silent_request =
|
| + [](base::Optional<std::string>* name_out,
|
| + base::Optional<std::vector<std::string>>* args_out,
|
| + v8::Local<v8::Context> context, const std::string& call_name,
|
| + const std::vector<v8::Local<v8::Value>>& arguments) {
|
| + *name_out = call_name;
|
| + *args_out = std::vector<std::string>();
|
| + (*args_out)->reserve(arguments.size());
|
| + for (const auto& arg : arguments)
|
| + (*args_out)->push_back(V8ToString(arg, context));
|
| + };
|
| + base::Optional<std::string> silent_request;
|
| + base::Optional<std::vector<std::string>> request_arguments;
|
| + SetOnSilentRequest(
|
| + base::Bind(on_silent_request, &silent_request, &request_arguments));
|
| +
|
| + InitializeBinding();
|
| +
|
| + v8::HandleScope handle_scope(isolate());
|
| + v8::Local<v8::Context> context = MainContext();
|
| +
|
| + v8::Local<v8::Object> binding_object = binding()->CreateInstance(context);
|
| +
|
| + auto call_api_method = [binding_object, context](
|
| + base::StringPiece name,
|
| + base::StringPiece string_args) {
|
| + v8::Local<v8::Function> call = FunctionFromString(
|
| + context, base::StringPrintf("(function(binding) { binding.%s(%s); })",
|
| + name.data(), string_args.data()));
|
| + v8::Local<v8::Value> args[] = {binding_object};
|
| + v8::TryCatch try_catch(context->GetIsolate());
|
| + // The throwException call will throw an exception; ignore it.
|
| + ignore_result(call->Call(context, v8::Undefined(context->GetIsolate()),
|
| + arraysize(args), args));
|
| + };
|
| +
|
| + call_api_method("modifyArgs", "");
|
| + ASSERT_TRUE(last_request());
|
| + EXPECT_EQ("test.modifyArgs", last_request()->method_name);
|
| + EXPECT_FALSE(silent_request);
|
| + reset_last_request();
|
| + silent_request.reset();
|
| + request_arguments.reset();
|
| +
|
| + call_api_method("invalidInvocation", "");
|
| + EXPECT_FALSE(last_request());
|
| + EXPECT_FALSE(silent_request);
|
| + reset_last_request();
|
| + silent_request.reset();
|
| + request_arguments.reset();
|
| +
|
| + call_api_method("throwException", "");
|
| + EXPECT_FALSE(last_request());
|
| + EXPECT_FALSE(silent_request);
|
| + reset_last_request();
|
| + silent_request.reset();
|
| + request_arguments.reset();
|
| +
|
| + call_api_method("dontHandle", "");
|
| + ASSERT_TRUE(last_request());
|
| + EXPECT_EQ("test.dontHandle", last_request()->method_name);
|
| + EXPECT_FALSE(silent_request);
|
| + reset_last_request();
|
| + silent_request.reset();
|
| + request_arguments.reset();
|
| +
|
| + call_api_method("handle", "");
|
| + EXPECT_FALSE(last_request());
|
| + ASSERT_TRUE(silent_request);
|
| + EXPECT_EQ("test.handle", *silent_request);
|
| + ASSERT_TRUE(request_arguments);
|
| + EXPECT_TRUE(request_arguments->empty());
|
| + reset_last_request();
|
| + silent_request.reset();
|
| + request_arguments.reset();
|
| +
|
| + call_api_method("handleAndSendRequest", "");
|
| + ASSERT_TRUE(last_request());
|
| + EXPECT_EQ("test.handleAndSendRequest", last_request()->method_name);
|
| + EXPECT_FALSE(silent_request);
|
| + reset_last_request();
|
| + silent_request.reset();
|
| + request_arguments.reset();
|
| +
|
| + call_api_method("handleWithArgs", "'str'");
|
| + EXPECT_FALSE(last_request());
|
| + ASSERT_TRUE(silent_request);
|
| + ASSERT_EQ("test.handleWithArgs", *silent_request);
|
| + ASSERT_TRUE(request_arguments);
|
| + EXPECT_THAT(
|
| + *request_arguments,
|
| + testing::ElementsAre("\"str\"", "42")); // 42 was added by the handler.
|
| + reset_last_request();
|
| + silent_request.reset();
|
| + request_arguments.reset();
|
| +}
|
| +
|
| } // namespace extensions
|
|
|