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

Side by Side Diff: extensions/renderer/api_request_handler_unittest.cc

Issue 2697363003: [Extensions Bindings] Move request dispatch to APIRequestHandler (Closed)
Patch Set: . Created 3 years, 10 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/api_request_handler.h"
5 #include "base/bind.h" 6 #include "base/bind.h"
7 #include "base/memory/ptr_util.h"
6 #include "base/optional.h" 8 #include "base/optional.h"
7 #include "base/values.h" 9 #include "base/values.h"
8 #include "extensions/renderer/api_binding_test.h" 10 #include "extensions/renderer/api_binding_test.h"
9 #include "extensions/renderer/api_binding_test_util.h" 11 #include "extensions/renderer/api_binding_test_util.h"
10 #include "extensions/renderer/api_request_handler.h"
11 #include "gin/converter.h" 12 #include "gin/converter.h"
12 #include "gin/function_template.h" 13 #include "gin/function_template.h"
13 #include "gin/public/context_holder.h" 14 #include "gin/public/context_holder.h"
14 #include "gin/public/isolate_holder.h" 15 #include "gin/public/isolate_holder.h"
15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gmock/include/gmock/gmock.h"
16 #include "third_party/WebKit/public/web/WebScopedUserGesture.h" 17 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
17 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 18 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
18 19
19 namespace extensions { 20 namespace extensions {
20 21
21 namespace { 22 namespace {
22 23
23 const char kEchoArgs[] = 24 const char kEchoArgs[] =
24 "(function() { this.result = Array.from(arguments); })"; 25 "(function() { this.result = Array.from(arguments); })";
25 26
27 const char kMethod[] = "method";
28
26 // TODO(devlin): We should probably hoist this up to e.g. api_binding_types.h. 29 // TODO(devlin): We should probably hoist this up to e.g. api_binding_types.h.
27 using ArgumentList = std::vector<v8::Local<v8::Value>>; 30 using ArgumentList = std::vector<v8::Local<v8::Value>>;
28 31
32 // TODO(devlin): Should we move some parts of api_binding_unittest.cc to here?
33 void DoNothingWithRequest(std::unique_ptr<APIRequestHandler::Request> request,
34 v8::Local<v8::Context> context) {}
35
29 } // namespace 36 } // namespace
30 37
31 class APIRequestHandlerTest : public APIBindingTest { 38 class APIRequestHandlerTest : public APIBindingTest {
32 public: 39 public:
33 // Runs the given |function|. 40 // Runs the given |function|.
34 void RunJS(v8::Local<v8::Function> function, 41 void RunJS(v8::Local<v8::Function> function,
35 v8::Local<v8::Context> context, 42 v8::Local<v8::Context> context,
36 int argc, 43 int argc,
37 v8::Local<v8::Value> argv[]) { 44 v8::Local<v8::Value> argv[]) {
38 RunFunctionOnGlobal(function, context, argc, argv); 45 RunFunctionOnGlobal(function, context, argc, argv);
(...skipping 12 matching lines...) Expand all
51 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest); 58 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest);
52 }; 59 };
53 60
54 // Tests adding a request to the request handler, and then triggering the 61 // Tests adding a request to the request handler, and then triggering the
55 // response. 62 // response.
56 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) { 63 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) {
57 v8::HandleScope handle_scope(isolate()); 64 v8::HandleScope handle_scope(isolate());
58 v8::Local<v8::Context> context = ContextLocal(); 65 v8::Local<v8::Context> context = ContextLocal();
59 66
60 APIRequestHandler request_handler( 67 APIRequestHandler request_handler(
68 base::Bind(&DoNothingWithRequest),
61 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 69 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
62 APILastError(APILastError::GetParent())); 70 APILastError(APILastError::GetParent()));
63 71
64 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 72 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
65 73
66 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); 74 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
67 ASSERT_FALSE(function.IsEmpty()); 75 ASSERT_FALSE(function.IsEmpty());
68 76
69 int request_id = request_handler.AddPendingRequest(isolate(), function, 77 int request_id = request_handler.StartRequest(
70 context, ArgumentList()); 78 context, kMethod, base::MakeUnique<base::ListValue>(), function,
79 v8::Local<v8::Function>());
71 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 80 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
72 testing::UnorderedElementsAre(request_id)); 81 testing::UnorderedElementsAre(request_id));
73 82
74 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; 83 const char kArguments[] = "['foo',1,{'prop1':'bar'}]";
75 std::unique_ptr<base::ListValue> response_arguments = 84 std::unique_ptr<base::ListValue> response_arguments =
76 ListValueFromString(kArguments); 85 ListValueFromString(kArguments);
77 ASSERT_TRUE(response_arguments); 86 ASSERT_TRUE(response_arguments);
78 request_handler.CompleteRequest(request_id, *response_arguments, 87 request_handler.CompleteRequest(request_id, *response_arguments,
79 std::string()); 88 std::string());
80 89
81 EXPECT_TRUE(did_run_js()); 90 EXPECT_TRUE(did_run_js());
82 EXPECT_EQ(ReplaceSingleQuotes(kArguments), 91 EXPECT_EQ(ReplaceSingleQuotes(kArguments),
83 GetStringPropertyFromObject(context->Global(), context, "result")); 92 GetStringPropertyFromObject(context->Global(), context, "result"));
84 93
85 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 94 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
86 } 95 }
87 96
88 // Tests that trying to run non-existent or invalided requests is a no-op. 97 // Tests that trying to run non-existent or invalided requests is a no-op.
89 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) { 98 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) {
90 v8::HandleScope handle_scope(isolate()); 99 v8::HandleScope handle_scope(isolate());
91 v8::Local<v8::Context> context = ContextLocal(); 100 v8::Local<v8::Context> context = ContextLocal();
92 101
93 APIRequestHandler request_handler( 102 APIRequestHandler request_handler(
103 base::Bind(&DoNothingWithRequest),
94 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 104 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
95 APILastError(APILastError::GetParent())); 105 APILastError(APILastError::GetParent()));
96 106
97 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); 107 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
98 ASSERT_FALSE(function.IsEmpty()); 108 ASSERT_FALSE(function.IsEmpty());
99 109
100 int request_id = request_handler.AddPendingRequest(isolate(), function, 110 int request_id = request_handler.StartRequest(
101 context, ArgumentList()); 111 context, kMethod, base::MakeUnique<base::ListValue>(), function,
112 v8::Local<v8::Function>());
102 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 113 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
103 testing::UnorderedElementsAre(request_id)); 114 testing::UnorderedElementsAre(request_id));
104 115
105 std::unique_ptr<base::ListValue> response_arguments = 116 std::unique_ptr<base::ListValue> response_arguments =
106 ListValueFromString("['foo']"); 117 ListValueFromString("['foo']");
107 ASSERT_TRUE(response_arguments); 118 ASSERT_TRUE(response_arguments);
108 119
109 // Try running with a non-existent request id. 120 // Try running with a non-existent request id.
110 int fake_request_id = 42; 121 int fake_request_id = 42;
111 request_handler.CompleteRequest(fake_request_id, *response_arguments, 122 request_handler.CompleteRequest(fake_request_id, *response_arguments,
112 std::string()); 123 std::string());
113 EXPECT_FALSE(did_run_js()); 124 EXPECT_FALSE(did_run_js());
114 125
115 // Try running with a request from an invalidated context. 126 // Try running with a request from an invalidated context.
116 request_handler.InvalidateContext(context); 127 request_handler.InvalidateContext(context);
117 request_handler.CompleteRequest(request_id, *response_arguments, 128 request_handler.CompleteRequest(request_id, *response_arguments,
118 std::string()); 129 std::string());
119 EXPECT_FALSE(did_run_js()); 130 EXPECT_FALSE(did_run_js());
120 } 131 }
121 132
122 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) { 133 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) {
123 v8::HandleScope handle_scope(isolate()); 134 v8::HandleScope handle_scope(isolate());
124 v8::Local<v8::Context> context_a = ContextLocal(); 135 v8::Local<v8::Context> context_a = ContextLocal();
125 v8::Local<v8::Context> context_b = v8::Context::New(isolate()); 136 v8::Local<v8::Context> context_b = v8::Context::New(isolate());
126 gin::ContextHolder holder_b(isolate()); 137 gin::ContextHolder holder_b(isolate());
127 holder_b.SetContext(context_b); 138 holder_b.SetContext(context_b);
128 139
129 APIRequestHandler request_handler( 140 APIRequestHandler request_handler(
141 base::Bind(&DoNothingWithRequest),
130 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 142 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
131 APILastError(APILastError::GetParent())); 143 APILastError(APILastError::GetParent()));
132 144
133 // By having both different arguments and different behaviors in the 145 // By having both different arguments and different behaviors in the
134 // callbacks, we can easily verify that the right function is called in the 146 // callbacks, we can easily verify that the right function is called in the
135 // right context. 147 // right context.
136 v8::Local<v8::Function> function_a = FunctionFromString( 148 v8::Local<v8::Function> function_a = FunctionFromString(
137 context_a, "(function(res) { this.result = res + 'alpha'; })"); 149 context_a, "(function(res) { this.result = res + 'alpha'; })");
138 v8::Local<v8::Function> function_b = FunctionFromString( 150 v8::Local<v8::Function> function_b = FunctionFromString(
139 context_b, "(function(res) { this.result = res + 'beta'; })"); 151 context_b, "(function(res) { this.result = res + 'beta'; })");
140 152
141 int request_a = request_handler.AddPendingRequest(isolate(), function_a, 153 int request_a = request_handler.StartRequest(
142 context_a, ArgumentList()); 154 context_a, kMethod, base::MakeUnique<base::ListValue>(), function_a,
143 int request_b = request_handler.AddPendingRequest(isolate(), function_b, 155 v8::Local<v8::Function>());
144 context_b, ArgumentList()); 156 int request_b = request_handler.StartRequest(
157 context_b, kMethod, base::MakeUnique<base::ListValue>(), function_b,
158 v8::Local<v8::Function>());
145 159
146 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 160 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
147 testing::UnorderedElementsAre(request_a, request_b)); 161 testing::UnorderedElementsAre(request_a, request_b));
148 162
149 std::unique_ptr<base::ListValue> response_a = 163 std::unique_ptr<base::ListValue> response_a =
150 ListValueFromString("['response_a:']"); 164 ListValueFromString("['response_a:']");
151 ASSERT_TRUE(response_a); 165 ASSERT_TRUE(response_a);
152 166
153 request_handler.CompleteRequest(request_a, *response_a, std::string()); 167 request_handler.CompleteRequest(request_a, *response_a, std::string());
154 EXPECT_TRUE(did_run_js()); 168 EXPECT_TRUE(did_run_js());
(...skipping 14 matching lines...) Expand all
169 EXPECT_EQ( 183 EXPECT_EQ(
170 ReplaceSingleQuotes("'response_b:beta'"), 184 ReplaceSingleQuotes("'response_b:beta'"),
171 GetStringPropertyFromObject(context_b->Global(), context_b, "result")); 185 GetStringPropertyFromObject(context_b->Global(), context_b, "result"));
172 } 186 }
173 187
174 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) { 188 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) {
175 v8::HandleScope handle_scope(isolate()); 189 v8::HandleScope handle_scope(isolate());
176 v8::Local<v8::Context> context = ContextLocal(); 190 v8::Local<v8::Context> context = ContextLocal();
177 191
178 APIRequestHandler request_handler( 192 APIRequestHandler request_handler(
193 base::Bind(&DoNothingWithRequest),
179 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 194 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
180 APILastError(APILastError::GetParent())); 195 APILastError(APILastError::GetParent()));
181 196
182 ArgumentList custom_callback_args = { 197 v8::Local<v8::Function> custom_callback =
183 gin::StringToV8(isolate(), "to"), gin::StringToV8(isolate(), "be"), 198 FunctionFromString(context, kEchoArgs);
184 }; 199 v8::Local<v8::Function> callback =
200 FunctionFromString(context, "(function() {})");
201 ASSERT_FALSE(callback.IsEmpty());
202 ASSERT_FALSE(custom_callback.IsEmpty());
185 203
186 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); 204 int request_id = request_handler.StartRequest(
187 ASSERT_FALSE(function.IsEmpty()); 205 context, "method", base::MakeUnique<base::ListValue>(), callback,
188 206 custom_callback);
189 int request_id = request_handler.AddPendingRequest(
190 isolate(), function, context, custom_callback_args);
191 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 207 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
192 testing::UnorderedElementsAre(request_id)); 208 testing::UnorderedElementsAre(request_id));
193 209
194 std::unique_ptr<base::ListValue> response_arguments = 210 std::unique_ptr<base::ListValue> response_arguments =
195 ListValueFromString("['or','not','to','be']"); 211 ListValueFromString("['response', 'arguments']");
196 ASSERT_TRUE(response_arguments); 212 ASSERT_TRUE(response_arguments);
197 request_handler.CompleteRequest(request_id, *response_arguments, 213 request_handler.CompleteRequest(request_id, *response_arguments,
198 std::string()); 214 std::string());
199 215
200 EXPECT_TRUE(did_run_js()); 216 EXPECT_TRUE(did_run_js());
201 EXPECT_EQ(ReplaceSingleQuotes("['to','be','or','not','to','be']"), 217 v8::Local<v8::Value> result =
202 GetStringPropertyFromObject(context->Global(), context, "result")); 218 GetPropertyFromObject(context->Global(), context, "result");
219 ASSERT_FALSE(result.IsEmpty());
220 ASSERT_TRUE(result->IsArray());
221 ArgumentList args;
222 ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args));
223 ASSERT_EQ(5u, args.size());
224 EXPECT_EQ("\"method\"", V8ToString(args[0], context));
225 EXPECT_EQ("{}", V8ToString(args[1], context));
226 EXPECT_EQ(callback, args[2]);
227 EXPECT_EQ("\"response\"", V8ToString(args[3], context));
228 EXPECT_EQ("\"arguments\"", V8ToString(args[4], context));
203 229
204 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 230 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
205 } 231 }
206 232
207 // Test user gestures being curried around for API requests. 233 // Test user gestures being curried around for API requests.
208 TEST_F(APIRequestHandlerTest, UserGestureTest) { 234 TEST_F(APIRequestHandlerTest, UserGestureTest) {
209 v8::HandleScope handle_scope(isolate()); 235 v8::HandleScope handle_scope(isolate());
210 v8::Local<v8::Context> context = ContextLocal(); 236 v8::Local<v8::Context> context = ContextLocal();
211 237
212 APIRequestHandler request_handler( 238 APIRequestHandler request_handler(
239 base::Bind(&DoNothingWithRequest),
213 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 240 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
214 APILastError(APILastError::GetParent())); 241 APILastError(APILastError::GetParent()));
215 242
216 auto callback = [](base::Optional<bool>* ran_with_user_gesture) { 243 auto callback = [](base::Optional<bool>* ran_with_user_gesture) {
217 *ran_with_user_gesture = 244 *ran_with_user_gesture =
218 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe(); 245 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe();
219 }; 246 };
220 247
221 // Set up a callback to be used with the request so we can check if a user 248 // Set up a callback to be used with the request so we can check if a user
222 // gesture was active. 249 // gesture was active.
223 base::Optional<bool> ran_with_user_gesture; 250 base::Optional<bool> ran_with_user_gesture;
224 v8::Local<v8::FunctionTemplate> function_template = 251 v8::Local<v8::FunctionTemplate> function_template =
225 gin::CreateFunctionTemplate(isolate(), 252 gin::CreateFunctionTemplate(isolate(),
226 base::Bind(callback, &ran_with_user_gesture)); 253 base::Bind(callback, &ran_with_user_gesture));
227 v8::Local<v8::Function> v8_callback = 254 v8::Local<v8::Function> v8_callback =
228 function_template->GetFunction(context).ToLocalChecked(); 255 function_template->GetFunction(context).ToLocalChecked();
229 256
230 // Try first without a user gesture. 257 // Try first without a user gesture.
231 int request_id = request_handler.AddPendingRequest(isolate(), v8_callback, 258 int request_id = request_handler.StartRequest(
232 context, ArgumentList()); 259 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback,
260 v8::Local<v8::Function>());
233 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), 261 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"),
234 std::string()); 262 std::string());
235 263
236 ASSERT_TRUE(ran_with_user_gesture); 264 ASSERT_TRUE(ran_with_user_gesture);
237 EXPECT_FALSE(*ran_with_user_gesture); 265 EXPECT_FALSE(*ran_with_user_gesture);
238 ran_with_user_gesture.reset(); 266 ran_with_user_gesture.reset();
239 267
240 // Next try calling with a user gesture. Since a gesture will be active at the 268 // Next try calling with a user gesture. Since a gesture will be active at the
241 // time of the call, it should also be active during the callback. 269 // time of the call, it should also be active during the callback.
242 { 270 {
243 blink::WebScopedUserGesture user_gesture(nullptr); 271 blink::WebScopedUserGesture user_gesture(nullptr);
244 EXPECT_TRUE( 272 EXPECT_TRUE(
245 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); 273 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe());
246 request_id = request_handler.AddPendingRequest(isolate(), v8_callback, 274 request_id = request_handler.StartRequest(
247 context, ArgumentList()); 275 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback,
276 v8::Local<v8::Function>());
248 } 277 }
249 EXPECT_FALSE( 278 EXPECT_FALSE(
250 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); 279 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe());
251 280
252 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), 281 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"),
253 std::string()); 282 std::string());
254 ASSERT_TRUE(ran_with_user_gesture); 283 ASSERT_TRUE(ran_with_user_gesture);
255 EXPECT_TRUE(*ran_with_user_gesture); 284 EXPECT_TRUE(*ran_with_user_gesture);
256 // Sanity check - after the callback ran, there shouldn't be an active 285 // Sanity check - after the callback ran, there shouldn't be an active
257 // gesture. 286 // gesture.
258 EXPECT_FALSE( 287 EXPECT_FALSE(
259 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); 288 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe());
260 } 289 }
261 290
262 } // namespace extensions 291 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698