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

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

Issue 2962093002: [Extensions Bindings] Add activity logging of custom handling (Closed)
Patch Set: nit 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 "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 "extensions/renderer/bindings/api_binding.h" 10 #include "extensions/renderer/bindings/api_binding.h"
11 #include "extensions/renderer/bindings/api_binding_hooks.h" 11 #include "extensions/renderer/bindings/api_binding_hooks.h"
12 #include "extensions/renderer/bindings/api_binding_hooks_test_delegate.h" 12 #include "extensions/renderer/bindings/api_binding_hooks_test_delegate.h"
13 #include "extensions/renderer/bindings/api_binding_test.h" 13 #include "extensions/renderer/bindings/api_binding_test.h"
14 #include "extensions/renderer/bindings/api_binding_test_util.h" 14 #include "extensions/renderer/bindings/api_binding_test_util.h"
15 #include "extensions/renderer/bindings/api_event_handler.h" 15 #include "extensions/renderer/bindings/api_event_handler.h"
16 #include "extensions/renderer/bindings/api_invocation_errors.h" 16 #include "extensions/renderer/bindings/api_invocation_errors.h"
17 #include "extensions/renderer/bindings/api_request_handler.h" 17 #include "extensions/renderer/bindings/api_request_handler.h"
18 #include "extensions/renderer/bindings/api_type_reference_map.h" 18 #include "extensions/renderer/bindings/api_type_reference_map.h"
19 #include "extensions/renderer/bindings/binding_access_checker.h" 19 #include "extensions/renderer/bindings/binding_access_checker.h"
20 #include "gin/arguments.h" 20 #include "gin/arguments.h"
21 #include "gin/converter.h" 21 #include "gin/converter.h"
22 #include "gin/public/context_holder.h" 22 #include "gin/public/context_holder.h"
23 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h" 24 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/WebKit/public/web/WebScopedUserGesture.h" 25 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
25 #include "v8/include/v8.h" 26 #include "v8/include/v8.h"
26 27
27 namespace extensions { 28 namespace extensions {
28 29
29 using namespace api_errors; 30 using namespace api_errors;
30 31
31 namespace { 32 namespace {
32 33
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 bool AllowAllFeatures(v8::Local<v8::Context> context, const std::string& name) { 74 bool AllowAllFeatures(v8::Local<v8::Context> context, const std::string& name) {
74 return true; 75 return true;
75 } 76 }
76 77
77 void OnEventListenersChanged(const std::string& event_name, 78 void OnEventListenersChanged(const std::string& event_name,
78 binding::EventListenersChanged change, 79 binding::EventListenersChanged change,
79 const base::DictionaryValue* filter, 80 const base::DictionaryValue* filter,
80 bool was_manual, 81 bool was_manual,
81 v8::Local<v8::Context> context) {} 82 v8::Local<v8::Context> context) {}
82 83
84 void DoNothingWithSilentRequest(
85 v8::Local<v8::Context> context,
86 const std::string& call_name,
87 const std::vector<v8::Local<v8::Value>>& arguments) {}
88
83 } // namespace 89 } // namespace
84 90
85 class APIBindingUnittest : public APIBindingTest { 91 class APIBindingUnittest : public APIBindingTest {
86 public: 92 public:
87 void OnFunctionCall(std::unique_ptr<APIRequestHandler::Request> request, 93 void OnFunctionCall(std::unique_ptr<APIRequestHandler::Request> request,
88 v8::Local<v8::Context> context) { 94 v8::Local<v8::Context> context) {
89 last_request_ = std::move(request); 95 last_request_ = std::move(request);
90 } 96 }
91 97
92 protected: 98 protected:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 void SetHooksDelegate( 149 void SetHooksDelegate(
144 std::unique_ptr<APIBindingHooksDelegate> hooks_delegate) { 150 std::unique_ptr<APIBindingHooksDelegate> hooks_delegate) {
145 binding_hooks_delegate_ = std::move(hooks_delegate); 151 binding_hooks_delegate_ = std::move(hooks_delegate);
146 ASSERT_TRUE(binding_hooks_delegate_); 152 ASSERT_TRUE(binding_hooks_delegate_);
147 } 153 }
148 154
149 void SetCreateCustomType(const APIBinding::CreateCustomType& callback) { 155 void SetCreateCustomType(const APIBinding::CreateCustomType& callback) {
150 create_custom_type_ = callback; 156 create_custom_type_ = callback;
151 } 157 }
152 158
159 void SetOnSilentRequest(const APIBinding::OnSilentRequest& callback) {
160 on_silent_request_ = callback;
161 }
162
153 void SetAvailabilityCallback( 163 void SetAvailabilityCallback(
154 const BindingAccessChecker::AvailabilityCallback& callback) { 164 const BindingAccessChecker::AvailabilityCallback& callback) {
155 availability_callback_ = callback; 165 availability_callback_ = callback;
156 } 166 }
157 167
158 void InitializeBinding() { 168 void InitializeBinding() {
159 if (!binding_hooks_) { 169 if (!binding_hooks_) {
160 binding_hooks_ = base::MakeUnique<APIBindingHooks>( 170 binding_hooks_ = base::MakeUnique<APIBindingHooks>(
161 kBindingName, binding::RunJSFunctionSync()); 171 kBindingName, binding::RunJSFunctionSync());
162 } 172 }
163 if (binding_hooks_delegate_) 173 if (binding_hooks_delegate_)
164 binding_hooks_->SetDelegate(std::move(binding_hooks_delegate_)); 174 binding_hooks_->SetDelegate(std::move(binding_hooks_delegate_));
175 if (!on_silent_request_)
176 on_silent_request_ = base::Bind(&DoNothingWithSilentRequest);
165 if (!availability_callback_) 177 if (!availability_callback_)
166 availability_callback_ = base::Bind(&AllowAllFeatures); 178 availability_callback_ = base::Bind(&AllowAllFeatures);
167 event_handler_ = base::MakeUnique<APIEventHandler>( 179 event_handler_ = base::MakeUnique<APIEventHandler>(
168 base::Bind(&RunFunctionOnGlobalAndIgnoreResult), 180 base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
169 base::Bind(&RunFunctionOnGlobalAndReturnHandle), 181 base::Bind(&RunFunctionOnGlobalAndReturnHandle),
170 base::Bind(&OnEventListenersChanged)); 182 base::Bind(&OnEventListenersChanged));
171 access_checker_ = 183 access_checker_ =
172 base::MakeUnique<BindingAccessChecker>(availability_callback_); 184 base::MakeUnique<BindingAccessChecker>(availability_callback_);
173 binding_ = base::MakeUnique<APIBinding>( 185 binding_ = base::MakeUnique<APIBinding>(
174 kBindingName, binding_functions_.get(), binding_types_.get(), 186 kBindingName, binding_functions_.get(), binding_types_.get(),
175 binding_events_.get(), binding_properties_.get(), create_custom_type_, 187 binding_events_.get(), binding_properties_.get(), create_custom_type_,
176 std::move(binding_hooks_), &type_refs_, request_handler_.get(), 188 on_silent_request_, std::move(binding_hooks_), &type_refs_,
177 event_handler_.get(), access_checker_.get()); 189 request_handler_.get(), event_handler_.get(), access_checker_.get());
178 EXPECT_EQ(!binding_types_.get(), type_refs_.empty()); 190 EXPECT_EQ(!binding_types_.get(), type_refs_.empty());
179 } 191 }
180 192
181 void ExpectPass(v8::Local<v8::Object> object, 193 void ExpectPass(v8::Local<v8::Object> object,
182 const std::string& script_source, 194 const std::string& script_source,
183 const std::string& expected_json_arguments_single_quotes, 195 const std::string& expected_json_arguments_single_quotes,
184 bool expect_callback) { 196 bool expect_callback) {
185 ExpectPass(MainContext(), object, script_source, 197 ExpectPass(MainContext(), object, script_source,
186 expected_json_arguments_single_quotes, expect_callback); 198 expected_json_arguments_single_quotes, expect_callback);
187 } 199 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 std::unique_ptr<BindingAccessChecker> access_checker_; 248 std::unique_ptr<BindingAccessChecker> access_checker_;
237 APITypeReferenceMap type_refs_; 249 APITypeReferenceMap type_refs_;
238 250
239 std::unique_ptr<base::ListValue> binding_functions_; 251 std::unique_ptr<base::ListValue> binding_functions_;
240 std::unique_ptr<base::ListValue> binding_events_; 252 std::unique_ptr<base::ListValue> binding_events_;
241 std::unique_ptr<base::ListValue> binding_types_; 253 std::unique_ptr<base::ListValue> binding_types_;
242 std::unique_ptr<base::DictionaryValue> binding_properties_; 254 std::unique_ptr<base::DictionaryValue> binding_properties_;
243 std::unique_ptr<APIBindingHooks> binding_hooks_; 255 std::unique_ptr<APIBindingHooks> binding_hooks_;
244 std::unique_ptr<APIBindingHooksDelegate> binding_hooks_delegate_; 256 std::unique_ptr<APIBindingHooksDelegate> binding_hooks_delegate_;
245 APIBinding::CreateCustomType create_custom_type_; 257 APIBinding::CreateCustomType create_custom_type_;
258 APIBinding::OnSilentRequest on_silent_request_;
246 BindingAccessChecker::AvailabilityCallback availability_callback_; 259 BindingAccessChecker::AvailabilityCallback availability_callback_;
247 260
248 DISALLOW_COPY_AND_ASSIGN(APIBindingUnittest); 261 DISALLOW_COPY_AND_ASSIGN(APIBindingUnittest);
249 }; 262 };
250 263
251 void APIBindingUnittest::RunTest(v8::Local<v8::Context> context, 264 void APIBindingUnittest::RunTest(v8::Local<v8::Context> context,
252 v8::Local<v8::Object> object, 265 v8::Local<v8::Object> object,
253 const std::string& script_source, 266 const std::string& script_source,
254 bool should_pass, 267 bool should_pass,
255 const std::string& expected_json_arguments, 268 const std::string& expected_json_arguments,
(...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context); 1307 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context);
1295 1308
1296 // The extra property should be present on the binding object. 1309 // The extra property should be present on the binding object.
1297 EXPECT_EQ("42", GetStringPropertyFromObject(binding_object, context, 1310 EXPECT_EQ("42", GetStringPropertyFromObject(binding_object, context,
1298 "hookedProperty")); 1311 "hookedProperty"));
1299 // Sanity check: other values should still be there. 1312 // Sanity check: other values should still be there.
1300 EXPECT_EQ("function", 1313 EXPECT_EQ("function",
1301 GetStringPropertyFromObject(binding_object, context, "oneString")); 1314 GetStringPropertyFromObject(binding_object, context, "oneString"));
1302 } 1315 }
1303 1316
1317 // Test that running hooks returning different results correctly sends requests
1318 // or notifies of silent requests.
1319 TEST_F(APIBindingUnittest, TestSendingRequestsAndSilentRequestsWithHooks) {
1320 SetFunctions(
1321 "[{"
1322 " 'name': 'modifyArgs',"
1323 " 'parameters': []"
1324 "}, {"
1325 " 'name': 'invalidInvocation',"
1326 " 'parameters': []"
1327 "}, {"
1328 " 'name': 'throwException',"
1329 " 'parameters': []"
1330 "}, {"
1331 " 'name': 'dontHandle',"
1332 " 'parameters': []"
1333 "}, {"
1334 " 'name': 'handle',"
1335 " 'parameters': []"
1336 "}, {"
1337 " 'name': 'handleAndSendRequest',"
1338 " 'parameters': []"
1339 "}, {"
1340 " 'name': 'handleWithArgs',"
1341 " 'parameters': [{"
1342 " 'name': 'first',"
1343 " 'type': 'string'"
1344 " }, {"
1345 " 'name': 'second',"
1346 " 'type': 'integer'"
1347 " }]"
1348 "}]");
1349
1350 using RequestResult = APIBindingHooks::RequestResult;
1351
1352 auto basic_handler = [](RequestResult::ResultCode code, const APISignature*,
1353 v8::Local<v8::Context> context,
1354 std::vector<v8::Local<v8::Value>>* arguments,
1355 const APITypeReferenceMap& map) {
1356 return RequestResult(code);
1357 };
1358
1359 auto hooks = base::MakeUnique<APIBindingHooksTestDelegate>();
1360 hooks->AddHandler(
1361 "test.modifyArgs",
1362 base::Bind(basic_handler, RequestResult::ARGUMENTS_UPDATED));
1363 hooks->AddHandler(
1364 "test.invalidInvocation",
1365 base::Bind(basic_handler, RequestResult::INVALID_INVOCATION));
1366 hooks->AddHandler("test.dontHandle",
1367 base::Bind(basic_handler, RequestResult::NOT_HANDLED));
1368 hooks->AddHandler("test.handle",
1369 base::Bind(basic_handler, RequestResult::HANDLED));
1370 hooks->AddHandler(
1371 "test.throwException",
1372 base::Bind([](const APISignature*, v8::Local<v8::Context> context,
1373 std::vector<v8::Local<v8::Value>>* arguments,
1374 const APITypeReferenceMap& map) {
1375 context->GetIsolate()->ThrowException(
1376 gin::StringToV8(context->GetIsolate(), "some error"));
1377 return RequestResult(RequestResult::THROWN);
1378 }));
1379 hooks->AddHandler(
1380 "test.handleWithArgs",
1381 base::Bind([](const APISignature*, v8::Local<v8::Context> context,
1382 std::vector<v8::Local<v8::Value>>* arguments,
1383 const APITypeReferenceMap& map) {
1384 arguments->push_back(v8::Integer::New(context->GetIsolate(), 42));
1385 return RequestResult(RequestResult::HANDLED);
1386 }));
1387
1388 auto handle_and_send_request =
1389 [](APIRequestHandler* handler, const APISignature*,
1390 v8::Local<v8::Context> context,
1391 std::vector<v8::Local<v8::Value>>* arguments,
1392 const APITypeReferenceMap& map) {
1393 handler->StartRequest(
1394 context, "test.handleAndSendRequest",
1395 base::MakeUnique<base::ListValue>(), v8::Local<v8::Function>(),
1396 v8::Local<v8::Function>(), binding::RequestThread::UI);
1397 return RequestResult(RequestResult::HANDLED);
1398 };
1399 hooks->AddHandler("test.handleAndSendRequest",
1400 base::Bind(handle_and_send_request, request_handler()));
1401
1402 SetHooksDelegate(std::move(hooks));
1403
1404 auto on_silent_request =
1405 [](base::Optional<std::string>* name_out,
1406 base::Optional<std::vector<std::string>>* args_out,
1407 v8::Local<v8::Context> context, const std::string& call_name,
1408 const std::vector<v8::Local<v8::Value>>& arguments) {
1409 *name_out = call_name;
1410 *args_out = std::vector<std::string>();
1411 (*args_out)->reserve(arguments.size());
1412 for (const auto& arg : arguments)
1413 (*args_out)->push_back(V8ToString(arg, context));
1414 };
1415 base::Optional<std::string> silent_request;
1416 base::Optional<std::vector<std::string>> request_arguments;
1417 SetOnSilentRequest(
1418 base::Bind(on_silent_request, &silent_request, &request_arguments));
1419
1420 InitializeBinding();
1421
1422 v8::HandleScope handle_scope(isolate());
1423 v8::Local<v8::Context> context = MainContext();
1424
1425 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context);
1426
1427 auto call_api_method = [binding_object, context](
1428 base::StringPiece name,
1429 base::StringPiece string_args) {
1430 v8::Local<v8::Function> call = FunctionFromString(
1431 context, base::StringPrintf("(function(binding) { binding.%s(%s); })",
1432 name.data(), string_args.data()));
1433 v8::Local<v8::Value> args[] = {binding_object};
1434 v8::TryCatch try_catch(context->GetIsolate());
1435 // The throwException call will throw an exception; ignore it.
1436 ignore_result(call->Call(context, v8::Undefined(context->GetIsolate()),
1437 arraysize(args), args));
1438 };
1439
1440 call_api_method("modifyArgs", "");
1441 ASSERT_TRUE(last_request());
1442 EXPECT_EQ("test.modifyArgs", last_request()->method_name);
1443 EXPECT_FALSE(silent_request);
1444 reset_last_request();
1445 silent_request.reset();
1446 request_arguments.reset();
1447
1448 call_api_method("invalidInvocation", "");
1449 EXPECT_FALSE(last_request());
1450 EXPECT_FALSE(silent_request);
1451 reset_last_request();
1452 silent_request.reset();
1453 request_arguments.reset();
1454
1455 call_api_method("throwException", "");
1456 EXPECT_FALSE(last_request());
1457 EXPECT_FALSE(silent_request);
1458 reset_last_request();
1459 silent_request.reset();
1460 request_arguments.reset();
1461
1462 call_api_method("dontHandle", "");
1463 ASSERT_TRUE(last_request());
1464 EXPECT_EQ("test.dontHandle", last_request()->method_name);
1465 EXPECT_FALSE(silent_request);
1466 reset_last_request();
1467 silent_request.reset();
1468 request_arguments.reset();
1469
1470 call_api_method("handle", "");
1471 EXPECT_FALSE(last_request());
1472 ASSERT_TRUE(silent_request);
1473 EXPECT_EQ("test.handle", *silent_request);
1474 ASSERT_TRUE(request_arguments);
1475 EXPECT_TRUE(request_arguments->empty());
1476 reset_last_request();
1477 silent_request.reset();
1478 request_arguments.reset();
1479
1480 call_api_method("handleAndSendRequest", "");
1481 ASSERT_TRUE(last_request());
1482 EXPECT_EQ("test.handleAndSendRequest", last_request()->method_name);
1483 EXPECT_FALSE(silent_request);
1484 reset_last_request();
1485 silent_request.reset();
1486 request_arguments.reset();
1487
1488 call_api_method("handleWithArgs", "'str'");
1489 EXPECT_FALSE(last_request());
1490 ASSERT_TRUE(silent_request);
1491 ASSERT_EQ("test.handleWithArgs", *silent_request);
1492 ASSERT_TRUE(request_arguments);
1493 EXPECT_THAT(
1494 *request_arguments,
1495 testing::ElementsAre("\"str\"", "42")); // 42 was added by the handler.
1496 reset_last_request();
1497 silent_request.reset();
1498 request_arguments.reset();
1499 }
1500
1304 } // namespace extensions 1501 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/bindings/api_binding.cc ('k') | extensions/renderer/bindings/api_bindings_system.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698