Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(678)

Unified Diff: extensions/renderer/api_request_handler_unittest.cc

Issue 2947463002: [Extensions Bindings] Add a bindings/ subdirectory under renderer (Closed)
Patch Set: . Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « extensions/renderer/api_request_handler.cc ('k') | extensions/renderer/api_signature.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/api_request_handler_unittest.cc
diff --git a/extensions/renderer/api_request_handler_unittest.cc b/extensions/renderer/api_request_handler_unittest.cc
deleted file mode 100644
index e646a981163bd106034995ba0c2c63c397d11a65..0000000000000000000000000000000000000000
--- a/extensions/renderer/api_request_handler_unittest.cc
+++ /dev/null
@@ -1,488 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/renderer/api_request_handler.h"
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/optional.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "extensions/renderer/api_binding_test.h"
-#include "extensions/renderer/api_binding_test_util.h"
-#include "gin/converter.h"
-#include "gin/function_template.h"
-#include "gin/public/context_holder.h"
-#include "gin/public/isolate_holder.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
-
-namespace extensions {
-
-namespace {
-
-const char kEchoArgs[] =
- "(function() { this.result = Array.from(arguments); })";
-
-const char kMethod[] = "method";
-
-// TODO(devlin): We should probably hoist this up to e.g. api_binding_types.h.
-using ArgumentList = std::vector<v8::Local<v8::Value>>;
-
-// TODO(devlin): Should we move some parts of api_binding_unittest.cc to here?
-void DoNothingWithRequest(std::unique_ptr<APIRequestHandler::Request> request,
- v8::Local<v8::Context> context) {}
-
-} // namespace
-
-class APIRequestHandlerTest : public APIBindingTest {
- public:
- // Runs the given |function|.
- void RunJS(v8::Local<v8::Function> function,
- v8::Local<v8::Context> context,
- int argc,
- v8::Local<v8::Value> argv[]) {
- RunFunctionOnGlobal(function, context, argc, argv);
- did_run_js_ = true;
- }
-
- protected:
- APIRequestHandlerTest() {}
- ~APIRequestHandlerTest() override {}
-
- bool did_run_js() const { return did_run_js_; }
-
- private:
- bool did_run_js_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest);
-};
-
-// Tests adding a request to the request handler, and then triggering the
-// response.
-TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- APIRequestHandler request_handler(
- base::Bind(&DoNothingWithRequest),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
-
- v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
- ASSERT_FALSE(function.IsEmpty());
-
- int request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(), function,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
- testing::UnorderedElementsAre(request_id));
-
- const char kArguments[] = "['foo',1,{'prop1':'bar'}]";
- std::unique_ptr<base::ListValue> response_arguments =
- ListValueFromString(kArguments);
- ASSERT_TRUE(response_arguments);
- request_handler.CompleteRequest(request_id, *response_arguments,
- std::string());
-
- EXPECT_TRUE(did_run_js());
- EXPECT_EQ(ReplaceSingleQuotes(kArguments),
- GetStringPropertyFromObject(context->Global(), context, "result"));
-
- EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
-
- request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(),
- v8::Local<v8::Function>(), v8::Local<v8::Function>(),
- binding::RequestThread::UI);
- EXPECT_NE(-1, request_id);
- request_handler.CompleteRequest(request_id, base::ListValue(), std::string());
-}
-
-// Tests that trying to run non-existent or invalided requests is a no-op.
-TEST_F(APIRequestHandlerTest, InvalidRequestsTest) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- APIRequestHandler request_handler(
- base::Bind(&DoNothingWithRequest),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
- ASSERT_FALSE(function.IsEmpty());
-
- int request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(), function,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
- testing::UnorderedElementsAre(request_id));
-
- std::unique_ptr<base::ListValue> response_arguments =
- ListValueFromString("['foo']");
- ASSERT_TRUE(response_arguments);
-
- // Try running with a non-existent request id.
- int fake_request_id = 42;
- request_handler.CompleteRequest(fake_request_id, *response_arguments,
- std::string());
- EXPECT_FALSE(did_run_js());
-
- // Try running with a request from an invalidated context.
- request_handler.InvalidateContext(context);
- request_handler.CompleteRequest(request_id, *response_arguments,
- std::string());
- EXPECT_FALSE(did_run_js());
-}
-
-TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context_a = MainContext();
- v8::Local<v8::Context> context_b = AddContext();
-
- APIRequestHandler request_handler(
- base::Bind(&DoNothingWithRequest),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- // By having both different arguments and different behaviors in the
- // callbacks, we can easily verify that the right function is called in the
- // right context.
- v8::Local<v8::Function> function_a = FunctionFromString(
- context_a, "(function(res) { this.result = res + 'alpha'; })");
- v8::Local<v8::Function> function_b = FunctionFromString(
- context_b, "(function(res) { this.result = res + 'beta'; })");
-
- int request_a = request_handler.StartRequest(
- context_a, kMethod, base::MakeUnique<base::ListValue>(), function_a,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- int request_b = request_handler.StartRequest(
- context_b, kMethod, base::MakeUnique<base::ListValue>(), function_b,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
-
- EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
- testing::UnorderedElementsAre(request_a, request_b));
-
- std::unique_ptr<base::ListValue> response_a =
- ListValueFromString("['response_a:']");
- ASSERT_TRUE(response_a);
-
- request_handler.CompleteRequest(request_a, *response_a, std::string());
- EXPECT_TRUE(did_run_js());
- EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
- testing::UnorderedElementsAre(request_b));
-
- EXPECT_EQ(
- ReplaceSingleQuotes("'response_a:alpha'"),
- GetStringPropertyFromObject(context_a->Global(), context_a, "result"));
-
- std::unique_ptr<base::ListValue> response_b =
- ListValueFromString("['response_b:']");
- ASSERT_TRUE(response_b);
-
- request_handler.CompleteRequest(request_b, *response_b, std::string());
- EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
-
- EXPECT_EQ(
- ReplaceSingleQuotes("'response_b:beta'"),
- GetStringPropertyFromObject(context_b->Global(), context_b, "result"));
-}
-
-TEST_F(APIRequestHandlerTest, CustomCallbackArguments) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- APIRequestHandler request_handler(
- base::Bind(&DoNothingWithRequest),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- v8::Local<v8::Function> custom_callback =
- FunctionFromString(context, kEchoArgs);
- v8::Local<v8::Function> callback =
- FunctionFromString(context, "(function() {})");
- ASSERT_FALSE(callback.IsEmpty());
- ASSERT_FALSE(custom_callback.IsEmpty());
-
- int request_id = request_handler.StartRequest(
- context, "method", base::MakeUnique<base::ListValue>(), callback,
- custom_callback, binding::RequestThread::UI);
- EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
- testing::UnorderedElementsAre(request_id));
-
- std::unique_ptr<base::ListValue> response_arguments =
- ListValueFromString("['response', 'arguments']");
- ASSERT_TRUE(response_arguments);
- request_handler.CompleteRequest(request_id, *response_arguments,
- std::string());
-
- EXPECT_TRUE(did_run_js());
- v8::Local<v8::Value> result =
- GetPropertyFromObject(context->Global(), context, "result");
- ASSERT_FALSE(result.IsEmpty());
- ASSERT_TRUE(result->IsArray());
- ArgumentList args;
- ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args));
- ASSERT_EQ(5u, args.size());
- EXPECT_EQ("\"method\"", V8ToString(args[0], context));
- EXPECT_EQ(base::StringPrintf("{\"id\":%d}", request_id),
- V8ToString(args[1], context));
- EXPECT_EQ(callback, args[2]);
- EXPECT_EQ("\"response\"", V8ToString(args[3], context));
- EXPECT_EQ("\"arguments\"", V8ToString(args[4], context));
-
- EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
-}
-
-// Test that having a custom callback without an extension-provided callback
-// doesn't crash.
-TEST_F(APIRequestHandlerTest, CustomCallbackArgumentsWithEmptyCallback) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- APIRequestHandler request_handler(
- base::Bind(&DoNothingWithRequest),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- v8::Local<v8::Function> custom_callback =
- FunctionFromString(context, kEchoArgs);
- ASSERT_FALSE(custom_callback.IsEmpty());
-
- v8::Local<v8::Function> empty_callback;
- int request_id = request_handler.StartRequest(
- context, "method", base::MakeUnique<base::ListValue>(), empty_callback,
- custom_callback, binding::RequestThread::UI);
- EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
- testing::UnorderedElementsAre(request_id));
-
- request_handler.CompleteRequest(request_id, base::ListValue(), std::string());
-
- EXPECT_TRUE(did_run_js());
- v8::Local<v8::Value> result =
- GetPropertyFromObject(context->Global(), context, "result");
- ASSERT_FALSE(result.IsEmpty());
- ASSERT_TRUE(result->IsArray());
- ArgumentList args;
- ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args));
- ASSERT_EQ(3u, args.size());
- EXPECT_EQ("\"method\"", V8ToString(args[0], context));
- EXPECT_EQ(base::StringPrintf("{\"id\":%d}", request_id),
- V8ToString(args[1], context));
- EXPECT_TRUE(args[2]->IsUndefined());
-
- EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
-}
-
-// Test user gestures being curried around for API requests.
-TEST_F(APIRequestHandlerTest, UserGestureTest) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- APIRequestHandler request_handler(
- base::Bind(&DoNothingWithRequest),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- auto callback = [](base::Optional<bool>* ran_with_user_gesture) {
- *ran_with_user_gesture =
- blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe();
- };
-
- // Set up a callback to be used with the request so we can check if a user
- // gesture was active.
- base::Optional<bool> ran_with_user_gesture;
- v8::Local<v8::FunctionTemplate> function_template =
- gin::CreateFunctionTemplate(isolate(),
- base::Bind(callback, &ran_with_user_gesture));
- v8::Local<v8::Function> v8_callback =
- function_template->GetFunction(context).ToLocalChecked();
-
- // Try first without a user gesture.
- int request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- request_handler.CompleteRequest(request_id, *ListValueFromString("[]"),
- std::string());
-
- ASSERT_TRUE(ran_with_user_gesture);
- EXPECT_FALSE(*ran_with_user_gesture);
- ran_with_user_gesture.reset();
-
- // Next try calling with a user gesture. Since a gesture will be active at the
- // time of the call, it should also be active during the callback.
- {
- blink::WebScopedUserGesture user_gesture(nullptr);
- EXPECT_TRUE(
- blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe());
- request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- }
- EXPECT_FALSE(
- blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe());
-
- request_handler.CompleteRequest(request_id, *ListValueFromString("[]"),
- std::string());
- ASSERT_TRUE(ran_with_user_gesture);
- EXPECT_TRUE(*ran_with_user_gesture);
- // Sanity check - after the callback ran, there shouldn't be an active
- // gesture.
- EXPECT_FALSE(
- blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe());
-}
-
-TEST_F(APIRequestHandlerTest, RequestThread) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- base::Optional<binding::RequestThread> thread;
- auto on_request = [](base::Optional<binding::RequestThread>* thread_out,
- std::unique_ptr<APIRequestHandler::Request> request,
- v8::Local<v8::Context> context) {
- *thread_out = request->thread;
- };
-
- APIRequestHandler request_handler(
- base::Bind(on_request, &thread),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(),
- v8::Local<v8::Function>(), v8::Local<v8::Function>(),
- binding::RequestThread::UI);
- ASSERT_TRUE(thread);
- EXPECT_EQ(binding::RequestThread::UI, *thread);
- thread.reset();
-
- request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(),
- v8::Local<v8::Function>(), v8::Local<v8::Function>(),
- binding::RequestThread::IO);
- ASSERT_TRUE(thread);
- EXPECT_EQ(binding::RequestThread::IO, *thread);
- thread.reset();
-}
-
-TEST_F(APIRequestHandlerTest, SettingLastError) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- base::Optional<std::string> logged_error;
- auto get_parent = [](v8::Local<v8::Context> context) {
- return context->Global();
- };
-
- auto log_error = [](base::Optional<std::string>* logged_error,
- v8::Local<v8::Context> context,
- const std::string& error) { *logged_error = error; };
-
- APIRequestHandler request_handler(
- base::Bind(&DoNothingWithRequest),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(base::Bind(get_parent),
- base::Bind(log_error, &logged_error)));
-
- const char kReportExposedLastError[] =
- "(function() {\n"
- " if (this.lastError)\n"
- " this.seenLastError = this.lastError.message;\n"
- "})";
- auto get_exposed_error = [context]() {
- return GetStringPropertyFromObject(context->Global(), context,
- "seenLastError");
- };
-
- {
- // Test a successful function call. No last error should be emitted to the
- // console or exposed to the callback.
- v8::Local<v8::Function> callback =
- FunctionFromString(context, kReportExposedLastError);
- int request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(), callback,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- request_handler.CompleteRequest(request_id, base::ListValue(),
- std::string());
- EXPECT_FALSE(logged_error);
- EXPECT_EQ("undefined", get_exposed_error());
- logged_error.reset();
- }
-
- {
- // Test a function call resulting in an error. Since the callback checks the
- // last error, no error should be logged to the console (but it should be
- // exposed to the callback).
- v8::Local<v8::Function> callback =
- FunctionFromString(context, kReportExposedLastError);
- int request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(), callback,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- request_handler.CompleteRequest(request_id, base::ListValue(),
- "some error");
- EXPECT_FALSE(logged_error);
- EXPECT_EQ("\"some error\"", get_exposed_error());
- logged_error.reset();
- }
-
- {
- // Test a function call resulting in an error that goes unchecked by the
- // callback. The error should be logged.
- v8::Local<v8::Function> callback =
- FunctionFromString(context, "(function() {})");
- int request_id = request_handler.StartRequest(
- context, kMethod, base::MakeUnique<base::ListValue>(), callback,
- v8::Local<v8::Function>(), binding::RequestThread::UI);
- request_handler.CompleteRequest(request_id, base::ListValue(),
- "some error");
- ASSERT_TRUE(logged_error);
- EXPECT_EQ("Unchecked runtime.lastError: some error", *logged_error);
- logged_error.reset();
- }
-}
-
-TEST_F(APIRequestHandlerTest, AddPendingRequest) {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = MainContext();
-
- bool dispatched_request = false;
- auto handle_request = [](bool* dispatched_request,
- std::unique_ptr<APIRequestHandler::Request> request,
- v8::Local<v8::Context> context) {
- *dispatched_request = true;
- };
-
- APIRequestHandler request_handler(
- base::Bind(handle_request, &dispatched_request),
- base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
- APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
-
- EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
- v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
- ASSERT_FALSE(function.IsEmpty());
-
- int request_id = request_handler.AddPendingRequest(context, function);
- EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
- testing::UnorderedElementsAre(request_id));
- // Even though we add a pending request, we shouldn't have dispatched anything
- // because AddPendingRequest() is intended for renderer-side implementations.
- EXPECT_FALSE(dispatched_request);
-
- const char kArguments[] = "['foo',1,{'prop1':'bar'}]";
- std::unique_ptr<base::ListValue> response_arguments =
- ListValueFromString(kArguments);
- ASSERT_TRUE(response_arguments);
- request_handler.CompleteRequest(request_id, *response_arguments,
- std::string());
-
- EXPECT_EQ(ReplaceSingleQuotes(kArguments),
- GetStringPropertyFromObject(context->Global(), context, "result"));
-
- EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
- EXPECT_FALSE(dispatched_request);
-}
-
-} // namespace extensions
« no previous file with comments | « extensions/renderer/api_request_handler.cc ('k') | extensions/renderer/api_signature.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698