| OLD | NEW |
| 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_bindings_system.h" | 5 #include "extensions/renderer/api_bindings_system.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/macros.h" | 8 #include "base/macros.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 | 84 |
| 85 const char kGammaAPIName[] = "gamma"; | 85 const char kGammaAPIName[] = "gamma"; |
| 86 const char kGammaAPISpec[] = | 86 const char kGammaAPISpec[] = |
| 87 "{" | 87 "{" |
| 88 " 'functions': [{" | 88 " 'functions': [{" |
| 89 " 'name': 'functionWithExternalRef'," | 89 " 'name': 'functionWithExternalRef'," |
| 90 " 'parameters': [{ 'name': 'someRef', '$ref': 'alpha.objRef' }]" | 90 " 'parameters': [{ 'name': 'someRef', '$ref': 'alpha.objRef' }]" |
| 91 " }]" | 91 " }]" |
| 92 "}"; | 92 "}"; |
| 93 | 93 |
| 94 bool AllowAllAPIs(const std::string& name) { | 94 bool AllowAllAPIs(v8::Local<v8::Context> context, const std::string& name) { |
| 95 return true; | 95 return true; |
| 96 } | 96 } |
| 97 | 97 |
| 98 } // namespace | 98 } // namespace |
| 99 | 99 |
| 100 APIBindingsSystemTest::APIBindingsSystemTest() {} | 100 APIBindingsSystemTest::APIBindingsSystemTest() {} |
| 101 APIBindingsSystemTest::~APIBindingsSystemTest() = default; | 101 APIBindingsSystemTest::~APIBindingsSystemTest() = default; |
| 102 | 102 |
| 103 void APIBindingsSystemTest::SetUp() { | 103 void APIBindingsSystemTest::SetUp() { |
| 104 APIBindingTest::SetUp(); | 104 APIBindingTest::SetUp(); |
| 105 | 105 |
| 106 // Create the fake API schemas. | 106 // Create the fake API schemas. |
| 107 for (const auto& api : GetAPIs()) { | 107 for (const auto& api : GetAPIs()) { |
| 108 std::unique_ptr<base::DictionaryValue> api_schema = | 108 std::unique_ptr<base::DictionaryValue> api_schema = |
| 109 DictionaryValueFromString(api.spec); | 109 DictionaryValueFromString(api.spec); |
| 110 ASSERT_TRUE(api_schema); | 110 ASSERT_TRUE(api_schema); |
| 111 api_schemas_[api.name] = std::move(api_schema); | 111 api_schemas_[api.name] = std::move(api_schema); |
| 112 } | 112 } |
| 113 | 113 |
| 114 bindings_system_ = base::MakeUnique<APIBindingsSystem>( | 114 bindings_system_ = base::MakeUnique<APIBindingsSystem>( |
| 115 base::Bind(&RunFunctionOnGlobalAndIgnoreResult), | 115 base::Bind(&RunFunctionOnGlobalAndIgnoreResult), |
| 116 base::Bind(&RunFunctionOnGlobalAndReturnHandle), | 116 base::Bind(&RunFunctionOnGlobalAndReturnHandle), |
| 117 base::Bind(&APIBindingsSystemTest::GetAPISchema, base::Unretained(this)), | 117 base::Bind(&APIBindingsSystemTest::GetAPISchema, base::Unretained(this)), |
| 118 base::Bind(&AllowAllAPIs), |
| 118 base::Bind(&APIBindingsSystemTest::OnAPIRequest, base::Unretained(this)), | 119 base::Bind(&APIBindingsSystemTest::OnAPIRequest, base::Unretained(this)), |
| 119 base::Bind(&APIBindingsSystemTest::OnEventListenersChanged, | 120 base::Bind(&APIBindingsSystemTest::OnEventListenersChanged, |
| 120 base::Unretained(this)), | 121 base::Unretained(this)), |
| 121 APILastError(base::Bind(&APIBindingsSystemTest::GetLastErrorParent, | 122 APILastError(base::Bind(&APIBindingsSystemTest::GetLastErrorParent, |
| 122 base::Unretained(this)), | 123 base::Unretained(this)), |
| 123 APILastError::AddConsoleError())); | 124 APILastError::AddConsoleError())); |
| 124 } | 125 } |
| 125 | 126 |
| 126 void APIBindingsSystemTest::TearDown() { | 127 void APIBindingsSystemTest::TearDown() { |
| 127 // Dispose all contexts now so that we call WillReleaseContext(). | 128 // Dispose all contexts now so that we call WillReleaseContext(). |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 v8::Local<v8::Value> argv[] = {object}; | 199 v8::Local<v8::Value> argv[] = {object}; |
| 199 return RunFunction(func, context, 1, argv); | 200 return RunFunction(func, context, 1, argv); |
| 200 } | 201 } |
| 201 | 202 |
| 202 // Tests API object initialization, calling a method on the supplied APIs, and | 203 // Tests API object initialization, calling a method on the supplied APIs, and |
| 203 // triggering the callback for the request. | 204 // triggering the callback for the request. |
| 204 TEST_F(APIBindingsSystemTest, TestInitializationAndCallbacks) { | 205 TEST_F(APIBindingsSystemTest, TestInitializationAndCallbacks) { |
| 205 v8::HandleScope handle_scope(isolate()); | 206 v8::HandleScope handle_scope(isolate()); |
| 206 v8::Local<v8::Context> context = MainContext(); | 207 v8::Local<v8::Context> context = MainContext(); |
| 207 | 208 |
| 208 v8::Local<v8::Object> alpha_api = bindings_system()->CreateAPIInstance( | 209 v8::Local<v8::Object> alpha_api = |
| 209 kAlphaAPIName, context, base::Bind(&AllowAllAPIs), nullptr); | 210 bindings_system()->CreateAPIInstance(kAlphaAPIName, context, nullptr); |
| 210 ASSERT_FALSE(alpha_api.IsEmpty()); | 211 ASSERT_FALSE(alpha_api.IsEmpty()); |
| 211 v8::Local<v8::Object> beta_api = bindings_system()->CreateAPIInstance( | 212 v8::Local<v8::Object> beta_api = |
| 212 kBetaAPIName, context, base::Bind(&AllowAllAPIs), nullptr); | 213 bindings_system()->CreateAPIInstance(kBetaAPIName, context, nullptr); |
| 213 ASSERT_FALSE(beta_api.IsEmpty()); | 214 ASSERT_FALSE(beta_api.IsEmpty()); |
| 214 | 215 |
| 215 { | 216 { |
| 216 // Test a simple call -> response. | 217 // Test a simple call -> response. |
| 217 const char kTestCall[] = | 218 const char kTestCall[] = |
| 218 "obj.functionWithCallback('foo', function() {\n" | 219 "obj.functionWithCallback('foo', function() {\n" |
| 219 " this.callbackArguments = Array.from(arguments);\n" | 220 " this.callbackArguments = Array.from(arguments);\n" |
| 220 "});"; | 221 "});"; |
| 221 CallFunctionOnObject(context, alpha_api, kTestCall); | 222 CallFunctionOnObject(context, alpha_api, kTestCall); |
| 222 | 223 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 return result; | 333 return result; |
| 333 }; | 334 }; |
| 334 | 335 |
| 335 auto test_hooks = base::MakeUnique<APIBindingHooksTestDelegate>(); | 336 auto test_hooks = base::MakeUnique<APIBindingHooksTestDelegate>(); |
| 336 test_hooks->AddHandler("alpha.functionWithCallback", | 337 test_hooks->AddHandler("alpha.functionWithCallback", |
| 337 base::Bind(hook, &did_call)); | 338 base::Bind(hook, &did_call)); |
| 338 APIBindingHooks* binding_hooks = | 339 APIBindingHooks* binding_hooks = |
| 339 bindings_system()->GetHooksForAPI(kAlphaAPIName); | 340 bindings_system()->GetHooksForAPI(kAlphaAPIName); |
| 340 binding_hooks->SetDelegate(std::move(test_hooks)); | 341 binding_hooks->SetDelegate(std::move(test_hooks)); |
| 341 | 342 |
| 342 v8::Local<v8::Object> alpha_api = bindings_system()->CreateAPIInstance( | 343 v8::Local<v8::Object> alpha_api = |
| 343 kAlphaAPIName, context, base::Bind(&AllowAllAPIs), nullptr); | 344 bindings_system()->CreateAPIInstance(kAlphaAPIName, context, nullptr); |
| 344 ASSERT_FALSE(alpha_api.IsEmpty()); | 345 ASSERT_FALSE(alpha_api.IsEmpty()); |
| 345 | 346 |
| 346 { | 347 { |
| 347 // Test a simple call -> response. | 348 // Test a simple call -> response. |
| 348 const char kTestCall[] = | 349 const char kTestCall[] = |
| 349 "obj.functionWithCallback('foo', function() {\n" | 350 "obj.functionWithCallback('foo', function() {\n" |
| 350 " this.callbackArguments = Array.from(arguments);\n" | 351 " this.callbackArguments = Array.from(arguments);\n" |
| 351 "});"; | 352 "});"; |
| 352 CallFunctionOnObject(context, alpha_api, kTestCall); | 353 CallFunctionOnObject(context, alpha_api, kTestCall); |
| 353 EXPECT_TRUE(did_call); | 354 EXPECT_TRUE(did_call); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 370 " firstResult, secondResult) => {\n" | 371 " firstResult, secondResult) => {\n" |
| 371 " this.methodName = name;\n" | 372 " this.methodName = name;\n" |
| 372 // TODO(devlin): Currently, we don't actually pass anything useful in for | 373 // TODO(devlin): Currently, we don't actually pass anything useful in for |
| 373 // the |request| object. If/when we do, we should test it. | 374 // the |request| object. If/when we do, we should test it. |
| 374 " this.results = [firstResult, secondResult];\n" | 375 " this.results = [firstResult, secondResult];\n" |
| 375 " originalCallback(secondResult);\n" | 376 " originalCallback(secondResult);\n" |
| 376 " });\n" | 377 " });\n" |
| 377 "})"; | 378 "})"; |
| 378 | 379 |
| 379 APIBindingHooks* hooks = nullptr; | 380 APIBindingHooks* hooks = nullptr; |
| 380 v8::Local<v8::Object> alpha_api = bindings_system()->CreateAPIInstance( | 381 v8::Local<v8::Object> alpha_api = |
| 381 kAlphaAPIName, context, base::Bind(&AllowAllAPIs), &hooks); | 382 bindings_system()->CreateAPIInstance(kAlphaAPIName, context, &hooks); |
| 382 ASSERT_FALSE(alpha_api.IsEmpty()); | 383 ASSERT_FALSE(alpha_api.IsEmpty()); |
| 383 ASSERT_TRUE(hooks); | 384 ASSERT_TRUE(hooks); |
| 384 v8::Local<v8::Object> js_hooks = hooks->GetJSHookInterface(context); | 385 v8::Local<v8::Object> js_hooks = hooks->GetJSHookInterface(context); |
| 385 v8::Local<v8::Function> function = FunctionFromString(context, kHook); | 386 v8::Local<v8::Function> function = FunctionFromString(context, kHook); |
| 386 v8::Local<v8::Value> args[] = {js_hooks}; | 387 v8::Local<v8::Value> args[] = {js_hooks}; |
| 387 RunFunctionOnGlobal(function, context, arraysize(args), args); | 388 RunFunctionOnGlobal(function, context, arraysize(args), args); |
| 388 | 389 |
| 389 { | 390 { |
| 390 const char kTestCall[] = | 391 const char kTestCall[] = |
| 391 "obj.functionWithCallback('foo', function() {\n" | 392 "obj.functionWithCallback('foo', function() {\n" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 413 } | 414 } |
| 414 | 415 |
| 415 // Test that references to other API's types works. | 416 // Test that references to other API's types works. |
| 416 TEST_F(APIBindingsSystemTest, CrossAPIReferences) { | 417 TEST_F(APIBindingsSystemTest, CrossAPIReferences) { |
| 417 v8::HandleScope handle_scope(isolate()); | 418 v8::HandleScope handle_scope(isolate()); |
| 418 v8::Local<v8::Context> context = MainContext(); | 419 v8::Local<v8::Context> context = MainContext(); |
| 419 | 420 |
| 420 // Instantiate gamma API. Note: It's important that we haven't instantiated | 421 // Instantiate gamma API. Note: It's important that we haven't instantiated |
| 421 // alpha API yet, since this tests that we can lazily populate the type | 422 // alpha API yet, since this tests that we can lazily populate the type |
| 422 // information. | 423 // information. |
| 423 v8::Local<v8::Object> gamma_api = bindings_system()->CreateAPIInstance( | 424 v8::Local<v8::Object> gamma_api = |
| 424 kGammaAPIName, context, base::Bind(&AllowAllAPIs), nullptr); | 425 bindings_system()->CreateAPIInstance(kGammaAPIName, context, nullptr); |
| 425 ASSERT_FALSE(gamma_api.IsEmpty()); | 426 ASSERT_FALSE(gamma_api.IsEmpty()); |
| 426 | 427 |
| 427 { | 428 { |
| 428 // Test a simple call -> response. | 429 // Test a simple call -> response. |
| 429 const char kTestCall[] = "obj.functionWithExternalRef({prop1: 'foo'});"; | 430 const char kTestCall[] = "obj.functionWithExternalRef({prop1: 'foo'});"; |
| 430 CallFunctionOnObject(context, gamma_api, kTestCall); | 431 CallFunctionOnObject(context, gamma_api, kTestCall); |
| 431 ValidateLastRequest("gamma.functionWithExternalRef", "[{'prop1':'foo'}]"); | 432 ValidateLastRequest("gamma.functionWithExternalRef", "[{'prop1':'foo'}]"); |
| 432 reset_last_request(); | 433 reset_last_request(); |
| 433 } | 434 } |
| 434 } | 435 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 447 .ToChecked(); | 448 .ToChecked(); |
| 448 return ret.As<v8::Value>(); | 449 return ret.As<v8::Value>(); |
| 449 }; | 450 }; |
| 450 | 451 |
| 451 auto test_hooks = base::MakeUnique<APIBindingHooksTestDelegate>(); | 452 auto test_hooks = base::MakeUnique<APIBindingHooksTestDelegate>(); |
| 452 test_hooks->SetCustomEvent(base::Bind(create_custom_event)); | 453 test_hooks->SetCustomEvent(base::Bind(create_custom_event)); |
| 453 APIBindingHooks* binding_hooks = | 454 APIBindingHooks* binding_hooks = |
| 454 bindings_system()->GetHooksForAPI(kAlphaAPIName); | 455 bindings_system()->GetHooksForAPI(kAlphaAPIName); |
| 455 binding_hooks->SetDelegate(std::move(test_hooks)); | 456 binding_hooks->SetDelegate(std::move(test_hooks)); |
| 456 | 457 |
| 457 v8::Local<v8::Object> api = bindings_system()->CreateAPIInstance( | 458 v8::Local<v8::Object> api = |
| 458 kAlphaAPIName, context, base::Bind(&AllowAllAPIs), nullptr); | 459 bindings_system()->CreateAPIInstance(kAlphaAPIName, context, nullptr); |
| 459 | 460 |
| 460 v8::Local<v8::Value> event = | 461 v8::Local<v8::Value> event = |
| 461 GetPropertyFromObject(api, context, "alphaEvent"); | 462 GetPropertyFromObject(api, context, "alphaEvent"); |
| 462 ASSERT_TRUE(event->IsObject()); | 463 ASSERT_TRUE(event->IsObject()); |
| 463 EXPECT_EQ( | 464 EXPECT_EQ( |
| 464 "\"alpha.alphaEvent\"", | 465 "\"alpha.alphaEvent\"", |
| 465 GetStringPropertyFromObject(event.As<v8::Object>(), context, "name")); | 466 GetStringPropertyFromObject(event.As<v8::Object>(), context, "name")); |
| 466 v8::Local<v8::Value> event2 = | 467 v8::Local<v8::Value> event2 = |
| 467 GetPropertyFromObject(api, context, "alphaEvent"); | 468 GetPropertyFromObject(api, context, "alphaEvent"); |
| 468 EXPECT_EQ(event, event2); | 469 EXPECT_EQ(event, event2); |
| 469 | 470 |
| 470 v8::Local<v8::Value> other_event = | 471 v8::Local<v8::Value> other_event = |
| 471 GetPropertyFromObject(api, context, "alphaOtherEvent"); | 472 GetPropertyFromObject(api, context, "alphaOtherEvent"); |
| 472 ASSERT_TRUE(other_event->IsObject()); | 473 ASSERT_TRUE(other_event->IsObject()); |
| 473 EXPECT_EQ("\"alpha.alphaOtherEvent\"", | 474 EXPECT_EQ("\"alpha.alphaOtherEvent\"", |
| 474 GetStringPropertyFromObject(other_event.As<v8::Object>(), context, | 475 GetStringPropertyFromObject(other_event.As<v8::Object>(), context, |
| 475 "name")); | 476 "name")); |
| 476 EXPECT_NE(event, other_event); | 477 EXPECT_NE(event, other_event); |
| 477 } | 478 } |
| 478 | 479 |
| 479 } // namespace extensions | 480 } // namespace extensions |
| OLD | NEW |