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

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

Issue 2469593002: [Extensions Bindings] Add Events support (Closed)
Patch Set: asantest Created 4 years, 1 month 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
« no previous file with comments | « extensions/renderer/api_binding_types.h ('k') | extensions/renderer/api_bindings_system.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/memory/ptr_util.h" 6 #include "base/memory/ptr_util.h"
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
9 #include "base/values.h" 9 #include "base/values.h"
10 #include "content/public/child/v8_value_converter.h" 10 #include "content/public/child/v8_value_converter.h"
11 #include "extensions/renderer/api_binding.h" 11 #include "extensions/renderer/api_binding.h"
12 #include "extensions/renderer/api_binding_test_util.h" 12 #include "extensions/renderer/api_binding_test_util.h"
13 #include "extensions/renderer/api_event_handler.h"
13 #include "extensions/renderer/api_request_handler.h" 14 #include "extensions/renderer/api_request_handler.h"
14 #include "gin/converter.h" 15 #include "gin/converter.h"
15 #include "gin/public/context_holder.h" 16 #include "gin/public/context_holder.h"
16 #include "gin/public/isolate_holder.h" 17 #include "gin/public/isolate_holder.h"
17 #include "gin/test/v8_test.h" 18 #include "gin/test/v8_test.h"
18 #include "gin/try_catch.h" 19 #include "gin/try_catch.h"
19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
20 #include "v8/include/v8.h" 21 #include "v8/include/v8.h"
21 22
22 namespace extensions { 23 namespace extensions {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 v8::HandleScope handle_scope(instance_->isolate()); 125 v8::HandleScope handle_scope(instance_->isolate());
125 holder_ = base::MakeUnique<gin::ContextHolder>(instance_->isolate()); 126 holder_ = base::MakeUnique<gin::ContextHolder>(instance_->isolate());
126 holder_->SetContext( 127 holder_->SetContext(
127 v8::Local<v8::Context>::New(instance_->isolate(), context_)); 128 v8::Local<v8::Context>::New(instance_->isolate(), context_));
128 request_handler_ = base::MakeUnique<APIRequestHandler>( 129 request_handler_ = base::MakeUnique<APIRequestHandler>(
129 base::Bind(&RunFunctionOnGlobalAndIgnoreResult)); 130 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
130 } 131 }
131 132
132 void TearDown() override { 133 void TearDown() override {
133 request_handler_.reset(); 134 request_handler_.reset();
135
136 v8::Global<v8::Context> weak_context(instance_->isolate(), context_);
137 weak_context.SetWeak();
138
134 holder_.reset(); 139 holder_.reset();
135 gin::V8Test::TearDown(); 140
141 // NOTE: We explicitly do NOT call gin::V8Test::TearDown() here because we
142 // do intermittent validation by doing a garbage collection after context
143 // destruction and ensuring the context is fully released (which wouldn't
144 // happen in cycles).
145 // TODO(devlin): It might be time to move off V8Test if we're doing this.
146 {
147 v8::HandleScope handle_scope(instance_->isolate());
148 v8::Local<v8::Context>::New(instance_->isolate(), context_)->Exit();
149 context_.Reset();
150 }
151
152 // Garbage collect everything so that we find any issues where we might be
153 // double-freeing.
154 // '5' is a magic number stolen from Blink; arbitrarily large enough to
155 // hopefully clean up all the various paths.
156 for (int i = 0; i < 5; i++) {
157 instance_->isolate()->RequestGarbageCollectionForTesting(
158 v8::Isolate::kFullGarbageCollection);
159 }
160
161 ASSERT_TRUE(weak_context.IsEmpty());
162
163 instance_->isolate()->Exit();
164 instance_.reset();
136 } 165 }
137 166
138 void ExpectPass(v8::Local<v8::Object> object, 167 void ExpectPass(v8::Local<v8::Object> object,
139 const std::string& script_source, 168 const std::string& script_source,
140 const std::string& expected_json_arguments_single_quotes) { 169 const std::string& expected_json_arguments_single_quotes) {
141 RunTest(object, script_source, true, 170 RunTest(object, script_source, true,
142 ReplaceSingleQuotes(expected_json_arguments_single_quotes), 171 ReplaceSingleQuotes(expected_json_arguments_single_quotes),
143 std::string()); 172 std::string());
144 } 173 }
145 174
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 } 224 }
196 225
197 arguments_.reset(); 226 arguments_.reset();
198 } 227 }
199 228
200 TEST_F(APIBindingTest, Test) { 229 TEST_F(APIBindingTest, Test) {
201 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions); 230 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions);
202 ASSERT_TRUE(functions); 231 ASSERT_TRUE(functions);
203 ArgumentSpec::RefMap refs; 232 ArgumentSpec::RefMap refs;
204 APIBinding binding( 233 APIBinding binding(
205 "test", *functions, nullptr, 234 "test", *functions, nullptr, nullptr,
206 base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this)), 235 base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this)),
207 &refs); 236 &refs);
208 EXPECT_TRUE(refs.empty()); 237 EXPECT_TRUE(refs.empty());
209 238
210 v8::Isolate* isolate = instance_->isolate(); 239 v8::Isolate* isolate = instance_->isolate();
211 240
212 v8::HandleScope handle_scope(isolate); 241 v8::HandleScope handle_scope(isolate);
213 v8::Local<v8::Context> context = 242 v8::Local<v8::Context> context =
214 v8::Local<v8::Context>::New(isolate, context_); 243 v8::Local<v8::Context>::New(isolate, context_);
215 244
245 APIEventHandler event_handler(
246 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
216 v8::Local<v8::Object> binding_object = 247 v8::Local<v8::Object> binding_object =
217 binding.CreateInstance(context, isolate, base::Bind(&AllowAllAPIs)); 248 binding.CreateInstance(context, isolate, &event_handler,
249 base::Bind(&AllowAllAPIs));
218 250
219 ExpectPass(binding_object, "obj.oneString('foo');", "['foo']"); 251 ExpectPass(binding_object, "obj.oneString('foo');", "['foo']");
220 ExpectPass(binding_object, "obj.oneString('');", "['']"); 252 ExpectPass(binding_object, "obj.oneString('');", "['']");
221 ExpectFailure(binding_object, "obj.oneString(1);", kError); 253 ExpectFailure(binding_object, "obj.oneString(1);", kError);
222 ExpectFailure(binding_object, "obj.oneString();", kError); 254 ExpectFailure(binding_object, "obj.oneString();", kError);
223 ExpectFailure(binding_object, "obj.oneString({});", kError); 255 ExpectFailure(binding_object, "obj.oneString({});", kError);
224 ExpectFailure(binding_object, "obj.oneString('foo', 'bar');", kError); 256 ExpectFailure(binding_object, "obj.oneString('foo', 'bar');", kError);
225 257
226 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); 258 ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]");
227 ExpectPass(binding_object, "obj.stringAndInt('foo', -1);", "['foo',-1]"); 259 ExpectPass(binding_object, "obj.stringAndInt('foo', -1);", "['foo',-1]");
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 " }]" 329 " }]"
298 "}]"; 330 "}]";
299 331
300 std::unique_ptr<base::ListValue> functions = 332 std::unique_ptr<base::ListValue> functions =
301 ListValueFromString(kRefFunctions); 333 ListValueFromString(kRefFunctions);
302 ASSERT_TRUE(functions); 334 ASSERT_TRUE(functions);
303 std::unique_ptr<base::ListValue> types = ListValueFromString(kTypes); 335 std::unique_ptr<base::ListValue> types = ListValueFromString(kTypes);
304 ASSERT_TRUE(types); 336 ASSERT_TRUE(types);
305 ArgumentSpec::RefMap refs; 337 ArgumentSpec::RefMap refs;
306 APIBinding binding( 338 APIBinding binding(
307 "test", *functions, types.get(), 339 "test", *functions, types.get(), nullptr,
308 base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this)), 340 base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this)),
309 &refs); 341 &refs);
310 EXPECT_EQ(2u, refs.size()); 342 EXPECT_EQ(2u, refs.size());
311 EXPECT_TRUE(base::ContainsKey(refs, "refObj")); 343 EXPECT_TRUE(base::ContainsKey(refs, "refObj"));
312 EXPECT_TRUE(base::ContainsKey(refs, "refEnum")); 344 EXPECT_TRUE(base::ContainsKey(refs, "refEnum"));
313 345
314 v8::Isolate* isolate = instance_->isolate(); 346 v8::Isolate* isolate = instance_->isolate();
315 347
316 v8::HandleScope handle_scope(isolate); 348 v8::HandleScope handle_scope(isolate);
317 v8::Local<v8::Context> context = 349 v8::Local<v8::Context> context =
318 v8::Local<v8::Context>::New(isolate, context_); 350 v8::Local<v8::Context>::New(isolate, context_);
319 351
352 APIEventHandler event_handler(
353 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
320 v8::Local<v8::Object> binding_object = 354 v8::Local<v8::Object> binding_object =
321 binding.CreateInstance(context, isolate, base::Bind(&AllowAllAPIs)); 355 binding.CreateInstance(context, isolate, &event_handler,
356 base::Bind(&AllowAllAPIs));
322 357
323 ExpectPass(binding_object, "obj.takesRefObj({prop1: 'foo'})", 358 ExpectPass(binding_object, "obj.takesRefObj({prop1: 'foo'})",
324 "[{'prop1':'foo'}]"); 359 "[{'prop1':'foo'}]");
325 ExpectPass(binding_object, "obj.takesRefObj({prop1: 'foo', prop2: 2})", 360 ExpectPass(binding_object, "obj.takesRefObj({prop1: 'foo', prop2: 2})",
326 "[{'prop1':'foo','prop2':2}]"); 361 "[{'prop1':'foo','prop2':2}]");
327 ExpectFailure(binding_object, "obj.takesRefObj({prop1: 'foo', prop2: 'a'})", 362 ExpectFailure(binding_object, "obj.takesRefObj({prop1: 'foo', prop2: 'a'})",
328 kError); 363 kError);
329 ExpectPass(binding_object, "obj.takesRefEnum('alpha')", "['alpha']"); 364 ExpectPass(binding_object, "obj.takesRefEnum('alpha')", "['alpha']");
330 ExpectPass(binding_object, "obj.takesRefEnum('beta')", "['beta']"); 365 ExpectPass(binding_object, "obj.takesRefEnum('beta')", "['beta']");
331 ExpectFailure(binding_object, "obj.takesRefEnum('gamma')", kError); 366 ExpectFailure(binding_object, "obj.takesRefEnum('gamma')", kError);
(...skipping 12 matching lines...) Expand all
344 " 'parameters': []" 379 " 'parameters': []"
345 "}, {" 380 "}, {"
346 " 'name': 'restrictedTwo'," 381 " 'name': 'restrictedTwo',"
347 " 'parameters': []" 382 " 'parameters': []"
348 "}]"; 383 "}]";
349 std::unique_ptr<base::ListValue> functions = 384 std::unique_ptr<base::ListValue> functions =
350 ListValueFromString(kRestrictedFunctions); 385 ListValueFromString(kRestrictedFunctions);
351 ASSERT_TRUE(functions); 386 ASSERT_TRUE(functions);
352 ArgumentSpec::RefMap refs; 387 ArgumentSpec::RefMap refs;
353 APIBinding binding( 388 APIBinding binding(
354 "test", *functions, nullptr, 389 "test", *functions, nullptr, nullptr,
355 base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this)), 390 base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this)),
356 &refs); 391 &refs);
357 392
358 v8::Isolate* isolate = instance_->isolate(); 393 v8::Isolate* isolate = instance_->isolate();
359 v8::HandleScope handle_scope(isolate); 394 v8::HandleScope handle_scope(isolate);
360 v8::Local<v8::Context> context = 395 v8::Local<v8::Context> context =
361 v8::Local<v8::Context>::New(isolate, context_); 396 v8::Local<v8::Context>::New(isolate, context_);
362 397
363 auto is_available = [](const std::string& name) { 398 auto is_available = [](const std::string& name) {
364 std::set<std::string> functions = {"test.allowedOne", "test.allowedTwo", 399 std::set<std::string> functions = {"test.allowedOne", "test.allowedTwo",
365 "test.restrictedOne", 400 "test.restrictedOne",
366 "test.restrictedTwo"}; 401 "test.restrictedTwo"};
367 EXPECT_TRUE(functions.count(name)); 402 EXPECT_TRUE(functions.count(name));
368 return name == "test.allowedOne" || name == "test.allowedTwo"; 403 return name == "test.allowedOne" || name == "test.allowedTwo";
369 }; 404 };
370 405
406 APIEventHandler event_handler(
407 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
371 v8::Local<v8::Object> binding_object = 408 v8::Local<v8::Object> binding_object =
372 binding.CreateInstance(context, isolate, base::Bind(is_available)); 409 binding.CreateInstance(context, isolate, &event_handler,
410 base::Bind(is_available));
373 411
374 auto is_defined = [&binding_object, context](const std::string& name) { 412 auto is_defined = [&binding_object, context](const std::string& name) {
375 v8::Local<v8::Value> val = 413 v8::Local<v8::Value> val =
376 GetPropertyFromObject(binding_object, context, name); 414 GetPropertyFromObject(binding_object, context, name);
377 EXPECT_FALSE(val.IsEmpty()); 415 EXPECT_FALSE(val.IsEmpty());
378 return !val->IsUndefined() && !val->IsNull(); 416 return !val->IsUndefined() && !val->IsNull();
379 }; 417 };
380 418
381 EXPECT_TRUE(is_defined("allowedOne")); 419 EXPECT_TRUE(is_defined("allowedOne"));
382 EXPECT_TRUE(is_defined("allowedTwo")); 420 EXPECT_TRUE(is_defined("allowedTwo"));
383 EXPECT_FALSE(is_defined("restrictedOne")); 421 EXPECT_FALSE(is_defined("restrictedOne"));
384 EXPECT_FALSE(is_defined("restrictedTwo")); 422 EXPECT_FALSE(is_defined("restrictedTwo"));
385 } 423 }
386 424
425 // Tests that events specified in the API are created as properties of the API
426 // object.
427 TEST_F(APIBindingTest, TestEventCreation) {
428 const char kEvents[] = "[{'name': 'onFoo'}, {'name': 'onBar'}]";
429 std::unique_ptr<base::ListValue> events = ListValueFromString(kEvents);
430 ASSERT_TRUE(events);
431 std::unique_ptr<base::ListValue> functions = ListValueFromString(kFunctions);
432 ASSERT_TRUE(functions);
433 ArgumentSpec::RefMap refs;
434 APIBinding binding(
435 "test", *functions, nullptr, events.get(),
436 base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this)),
437 &refs);
438
439 v8::Isolate* isolate = instance_->isolate();
440 v8::HandleScope handle_scope(isolate);
441 v8::Local<v8::Context> context =
442 v8::Local<v8::Context>::New(isolate, context_);
443
444 APIEventHandler event_handler(
445 base::Bind(&RunFunctionOnGlobalAndIgnoreResult));
446 v8::Local<v8::Object> binding_object =
447 binding.CreateInstance(context, isolate, &event_handler,
448 base::Bind(&AllowAllAPIs));
449
450 // Event behavior is tested in the APIEventHandler unittests as well as the
451 // APIBindingsSystem tests, so we really only need to check that the events
452 // are being initialized on the object.
453 v8::Maybe<bool> has_on_foo =
454 binding_object->Has(context, gin::StringToV8(isolate, "onFoo"));
455 EXPECT_TRUE(has_on_foo.IsJust());
456 EXPECT_TRUE(has_on_foo.FromJust());
457
458 v8::Maybe<bool> has_on_bar =
459 binding_object->Has(context, gin::StringToV8(isolate, "onBar"));
460 EXPECT_TRUE(has_on_bar.IsJust());
461 EXPECT_TRUE(has_on_bar.FromJust());
462
463 v8::Maybe<bool> has_on_baz =
464 binding_object->Has(context, gin::StringToV8(isolate, "onBaz"));
465 EXPECT_TRUE(has_on_baz.IsJust());
466 EXPECT_FALSE(has_on_baz.FromJust());
467 }
468
387 } // namespace extensions 469 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/api_binding_types.h ('k') | extensions/renderer/api_bindings_system.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698