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

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

Issue 2962093002: [Extensions Bindings] Add activity logging of custom handling (Closed)
Patch Set: . 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"
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 bool AllowAllFeatures(v8::Local<v8::Context> context, const std::string& name) { 73 bool AllowAllFeatures(v8::Local<v8::Context> context, const std::string& name) {
74 return true; 74 return true;
75 } 75 }
76 76
77 void OnEventListenersChanged(const std::string& event_name, 77 void OnEventListenersChanged(const std::string& event_name,
78 binding::EventListenersChanged change, 78 binding::EventListenersChanged change,
79 const base::DictionaryValue* filter, 79 const base::DictionaryValue* filter,
80 bool was_manual, 80 bool was_manual,
81 v8::Local<v8::Context> context) {} 81 v8::Local<v8::Context> context) {}
82 82
83 void DoNothingWithSilentRequest(
84 v8::Local<v8::Context> context,
85 const std::string& call_name,
86 const std::vector<v8::Local<v8::Value>>& arguments) {}
87
83 } // namespace 88 } // namespace
84 89
85 class APIBindingUnittest : public APIBindingTest { 90 class APIBindingUnittest : public APIBindingTest {
86 public: 91 public:
87 void OnFunctionCall(std::unique_ptr<APIRequestHandler::Request> request, 92 void OnFunctionCall(std::unique_ptr<APIRequestHandler::Request> request,
88 v8::Local<v8::Context> context) { 93 v8::Local<v8::Context> context) {
89 last_request_ = std::move(request); 94 last_request_ = std::move(request);
90 } 95 }
91 96
92 protected: 97 protected:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 void SetHooksDelegate( 148 void SetHooksDelegate(
144 std::unique_ptr<APIBindingHooksDelegate> hooks_delegate) { 149 std::unique_ptr<APIBindingHooksDelegate> hooks_delegate) {
145 binding_hooks_delegate_ = std::move(hooks_delegate); 150 binding_hooks_delegate_ = std::move(hooks_delegate);
146 ASSERT_TRUE(binding_hooks_delegate_); 151 ASSERT_TRUE(binding_hooks_delegate_);
147 } 152 }
148 153
149 void SetCreateCustomType(const APIBinding::CreateCustomType& callback) { 154 void SetCreateCustomType(const APIBinding::CreateCustomType& callback) {
150 create_custom_type_ = callback; 155 create_custom_type_ = callback;
151 } 156 }
152 157
158 void SetOnSilentRequest(const APIBinding::OnSilentRequest& callback) {
159 on_silent_request_ = callback;
160 }
161
153 void SetAvailabilityCallback( 162 void SetAvailabilityCallback(
154 const BindingAccessChecker::AvailabilityCallback& callback) { 163 const BindingAccessChecker::AvailabilityCallback& callback) {
155 availability_callback_ = callback; 164 availability_callback_ = callback;
156 } 165 }
157 166
158 void InitializeBinding() { 167 void InitializeBinding() {
159 if (!binding_hooks_) { 168 if (!binding_hooks_) {
160 binding_hooks_ = base::MakeUnique<APIBindingHooks>( 169 binding_hooks_ = base::MakeUnique<APIBindingHooks>(
161 kBindingName, binding::RunJSFunctionSync()); 170 kBindingName, binding::RunJSFunctionSync());
162 } 171 }
163 if (binding_hooks_delegate_) 172 if (binding_hooks_delegate_)
164 binding_hooks_->SetDelegate(std::move(binding_hooks_delegate_)); 173 binding_hooks_->SetDelegate(std::move(binding_hooks_delegate_));
174 if (!on_silent_request_)
175 on_silent_request_ = base::Bind(&DoNothingWithSilentRequest);
165 if (!availability_callback_) 176 if (!availability_callback_)
166 availability_callback_ = base::Bind(&AllowAllFeatures); 177 availability_callback_ = base::Bind(&AllowAllFeatures);
167 event_handler_ = base::MakeUnique<APIEventHandler>( 178 event_handler_ = base::MakeUnique<APIEventHandler>(
168 base::Bind(&RunFunctionOnGlobalAndIgnoreResult), 179 base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
169 base::Bind(&RunFunctionOnGlobalAndReturnHandle), 180 base::Bind(&RunFunctionOnGlobalAndReturnHandle),
170 base::Bind(&OnEventListenersChanged)); 181 base::Bind(&OnEventListenersChanged));
171 access_checker_ = 182 access_checker_ =
172 base::MakeUnique<BindingAccessChecker>(availability_callback_); 183 base::MakeUnique<BindingAccessChecker>(availability_callback_);
173 binding_ = base::MakeUnique<APIBinding>( 184 binding_ = base::MakeUnique<APIBinding>(
174 kBindingName, binding_functions_.get(), binding_types_.get(), 185 kBindingName, binding_functions_.get(), binding_types_.get(),
175 binding_events_.get(), binding_properties_.get(), create_custom_type_, 186 binding_events_.get(), binding_properties_.get(), create_custom_type_,
176 std::move(binding_hooks_), &type_refs_, request_handler_.get(), 187 on_silent_request_, std::move(binding_hooks_), &type_refs_,
177 event_handler_.get(), access_checker_.get()); 188 request_handler_.get(), event_handler_.get(), access_checker_.get());
178 EXPECT_EQ(!binding_types_.get(), type_refs_.empty()); 189 EXPECT_EQ(!binding_types_.get(), type_refs_.empty());
179 } 190 }
180 191
181 void ExpectPass(v8::Local<v8::Object> object, 192 void ExpectPass(v8::Local<v8::Object> object,
182 const std::string& script_source, 193 const std::string& script_source,
183 const std::string& expected_json_arguments_single_quotes, 194 const std::string& expected_json_arguments_single_quotes,
184 bool expect_callback) { 195 bool expect_callback) {
185 ExpectPass(MainContext(), object, script_source, 196 ExpectPass(MainContext(), object, script_source,
186 expected_json_arguments_single_quotes, expect_callback); 197 expected_json_arguments_single_quotes, expect_callback);
187 } 198 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 std::unique_ptr<BindingAccessChecker> access_checker_; 247 std::unique_ptr<BindingAccessChecker> access_checker_;
237 APITypeReferenceMap type_refs_; 248 APITypeReferenceMap type_refs_;
238 249
239 std::unique_ptr<base::ListValue> binding_functions_; 250 std::unique_ptr<base::ListValue> binding_functions_;
240 std::unique_ptr<base::ListValue> binding_events_; 251 std::unique_ptr<base::ListValue> binding_events_;
241 std::unique_ptr<base::ListValue> binding_types_; 252 std::unique_ptr<base::ListValue> binding_types_;
242 std::unique_ptr<base::DictionaryValue> binding_properties_; 253 std::unique_ptr<base::DictionaryValue> binding_properties_;
243 std::unique_ptr<APIBindingHooks> binding_hooks_; 254 std::unique_ptr<APIBindingHooks> binding_hooks_;
244 std::unique_ptr<APIBindingHooksDelegate> binding_hooks_delegate_; 255 std::unique_ptr<APIBindingHooksDelegate> binding_hooks_delegate_;
245 APIBinding::CreateCustomType create_custom_type_; 256 APIBinding::CreateCustomType create_custom_type_;
257 APIBinding::OnSilentRequest on_silent_request_;
246 BindingAccessChecker::AvailabilityCallback availability_callback_; 258 BindingAccessChecker::AvailabilityCallback availability_callback_;
247 259
248 DISALLOW_COPY_AND_ASSIGN(APIBindingUnittest); 260 DISALLOW_COPY_AND_ASSIGN(APIBindingUnittest);
249 }; 261 };
250 262
251 void APIBindingUnittest::RunTest(v8::Local<v8::Context> context, 263 void APIBindingUnittest::RunTest(v8::Local<v8::Context> context,
252 v8::Local<v8::Object> object, 264 v8::Local<v8::Object> object,
253 const std::string& script_source, 265 const std::string& script_source,
254 bool should_pass, 266 bool should_pass,
255 const std::string& expected_json_arguments, 267 const std::string& expected_json_arguments,
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context); 1284 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context);
1273 1285
1274 // The extra property should be present on the binding object. 1286 // The extra property should be present on the binding object.
1275 EXPECT_EQ("42", GetStringPropertyFromObject(binding_object, context, 1287 EXPECT_EQ("42", GetStringPropertyFromObject(binding_object, context,
1276 "hookedProperty")); 1288 "hookedProperty"));
1277 // Sanity check: other values should still be there. 1289 // Sanity check: other values should still be there.
1278 EXPECT_EQ("function", 1290 EXPECT_EQ("function",
1279 GetStringPropertyFromObject(binding_object, context, "oneString")); 1291 GetStringPropertyFromObject(binding_object, context, "oneString"));
1280 } 1292 }
1281 1293
1294 // Test that running hooks returning different results correctly sends requests
1295 // or notifies of silent requests.
1296 TEST_F(APIBindingUnittest, TestSendingRequestsAndSilentRequestsWithHooks) {
1297 SetFunctions(
1298 "[{"
1299 " 'name': 'modifyArgs',"
1300 " 'parameters': []"
1301 "}, {"
1302 " 'name': 'invalidInvocation',"
1303 " 'parameters': []"
1304 "}, {"
1305 " 'name': 'throwException',"
1306 " 'parameters': []"
1307 "}, {"
1308 " 'name': 'dontHandle',"
1309 " 'parameters': []"
1310 "}, {"
1311 " 'name': 'handle',"
1312 " 'parameters': []"
1313 "}, {"
1314 " 'name': 'handleAndSendRequest',"
1315 " 'parameters': []"
1316 "}, {"
1317 " 'name': 'handleWithArgs',"
1318 " 'parameters': [{"
1319 " 'name': 'first',"
1320 " 'type': 'string'"
1321 " }, {"
1322 " 'name': 'second',"
1323 " 'type': 'integer'"
1324 " }]"
1325 "}]");
1326
1327 using RequestResult = APIBindingHooks::RequestResult;
1328
1329 auto basic_handler = [](RequestResult::ResultCode code, const APISignature*,
1330 v8::Local<v8::Context> context,
1331 std::vector<v8::Local<v8::Value>>* arguments,
1332 const APITypeReferenceMap& map) {
1333 return RequestResult(code);
1334 };
1335
1336 auto hooks = base::MakeUnique<APIBindingHooksTestDelegate>();
1337 hooks->AddHandler(
1338 "test.modifyArgs",
1339 base::Bind(basic_handler, RequestResult::ARGUMENTS_UPDATED));
1340 hooks->AddHandler(
1341 "test.invalidInvocation",
1342 base::Bind(basic_handler, RequestResult::INVALID_INVOCATION));
1343 hooks->AddHandler("test.dontHandle",
1344 base::Bind(basic_handler, RequestResult::NOT_HANDLED));
1345 hooks->AddHandler("test.handle",
1346 base::Bind(basic_handler, RequestResult::HANDLED));
1347 hooks->AddHandler(
1348 "test.throwException",
1349 base::Bind([](const APISignature*, v8::Local<v8::Context> context,
1350 std::vector<v8::Local<v8::Value>>* arguments,
1351 const APITypeReferenceMap& map) {
1352 context->GetIsolate()->ThrowException(
1353 gin::StringToV8(context->GetIsolate(), "some error"));
1354 return RequestResult(RequestResult::THROWN);
1355 }));
1356 hooks->AddHandler(
1357 "test.handleWithArgs",
1358 base::Bind([](const APISignature*, v8::Local<v8::Context> context,
1359 std::vector<v8::Local<v8::Value>>* arguments,
1360 const APITypeReferenceMap& map) {
1361 arguments->push_back(v8::Integer::New(context->GetIsolate(), 42));
1362 return RequestResult(RequestResult::HANDLED);
1363 }));
1364
1365 auto handle_and_send_request =
1366 [](APIRequestHandler* handler, const APISignature*,
1367 v8::Local<v8::Context> context,
1368 std::vector<v8::Local<v8::Value>>* arguments,
1369 const APITypeReferenceMap& map) {
1370 handler->StartRequest(
1371 context, "test.handleAndSendRequest",
1372 base::MakeUnique<base::ListValue>(), v8::Local<v8::Function>(),
1373 v8::Local<v8::Function>(), binding::RequestThread::UI);
1374 return RequestResult(RequestResult::HANDLED);
1375 };
1376 hooks->AddHandler("test.handleAndSendRequest",
1377 base::Bind(handle_and_send_request, request_handler()));
1378
1379 SetHooksDelegate(std::move(hooks));
1380
1381 auto on_silent_request =
1382 [](base::Optional<std::string>* name_out,
1383 base::Optional<std::vector<std::string>>* args_out,
1384 v8::Local<v8::Context> context, const std::string& call_name,
1385 const std::vector<v8::Local<v8::Value>>& arguments) {
1386 *name_out = call_name;
1387 *args_out = std::vector<std::string>();
1388 (*args_out)->reserve(arguments.size());
1389 for (const auto& arg : arguments)
1390 (*args_out)->push_back(V8ToString(arg, context));
1391 };
1392 base::Optional<std::string> silent_request;
1393 base::Optional<std::vector<std::string>> request_arguments;
1394 SetOnSilentRequest(
1395 base::Bind(on_silent_request, &silent_request, &request_arguments));
1396
1397 InitializeBinding();
1398
1399 v8::HandleScope handle_scope(isolate());
1400 v8::Local<v8::Context> context = MainContext();
1401
1402 v8::Local<v8::Object> binding_object = binding()->CreateInstance(context);
1403
1404 auto call_api_method = [binding_object, context](
1405 base::StringPiece name,
1406 base::StringPiece string_args) {
1407 v8::Local<v8::Function> call = FunctionFromString(
1408 context, base::StringPrintf("(function(binding) { binding.%s(%s); })",
1409 name.data(), string_args.data()));
1410 v8::Local<v8::Value> args[] = {binding_object};
1411 // The throwException call will throw an exception; ignore it.
jbroman 2017/07/06 20:48:45 don't you still need to catch the exception?
Devlin 2017/07/10 22:28:03 Hmm... probably should be. Done.
1412 ignore_result(call->Call(context, v8::Undefined(context->GetIsolate()),
1413 arraysize(args), args));
1414 };
1415
1416 call_api_method("modifyArgs", "");
1417 ASSERT_TRUE(last_request());
1418 EXPECT_EQ("test.modifyArgs", last_request()->method_name);
1419 EXPECT_FALSE(silent_request);
1420 reset_last_request();
1421 silent_request.reset();
1422 request_arguments.reset();
1423
1424 call_api_method("invalidInvocation", "");
1425 EXPECT_FALSE(last_request());
1426 EXPECT_FALSE(silent_request);
1427 reset_last_request();
1428 silent_request.reset();
1429 request_arguments.reset();
1430
1431 call_api_method("throwException", "");
1432 EXPECT_FALSE(last_request());
1433 EXPECT_FALSE(silent_request);
1434 reset_last_request();
1435 silent_request.reset();
1436 request_arguments.reset();
1437
1438 call_api_method("dontHandle", "");
1439 ASSERT_TRUE(last_request());
1440 EXPECT_EQ("test.dontHandle", last_request()->method_name);
1441 EXPECT_FALSE(silent_request);
1442 reset_last_request();
1443 silent_request.reset();
1444 request_arguments.reset();
1445
1446 call_api_method("handle", "");
1447 EXPECT_FALSE(last_request());
1448 ASSERT_TRUE(silent_request);
1449 EXPECT_EQ("test.handle", *silent_request);
1450 ASSERT_TRUE(request_arguments);
1451 EXPECT_TRUE(request_arguments->empty());
1452 reset_last_request();
1453 silent_request.reset();
1454 request_arguments.reset();
1455
1456 call_api_method("handleAndSendRequest", "");
1457 ASSERT_TRUE(last_request());
1458 EXPECT_EQ("test.handleAndSendRequest", last_request()->method_name);
1459 EXPECT_FALSE(silent_request);
1460 reset_last_request();
1461 silent_request.reset();
1462 request_arguments.reset();
1463
1464 call_api_method("handleWithArgs", "'str'");
1465 EXPECT_FALSE(last_request());
1466 ASSERT_TRUE(silent_request);
1467 ASSERT_EQ("test.handleWithArgs", *silent_request);
1468 ASSERT_TRUE(request_arguments);
1469 ASSERT_EQ(2u, request_arguments->size());
jbroman 2017/07/06 20:48:45 nit: Or this and the following two could be (using
Devlin 2017/07/10 22:28:03 Sure, done.
1470 EXPECT_EQ("\"str\"", request_arguments->at(0));
1471 EXPECT_EQ("42", request_arguments->at(1)); // 42 was added by the handler.
1472 reset_last_request();
1473 silent_request.reset();
1474 request_arguments.reset();
1475 }
1476
1282 } // namespace extensions 1477 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698