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

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

Issue 2961103002: [Extensions Bindings] Add an ExceptionHandler class (Closed)
Patch Set: jbroman's Created 3 years, 5 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/bindings/api_request_handler.h"
6
5 #include "base/bind.h" 7 #include "base/bind.h"
6 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
7 #include "base/optional.h" 9 #include "base/optional.h"
8 #include "base/strings/stringprintf.h" 10 #include "base/strings/stringprintf.h"
9 #include "base/values.h" 11 #include "base/values.h"
10 #include "extensions/renderer/bindings/api_binding_test.h" 12 #include "extensions/renderer/bindings/api_binding_test.h"
11 #include "extensions/renderer/bindings/api_binding_test_util.h" 13 #include "extensions/renderer/bindings/api_binding_test_util.h"
12 #include "extensions/renderer/bindings/api_request_handler.h" 14 #include "extensions/renderer/bindings/exception_handler.h"
13 #include "gin/converter.h" 15 #include "gin/converter.h"
14 #include "gin/function_template.h" 16 #include "gin/function_template.h"
15 #include "gin/public/context_holder.h" 17 #include "gin/public/context_holder.h"
16 #include "gin/public/isolate_holder.h" 18 #include "gin/public/isolate_holder.h"
17 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gmock/include/gmock/gmock.h"
18 #include "third_party/WebKit/public/web/WebScopedUserGesture.h" 20 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
19 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 21 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
20 22
21 namespace extensions { 23 namespace extensions {
22 24
(...skipping 17 matching lines...) Expand all
40 public: 42 public:
41 // Runs the given |function|. 43 // Runs the given |function|.
42 void RunJS(v8::Local<v8::Function> function, 44 void RunJS(v8::Local<v8::Function> function,
43 v8::Local<v8::Context> context, 45 v8::Local<v8::Context> context,
44 int argc, 46 int argc,
45 v8::Local<v8::Value> argv[]) { 47 v8::Local<v8::Value> argv[]) {
46 RunFunctionOnGlobal(function, context, argc, argv); 48 RunFunctionOnGlobal(function, context, argc, argv);
47 did_run_js_ = true; 49 did_run_js_ = true;
48 } 50 }
49 51
52 std::unique_ptr<APIRequestHandler> CreateRequestHandler() {
53 return base::MakeUnique<APIRequestHandler>(
54 base::Bind(&DoNothingWithRequest),
55 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
56 APILastError(APILastError::GetParent(), binding::AddConsoleError()),
57 nullptr);
58 }
59
50 protected: 60 protected:
51 APIRequestHandlerTest() {} 61 APIRequestHandlerTest() {}
52 ~APIRequestHandlerTest() override {} 62 ~APIRequestHandlerTest() override {}
53 63
54 bool did_run_js() const { return did_run_js_; } 64 bool did_run_js() const { return did_run_js_; }
55 65
56 private: 66 private:
57 bool did_run_js_ = false; 67 bool did_run_js_ = false;
58 68
59 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest); 69 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest);
60 }; 70 };
61 71
62 // Tests adding a request to the request handler, and then triggering the 72 // Tests adding a request to the request handler, and then triggering the
63 // response. 73 // response.
64 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) { 74 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) {
65 v8::HandleScope handle_scope(isolate()); 75 v8::HandleScope handle_scope(isolate());
66 v8::Local<v8::Context> context = MainContext(); 76 v8::Local<v8::Context> context = MainContext();
67 77
68 APIRequestHandler request_handler( 78 std::unique_ptr<APIRequestHandler> request_handler = CreateRequestHandler();
69 base::Bind(&DoNothingWithRequest),
70 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
71 APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
72 79
73 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 80 EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
74 81
75 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); 82 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
76 ASSERT_FALSE(function.IsEmpty()); 83 ASSERT_FALSE(function.IsEmpty());
77 84
78 int request_id = request_handler.StartRequest( 85 int request_id = request_handler->StartRequest(
79 context, kMethod, base::MakeUnique<base::ListValue>(), function, 86 context, kMethod, base::MakeUnique<base::ListValue>(), function,
80 v8::Local<v8::Function>(), binding::RequestThread::UI); 87 v8::Local<v8::Function>(), binding::RequestThread::UI);
81 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 88 EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
82 testing::UnorderedElementsAre(request_id)); 89 testing::UnorderedElementsAre(request_id));
83 90
84 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; 91 const char kArguments[] = "['foo',1,{'prop1':'bar'}]";
85 std::unique_ptr<base::ListValue> response_arguments = 92 std::unique_ptr<base::ListValue> response_arguments =
86 ListValueFromString(kArguments); 93 ListValueFromString(kArguments);
87 ASSERT_TRUE(response_arguments); 94 ASSERT_TRUE(response_arguments);
88 request_handler.CompleteRequest(request_id, *response_arguments, 95 request_handler->CompleteRequest(request_id, *response_arguments,
89 std::string()); 96 std::string());
90 97
91 EXPECT_TRUE(did_run_js()); 98 EXPECT_TRUE(did_run_js());
92 EXPECT_EQ(ReplaceSingleQuotes(kArguments), 99 EXPECT_EQ(ReplaceSingleQuotes(kArguments),
93 GetStringPropertyFromObject(context->Global(), context, "result")); 100 GetStringPropertyFromObject(context->Global(), context, "result"));
94 101
95 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 102 EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
96 103
97 request_id = request_handler.StartRequest( 104 request_id = request_handler->StartRequest(
98 context, kMethod, base::MakeUnique<base::ListValue>(), 105 context, kMethod, base::MakeUnique<base::ListValue>(),
99 v8::Local<v8::Function>(), v8::Local<v8::Function>(), 106 v8::Local<v8::Function>(), v8::Local<v8::Function>(),
100 binding::RequestThread::UI); 107 binding::RequestThread::UI);
101 EXPECT_NE(-1, request_id); 108 EXPECT_NE(-1, request_id);
102 request_handler.CompleteRequest(request_id, base::ListValue(), std::string()); 109 request_handler->CompleteRequest(request_id, base::ListValue(),
110 std::string());
103 } 111 }
104 112
105 // Tests that trying to run non-existent or invalided requests is a no-op. 113 // Tests that trying to run non-existent or invalided requests is a no-op.
106 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) { 114 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) {
107 v8::HandleScope handle_scope(isolate()); 115 v8::HandleScope handle_scope(isolate());
108 v8::Local<v8::Context> context = MainContext(); 116 v8::Local<v8::Context> context = MainContext();
109 117
110 APIRequestHandler request_handler( 118 std::unique_ptr<APIRequestHandler> request_handler = CreateRequestHandler();
111 base::Bind(&DoNothingWithRequest),
112 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
113 APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
114 119
115 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); 120 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
116 ASSERT_FALSE(function.IsEmpty()); 121 ASSERT_FALSE(function.IsEmpty());
117 122
118 int request_id = request_handler.StartRequest( 123 int request_id = request_handler->StartRequest(
119 context, kMethod, base::MakeUnique<base::ListValue>(), function, 124 context, kMethod, base::MakeUnique<base::ListValue>(), function,
120 v8::Local<v8::Function>(), binding::RequestThread::UI); 125 v8::Local<v8::Function>(), binding::RequestThread::UI);
121 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 126 EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
122 testing::UnorderedElementsAre(request_id)); 127 testing::UnorderedElementsAre(request_id));
123 128
124 std::unique_ptr<base::ListValue> response_arguments = 129 std::unique_ptr<base::ListValue> response_arguments =
125 ListValueFromString("['foo']"); 130 ListValueFromString("['foo']");
126 ASSERT_TRUE(response_arguments); 131 ASSERT_TRUE(response_arguments);
127 132
128 // Try running with a non-existent request id. 133 // Try running with a non-existent request id.
129 int fake_request_id = 42; 134 int fake_request_id = 42;
130 request_handler.CompleteRequest(fake_request_id, *response_arguments, 135 request_handler->CompleteRequest(fake_request_id, *response_arguments,
131 std::string()); 136 std::string());
132 EXPECT_FALSE(did_run_js()); 137 EXPECT_FALSE(did_run_js());
133 138
134 // Try running with a request from an invalidated context. 139 // Try running with a request from an invalidated context.
135 request_handler.InvalidateContext(context); 140 request_handler->InvalidateContext(context);
136 request_handler.CompleteRequest(request_id, *response_arguments, 141 request_handler->CompleteRequest(request_id, *response_arguments,
137 std::string()); 142 std::string());
138 EXPECT_FALSE(did_run_js()); 143 EXPECT_FALSE(did_run_js());
139 } 144 }
140 145
141 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) { 146 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) {
142 v8::HandleScope handle_scope(isolate()); 147 v8::HandleScope handle_scope(isolate());
143 v8::Local<v8::Context> context_a = MainContext(); 148 v8::Local<v8::Context> context_a = MainContext();
144 v8::Local<v8::Context> context_b = AddContext(); 149 v8::Local<v8::Context> context_b = AddContext();
145 150
146 APIRequestHandler request_handler( 151 std::unique_ptr<APIRequestHandler> request_handler = CreateRequestHandler();
147 base::Bind(&DoNothingWithRequest),
148 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
149 APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
150 152
151 // By having both different arguments and different behaviors in the 153 // By having both different arguments and different behaviors in the
152 // callbacks, we can easily verify that the right function is called in the 154 // callbacks, we can easily verify that the right function is called in the
153 // right context. 155 // right context.
154 v8::Local<v8::Function> function_a = FunctionFromString( 156 v8::Local<v8::Function> function_a = FunctionFromString(
155 context_a, "(function(res) { this.result = res + 'alpha'; })"); 157 context_a, "(function(res) { this.result = res + 'alpha'; })");
156 v8::Local<v8::Function> function_b = FunctionFromString( 158 v8::Local<v8::Function> function_b = FunctionFromString(
157 context_b, "(function(res) { this.result = res + 'beta'; })"); 159 context_b, "(function(res) { this.result = res + 'beta'; })");
158 160
159 int request_a = request_handler.StartRequest( 161 int request_a = request_handler->StartRequest(
160 context_a, kMethod, base::MakeUnique<base::ListValue>(), function_a, 162 context_a, kMethod, base::MakeUnique<base::ListValue>(), function_a,
161 v8::Local<v8::Function>(), binding::RequestThread::UI); 163 v8::Local<v8::Function>(), binding::RequestThread::UI);
162 int request_b = request_handler.StartRequest( 164 int request_b = request_handler->StartRequest(
163 context_b, kMethod, base::MakeUnique<base::ListValue>(), function_b, 165 context_b, kMethod, base::MakeUnique<base::ListValue>(), function_b,
164 v8::Local<v8::Function>(), binding::RequestThread::UI); 166 v8::Local<v8::Function>(), binding::RequestThread::UI);
165 167
166 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 168 EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
167 testing::UnorderedElementsAre(request_a, request_b)); 169 testing::UnorderedElementsAre(request_a, request_b));
168 170
169 std::unique_ptr<base::ListValue> response_a = 171 std::unique_ptr<base::ListValue> response_a =
170 ListValueFromString("['response_a:']"); 172 ListValueFromString("['response_a:']");
171 ASSERT_TRUE(response_a); 173 ASSERT_TRUE(response_a);
172 174
173 request_handler.CompleteRequest(request_a, *response_a, std::string()); 175 request_handler->CompleteRequest(request_a, *response_a, std::string());
174 EXPECT_TRUE(did_run_js()); 176 EXPECT_TRUE(did_run_js());
175 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 177 EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
176 testing::UnorderedElementsAre(request_b)); 178 testing::UnorderedElementsAre(request_b));
177 179
178 EXPECT_EQ( 180 EXPECT_EQ(
179 ReplaceSingleQuotes("'response_a:alpha'"), 181 ReplaceSingleQuotes("'response_a:alpha'"),
180 GetStringPropertyFromObject(context_a->Global(), context_a, "result")); 182 GetStringPropertyFromObject(context_a->Global(), context_a, "result"));
181 183
182 std::unique_ptr<base::ListValue> response_b = 184 std::unique_ptr<base::ListValue> response_b =
183 ListValueFromString("['response_b:']"); 185 ListValueFromString("['response_b:']");
184 ASSERT_TRUE(response_b); 186 ASSERT_TRUE(response_b);
185 187
186 request_handler.CompleteRequest(request_b, *response_b, std::string()); 188 request_handler->CompleteRequest(request_b, *response_b, std::string());
187 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 189 EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
188 190
189 EXPECT_EQ( 191 EXPECT_EQ(
190 ReplaceSingleQuotes("'response_b:beta'"), 192 ReplaceSingleQuotes("'response_b:beta'"),
191 GetStringPropertyFromObject(context_b->Global(), context_b, "result")); 193 GetStringPropertyFromObject(context_b->Global(), context_b, "result"));
192 } 194 }
193 195
194 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) { 196 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) {
195 v8::HandleScope handle_scope(isolate()); 197 v8::HandleScope handle_scope(isolate());
196 v8::Local<v8::Context> context = MainContext(); 198 v8::Local<v8::Context> context = MainContext();
197 199
198 APIRequestHandler request_handler( 200 std::unique_ptr<APIRequestHandler> request_handler = CreateRequestHandler();
199 base::Bind(&DoNothingWithRequest),
200 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
201 APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
202 201
203 v8::Local<v8::Function> custom_callback = 202 v8::Local<v8::Function> custom_callback =
204 FunctionFromString(context, kEchoArgs); 203 FunctionFromString(context, kEchoArgs);
205 v8::Local<v8::Function> callback = 204 v8::Local<v8::Function> callback =
206 FunctionFromString(context, "(function() {})"); 205 FunctionFromString(context, "(function() {})");
207 ASSERT_FALSE(callback.IsEmpty()); 206 ASSERT_FALSE(callback.IsEmpty());
208 ASSERT_FALSE(custom_callback.IsEmpty()); 207 ASSERT_FALSE(custom_callback.IsEmpty());
209 208
210 int request_id = request_handler.StartRequest( 209 int request_id = request_handler->StartRequest(
211 context, "method", base::MakeUnique<base::ListValue>(), callback, 210 context, "method", base::MakeUnique<base::ListValue>(), callback,
212 custom_callback, binding::RequestThread::UI); 211 custom_callback, binding::RequestThread::UI);
213 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 212 EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
214 testing::UnorderedElementsAre(request_id)); 213 testing::UnorderedElementsAre(request_id));
215 214
216 std::unique_ptr<base::ListValue> response_arguments = 215 std::unique_ptr<base::ListValue> response_arguments =
217 ListValueFromString("['response', 'arguments']"); 216 ListValueFromString("['response', 'arguments']");
218 ASSERT_TRUE(response_arguments); 217 ASSERT_TRUE(response_arguments);
219 request_handler.CompleteRequest(request_id, *response_arguments, 218 request_handler->CompleteRequest(request_id, *response_arguments,
220 std::string()); 219 std::string());
221 220
222 EXPECT_TRUE(did_run_js()); 221 EXPECT_TRUE(did_run_js());
223 v8::Local<v8::Value> result = 222 v8::Local<v8::Value> result =
224 GetPropertyFromObject(context->Global(), context, "result"); 223 GetPropertyFromObject(context->Global(), context, "result");
225 ASSERT_FALSE(result.IsEmpty()); 224 ASSERT_FALSE(result.IsEmpty());
226 ASSERT_TRUE(result->IsArray()); 225 ASSERT_TRUE(result->IsArray());
227 ArgumentList args; 226 ArgumentList args;
228 ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args)); 227 ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args));
229 ASSERT_EQ(5u, args.size()); 228 ASSERT_EQ(5u, args.size());
230 EXPECT_EQ("\"method\"", V8ToString(args[0], context)); 229 EXPECT_EQ("\"method\"", V8ToString(args[0], context));
231 EXPECT_EQ(base::StringPrintf("{\"id\":%d}", request_id), 230 EXPECT_EQ(base::StringPrintf("{\"id\":%d}", request_id),
232 V8ToString(args[1], context)); 231 V8ToString(args[1], context));
233 EXPECT_EQ(callback, args[2]); 232 EXPECT_EQ(callback, args[2]);
234 EXPECT_EQ("\"response\"", V8ToString(args[3], context)); 233 EXPECT_EQ("\"response\"", V8ToString(args[3], context));
235 EXPECT_EQ("\"arguments\"", V8ToString(args[4], context)); 234 EXPECT_EQ("\"arguments\"", V8ToString(args[4], context));
236 235
237 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 236 EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
238 } 237 }
239 238
240 // Test that having a custom callback without an extension-provided callback 239 // Test that having a custom callback without an extension-provided callback
241 // doesn't crash. 240 // doesn't crash.
242 TEST_F(APIRequestHandlerTest, CustomCallbackArgumentsWithEmptyCallback) { 241 TEST_F(APIRequestHandlerTest, CustomCallbackArgumentsWithEmptyCallback) {
243 v8::HandleScope handle_scope(isolate()); 242 v8::HandleScope handle_scope(isolate());
244 v8::Local<v8::Context> context = MainContext(); 243 v8::Local<v8::Context> context = MainContext();
245 244
246 APIRequestHandler request_handler( 245 std::unique_ptr<APIRequestHandler> request_handler = CreateRequestHandler();
247 base::Bind(&DoNothingWithRequest),
248 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
249 APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
250 246
251 v8::Local<v8::Function> custom_callback = 247 v8::Local<v8::Function> custom_callback =
252 FunctionFromString(context, kEchoArgs); 248 FunctionFromString(context, kEchoArgs);
253 ASSERT_FALSE(custom_callback.IsEmpty()); 249 ASSERT_FALSE(custom_callback.IsEmpty());
254 250
255 v8::Local<v8::Function> empty_callback; 251 v8::Local<v8::Function> empty_callback;
256 int request_id = request_handler.StartRequest( 252 int request_id = request_handler->StartRequest(
257 context, "method", base::MakeUnique<base::ListValue>(), empty_callback, 253 context, "method", base::MakeUnique<base::ListValue>(), empty_callback,
258 custom_callback, binding::RequestThread::UI); 254 custom_callback, binding::RequestThread::UI);
259 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 255 EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
260 testing::UnorderedElementsAre(request_id)); 256 testing::UnorderedElementsAre(request_id));
261 257
262 request_handler.CompleteRequest(request_id, base::ListValue(), std::string()); 258 request_handler->CompleteRequest(request_id, base::ListValue(),
259 std::string());
263 260
264 EXPECT_TRUE(did_run_js()); 261 EXPECT_TRUE(did_run_js());
265 v8::Local<v8::Value> result = 262 v8::Local<v8::Value> result =
266 GetPropertyFromObject(context->Global(), context, "result"); 263 GetPropertyFromObject(context->Global(), context, "result");
267 ASSERT_FALSE(result.IsEmpty()); 264 ASSERT_FALSE(result.IsEmpty());
268 ASSERT_TRUE(result->IsArray()); 265 ASSERT_TRUE(result->IsArray());
269 ArgumentList args; 266 ArgumentList args;
270 ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args)); 267 ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args));
271 ASSERT_EQ(3u, args.size()); 268 ASSERT_EQ(3u, args.size());
272 EXPECT_EQ("\"method\"", V8ToString(args[0], context)); 269 EXPECT_EQ("\"method\"", V8ToString(args[0], context));
273 EXPECT_EQ(base::StringPrintf("{\"id\":%d}", request_id), 270 EXPECT_EQ(base::StringPrintf("{\"id\":%d}", request_id),
274 V8ToString(args[1], context)); 271 V8ToString(args[1], context));
275 EXPECT_TRUE(args[2]->IsUndefined()); 272 EXPECT_TRUE(args[2]->IsUndefined());
276 273
277 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 274 EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
278 } 275 }
279 276
280 // Test user gestures being curried around for API requests. 277 // Test user gestures being curried around for API requests.
281 TEST_F(APIRequestHandlerTest, UserGestureTest) { 278 TEST_F(APIRequestHandlerTest, UserGestureTest) {
282 v8::HandleScope handle_scope(isolate()); 279 v8::HandleScope handle_scope(isolate());
283 v8::Local<v8::Context> context = MainContext(); 280 v8::Local<v8::Context> context = MainContext();
284 281
285 APIRequestHandler request_handler( 282 std::unique_ptr<APIRequestHandler> request_handler = CreateRequestHandler();
286 base::Bind(&DoNothingWithRequest),
287 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
288 APILastError(APILastError::GetParent(), APILastError::AddConsoleError()));
289 283
290 auto callback = [](base::Optional<bool>* ran_with_user_gesture) { 284 auto callback = [](base::Optional<bool>* ran_with_user_gesture) {
291 *ran_with_user_gesture = 285 *ran_with_user_gesture =
292 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe(); 286 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe();
293 }; 287 };
294 288
295 // Set up a callback to be used with the request so we can check if a user 289 // Set up a callback to be used with the request so we can check if a user
296 // gesture was active. 290 // gesture was active.
297 base::Optional<bool> ran_with_user_gesture; 291 base::Optional<bool> ran_with_user_gesture;
298 v8::Local<v8::FunctionTemplate> function_template = 292 v8::Local<v8::FunctionTemplate> function_template =
299 gin::CreateFunctionTemplate(isolate(), 293 gin::CreateFunctionTemplate(isolate(),
300 base::Bind(callback, &ran_with_user_gesture)); 294 base::Bind(callback, &ran_with_user_gesture));
301 v8::Local<v8::Function> v8_callback = 295 v8::Local<v8::Function> v8_callback =
302 function_template->GetFunction(context).ToLocalChecked(); 296 function_template->GetFunction(context).ToLocalChecked();
303 297
304 // Try first without a user gesture. 298 // Try first without a user gesture.
305 int request_id = request_handler.StartRequest( 299 int request_id = request_handler->StartRequest(
306 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback, 300 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback,
307 v8::Local<v8::Function>(), binding::RequestThread::UI); 301 v8::Local<v8::Function>(), binding::RequestThread::UI);
308 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), 302 request_handler->CompleteRequest(request_id, *ListValueFromString("[]"),
309 std::string()); 303 std::string());
310 304
311 ASSERT_TRUE(ran_with_user_gesture); 305 ASSERT_TRUE(ran_with_user_gesture);
312 EXPECT_FALSE(*ran_with_user_gesture); 306 EXPECT_FALSE(*ran_with_user_gesture);
313 ran_with_user_gesture.reset(); 307 ran_with_user_gesture.reset();
314 308
315 // Next try calling with a user gesture. Since a gesture will be active at the 309 // Next try calling with a user gesture. Since a gesture will be active at the
316 // time of the call, it should also be active during the callback. 310 // time of the call, it should also be active during the callback.
317 { 311 {
318 blink::WebScopedUserGesture user_gesture(nullptr); 312 blink::WebScopedUserGesture user_gesture(nullptr);
319 EXPECT_TRUE( 313 EXPECT_TRUE(
320 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe()); 314 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe());
321 request_id = request_handler.StartRequest( 315 request_id = request_handler->StartRequest(
322 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback, 316 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback,
323 v8::Local<v8::Function>(), binding::RequestThread::UI); 317 v8::Local<v8::Function>(), binding::RequestThread::UI);
324 } 318 }
325 EXPECT_FALSE( 319 EXPECT_FALSE(
326 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe()); 320 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe());
327 321
328 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), 322 request_handler->CompleteRequest(request_id, *ListValueFromString("[]"),
329 std::string()); 323 std::string());
330 ASSERT_TRUE(ran_with_user_gesture); 324 ASSERT_TRUE(ran_with_user_gesture);
331 EXPECT_TRUE(*ran_with_user_gesture); 325 EXPECT_TRUE(*ran_with_user_gesture);
332 // Sanity check - after the callback ran, there shouldn't be an active 326 // Sanity check - after the callback ran, there shouldn't be an active
333 // gesture. 327 // gesture.
334 EXPECT_FALSE( 328 EXPECT_FALSE(
335 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe()); 329 blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe());
336 } 330 }
337 331
338 TEST_F(APIRequestHandlerTest, RequestThread) { 332 TEST_F(APIRequestHandlerTest, RequestThread) {
339 v8::HandleScope handle_scope(isolate()); 333 v8::HandleScope handle_scope(isolate());
340 v8::Local<v8::Context> context = MainContext(); 334 v8::Local<v8::Context> context = MainContext();
341 335
342 base::Optional<binding::RequestThread> thread; 336 base::Optional<binding::RequestThread> thread;
343 auto on_request = [](base::Optional<binding::RequestThread>* thread_out, 337 auto on_request = [](base::Optional<binding::RequestThread>* thread_out,
344 std::unique_ptr<APIRequestHandler::Request> request, 338 std::unique_ptr<APIRequestHandler::Request> request,
345 v8::Local<v8::Context> context) { 339 v8::Local<v8::Context> context) {
346 *thread_out = request->thread; 340 *thread_out = request->thread;
347 }; 341 };
348 342
349 APIRequestHandler request_handler( 343 APIRequestHandler request_handler(
350 base::Bind(on_request, &thread), 344 base::Bind(on_request, &thread),
351 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 345 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
352 APILastError(APILastError::GetParent(), APILastError::AddConsoleError())); 346 APILastError(APILastError::GetParent(), binding::AddConsoleError()),
347 nullptr);
353 348
354 request_handler.StartRequest( 349 request_handler.StartRequest(
355 context, kMethod, base::MakeUnique<base::ListValue>(), 350 context, kMethod, base::MakeUnique<base::ListValue>(),
356 v8::Local<v8::Function>(), v8::Local<v8::Function>(), 351 v8::Local<v8::Function>(), v8::Local<v8::Function>(),
357 binding::RequestThread::UI); 352 binding::RequestThread::UI);
358 ASSERT_TRUE(thread); 353 ASSERT_TRUE(thread);
359 EXPECT_EQ(binding::RequestThread::UI, *thread); 354 EXPECT_EQ(binding::RequestThread::UI, *thread);
360 thread.reset(); 355 thread.reset();
361 356
362 request_handler.StartRequest( 357 request_handler.StartRequest(
(...skipping 16 matching lines...) Expand all
379 }; 374 };
380 375
381 auto log_error = [](base::Optional<std::string>* logged_error, 376 auto log_error = [](base::Optional<std::string>* logged_error,
382 v8::Local<v8::Context> context, 377 v8::Local<v8::Context> context,
383 const std::string& error) { *logged_error = error; }; 378 const std::string& error) { *logged_error = error; };
384 379
385 APIRequestHandler request_handler( 380 APIRequestHandler request_handler(
386 base::Bind(&DoNothingWithRequest), 381 base::Bind(&DoNothingWithRequest),
387 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 382 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
388 APILastError(base::Bind(get_parent), 383 APILastError(base::Bind(get_parent),
389 base::Bind(log_error, &logged_error))); 384 base::Bind(log_error, &logged_error)),
385 nullptr);
390 386
391 const char kReportExposedLastError[] = 387 const char kReportExposedLastError[] =
392 "(function() {\n" 388 "(function() {\n"
393 " if (this.lastError)\n" 389 " if (this.lastError)\n"
394 " this.seenLastError = this.lastError.message;\n" 390 " this.seenLastError = this.lastError.message;\n"
395 "})"; 391 "})";
396 auto get_exposed_error = [context]() { 392 auto get_exposed_error = [context]() {
397 return GetStringPropertyFromObject(context->Global(), context, 393 return GetStringPropertyFromObject(context->Global(), context,
398 "seenLastError"); 394 "seenLastError");
399 }; 395 };
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 bool dispatched_request = false; 448 bool dispatched_request = false;
453 auto handle_request = [](bool* dispatched_request, 449 auto handle_request = [](bool* dispatched_request,
454 std::unique_ptr<APIRequestHandler::Request> request, 450 std::unique_ptr<APIRequestHandler::Request> request,
455 v8::Local<v8::Context> context) { 451 v8::Local<v8::Context> context) {
456 *dispatched_request = true; 452 *dispatched_request = true;
457 }; 453 };
458 454
459 APIRequestHandler request_handler( 455 APIRequestHandler request_handler(
460 base::Bind(handle_request, &dispatched_request), 456 base::Bind(handle_request, &dispatched_request),
461 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), 457 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)),
462 APILastError(APILastError::GetParent(), APILastError::AddConsoleError())); 458 APILastError(APILastError::GetParent(), binding::AddConsoleError()),
459 nullptr);
463 460
464 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 461 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
465 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); 462 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs);
466 ASSERT_FALSE(function.IsEmpty()); 463 ASSERT_FALSE(function.IsEmpty());
467 464
468 int request_id = request_handler.AddPendingRequest(context, function); 465 int request_id = request_handler.AddPendingRequest(context, function);
469 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), 466 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(),
470 testing::UnorderedElementsAre(request_id)); 467 testing::UnorderedElementsAre(request_id));
471 // Even though we add a pending request, we shouldn't have dispatched anything 468 // Even though we add a pending request, we shouldn't have dispatched anything
472 // because AddPendingRequest() is intended for renderer-side implementations. 469 // because AddPendingRequest() is intended for renderer-side implementations.
473 EXPECT_FALSE(dispatched_request); 470 EXPECT_FALSE(dispatched_request);
474 471
475 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; 472 const char kArguments[] = "['foo',1,{'prop1':'bar'}]";
476 std::unique_ptr<base::ListValue> response_arguments = 473 std::unique_ptr<base::ListValue> response_arguments =
477 ListValueFromString(kArguments); 474 ListValueFromString(kArguments);
478 ASSERT_TRUE(response_arguments); 475 ASSERT_TRUE(response_arguments);
479 request_handler.CompleteRequest(request_id, *response_arguments, 476 request_handler.CompleteRequest(request_id, *response_arguments,
480 std::string()); 477 std::string());
481 478
482 EXPECT_EQ(ReplaceSingleQuotes(kArguments), 479 EXPECT_EQ(ReplaceSingleQuotes(kArguments),
483 GetStringPropertyFromObject(context->Global(), context, "result")); 480 GetStringPropertyFromObject(context->Global(), context, "result"));
484 481
485 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); 482 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty());
486 EXPECT_FALSE(dispatched_request); 483 EXPECT_FALSE(dispatched_request);
487 } 484 }
488 485
486 // Tests that throwing an exception in a callback is properly handled.
487 TEST_F(APIRequestHandlerTest, ThrowExceptionInCallback) {
488 v8::HandleScope handle_scope(isolate());
489 v8::Local<v8::Context> context = MainContext();
490
491 auto add_console_error = [](base::Optional<std::string>* error_out,
492 v8::Local<v8::Context> context,
493 const std::string& error) { *error_out = error; };
494
495 // RunFunction* from the test util assert no errors; provide a version that
496 // allows them.
497 auto run_function_and_allow_errors =
498 [](v8::Local<v8::Function> function, v8::Local<v8::Context> context,
499 int argc, v8::Local<v8::Value> argv[]) {
500 ignore_result(function->Call(context, context->Global(), argc, argv));
501 };
502
503 base::Optional<std::string> logged_error;
504 ExceptionHandler exception_handler(
505 base::Bind(add_console_error, &logged_error),
506 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
507
508 APIRequestHandler request_handler(
509 base::Bind(&DoNothingWithRequest),
510 base::Bind(run_function_and_allow_errors),
511 APILastError(APILastError::GetParent(), binding::AddConsoleError()),
512 &exception_handler);
513
514 v8::TryCatch try_catch(isolate());
515 v8::Local<v8::Function> callback_throwing_error =
516 FunctionFromString(context, "(function() { throw new Error('hello'); })");
517 int request_id =
518 request_handler.AddPendingRequest(context, callback_throwing_error);
519 request_handler.CompleteRequest(request_id, base::ListValue(), std::string());
520 // The outer TryCatch should not be caught. This is important to not disrupt
lazyboy 2017/07/10 23:12:08 Add a bit more context about the try catch you're
Devlin 2017/07/11 17:33:35 Done.
521 // our bindings code (or other running JS) when asynchronously returning from
522 // an API call.
523 EXPECT_FALSE(try_catch.HasCaught());
524 ASSERT_TRUE(logged_error);
525 EXPECT_EQ("Error handling response: Uncaught Error: hello", *logged_error);
526 }
527
489 } // namespace extensions 528 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698