| 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/optional.h" | 6 #include "base/optional.h" |
| 7 #include "base/values.h" | 7 #include "base/values.h" |
| 8 #include "extensions/renderer/api_binding_test.h" | 8 #include "extensions/renderer/api_binding_test.h" |
| 9 #include "extensions/renderer/api_binding_test_util.h" | 9 #include "extensions/renderer/api_binding_test_util.h" |
| 10 #include "extensions/renderer/api_request_handler.h" | 10 #include "extensions/renderer/api_request_handler.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest); | 51 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest); |
| 52 }; | 52 }; |
| 53 | 53 |
| 54 // Tests adding a request to the request handler, and then triggering the | 54 // Tests adding a request to the request handler, and then triggering the |
| 55 // response. | 55 // response. |
| 56 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) { | 56 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) { |
| 57 v8::HandleScope handle_scope(isolate()); | 57 v8::HandleScope handle_scope(isolate()); |
| 58 v8::Local<v8::Context> context = ContextLocal(); | 58 v8::Local<v8::Context> context = ContextLocal(); |
| 59 | 59 |
| 60 APIRequestHandler request_handler( | 60 APIRequestHandler request_handler( |
| 61 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this))); | 61 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 62 APILastError(APILastError::GetParent())); |
| 62 | 63 |
| 63 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); | 64 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); |
| 64 | 65 |
| 65 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); | 66 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); |
| 66 ASSERT_FALSE(function.IsEmpty()); | 67 ASSERT_FALSE(function.IsEmpty()); |
| 67 | 68 |
| 68 int request_id = request_handler.AddPendingRequest(isolate(), function, | 69 int request_id = request_handler.AddPendingRequest(isolate(), function, |
| 69 context, ArgumentList()); | 70 context, ArgumentList()); |
| 70 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 71 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 71 testing::UnorderedElementsAre(request_id)); | 72 testing::UnorderedElementsAre(request_id)); |
| 72 | 73 |
| 73 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; | 74 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; |
| 74 std::unique_ptr<base::ListValue> response_arguments = | 75 std::unique_ptr<base::ListValue> response_arguments = |
| 75 ListValueFromString(kArguments); | 76 ListValueFromString(kArguments); |
| 76 ASSERT_TRUE(response_arguments); | 77 ASSERT_TRUE(response_arguments); |
| 77 request_handler.CompleteRequest(request_id, *response_arguments); | 78 request_handler.CompleteRequest(request_id, *response_arguments, |
| 79 std::string()); |
| 78 | 80 |
| 79 EXPECT_TRUE(did_run_js()); | 81 EXPECT_TRUE(did_run_js()); |
| 80 EXPECT_EQ(ReplaceSingleQuotes(kArguments), | 82 EXPECT_EQ(ReplaceSingleQuotes(kArguments), |
| 81 GetStringPropertyFromObject(context->Global(), context, "result")); | 83 GetStringPropertyFromObject(context->Global(), context, "result")); |
| 82 | 84 |
| 83 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); | 85 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); |
| 84 } | 86 } |
| 85 | 87 |
| 86 // Tests that trying to run non-existent or invalided requests is a no-op. | 88 // Tests that trying to run non-existent or invalided requests is a no-op. |
| 87 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) { | 89 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) { |
| 88 v8::HandleScope handle_scope(isolate()); | 90 v8::HandleScope handle_scope(isolate()); |
| 89 v8::Local<v8::Context> context = ContextLocal(); | 91 v8::Local<v8::Context> context = ContextLocal(); |
| 90 | 92 |
| 91 APIRequestHandler request_handler( | 93 APIRequestHandler request_handler( |
| 92 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this))); | 94 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 95 APILastError(APILastError::GetParent())); |
| 93 | 96 |
| 94 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); | 97 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); |
| 95 ASSERT_FALSE(function.IsEmpty()); | 98 ASSERT_FALSE(function.IsEmpty()); |
| 96 | 99 |
| 97 int request_id = request_handler.AddPendingRequest(isolate(), function, | 100 int request_id = request_handler.AddPendingRequest(isolate(), function, |
| 98 context, ArgumentList()); | 101 context, ArgumentList()); |
| 99 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 102 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 100 testing::UnorderedElementsAre(request_id)); | 103 testing::UnorderedElementsAre(request_id)); |
| 101 | 104 |
| 102 std::unique_ptr<base::ListValue> response_arguments = | 105 std::unique_ptr<base::ListValue> response_arguments = |
| 103 ListValueFromString("['foo']"); | 106 ListValueFromString("['foo']"); |
| 104 ASSERT_TRUE(response_arguments); | 107 ASSERT_TRUE(response_arguments); |
| 105 | 108 |
| 106 // Try running with a non-existent request id. | 109 // Try running with a non-existent request id. |
| 107 int fake_request_id = 42; | 110 int fake_request_id = 42; |
| 108 request_handler.CompleteRequest(fake_request_id, *response_arguments); | 111 request_handler.CompleteRequest(fake_request_id, *response_arguments, |
| 112 std::string()); |
| 109 EXPECT_FALSE(did_run_js()); | 113 EXPECT_FALSE(did_run_js()); |
| 110 | 114 |
| 111 // Try running with a request from an invalidated context. | 115 // Try running with a request from an invalidated context. |
| 112 request_handler.InvalidateContext(context); | 116 request_handler.InvalidateContext(context); |
| 113 request_handler.CompleteRequest(request_id, *response_arguments); | 117 request_handler.CompleteRequest(request_id, *response_arguments, |
| 118 std::string()); |
| 114 EXPECT_FALSE(did_run_js()); | 119 EXPECT_FALSE(did_run_js()); |
| 115 } | 120 } |
| 116 | 121 |
| 117 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) { | 122 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) { |
| 118 v8::HandleScope handle_scope(isolate()); | 123 v8::HandleScope handle_scope(isolate()); |
| 119 v8::Local<v8::Context> context_a = ContextLocal(); | 124 v8::Local<v8::Context> context_a = ContextLocal(); |
| 120 v8::Local<v8::Context> context_b = v8::Context::New(isolate()); | 125 v8::Local<v8::Context> context_b = v8::Context::New(isolate()); |
| 121 gin::ContextHolder holder_b(isolate()); | 126 gin::ContextHolder holder_b(isolate()); |
| 122 holder_b.SetContext(context_b); | 127 holder_b.SetContext(context_b); |
| 123 | 128 |
| 124 APIRequestHandler request_handler( | 129 APIRequestHandler request_handler( |
| 125 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this))); | 130 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 131 APILastError(APILastError::GetParent())); |
| 126 | 132 |
| 127 // By having both different arguments and different behaviors in the | 133 // By having both different arguments and different behaviors in the |
| 128 // callbacks, we can easily verify that the right function is called in the | 134 // callbacks, we can easily verify that the right function is called in the |
| 129 // right context. | 135 // right context. |
| 130 v8::Local<v8::Function> function_a = FunctionFromString( | 136 v8::Local<v8::Function> function_a = FunctionFromString( |
| 131 context_a, "(function(res) { this.result = res + 'alpha'; })"); | 137 context_a, "(function(res) { this.result = res + 'alpha'; })"); |
| 132 v8::Local<v8::Function> function_b = FunctionFromString( | 138 v8::Local<v8::Function> function_b = FunctionFromString( |
| 133 context_b, "(function(res) { this.result = res + 'beta'; })"); | 139 context_b, "(function(res) { this.result = res + 'beta'; })"); |
| 134 | 140 |
| 135 int request_a = request_handler.AddPendingRequest(isolate(), function_a, | 141 int request_a = request_handler.AddPendingRequest(isolate(), function_a, |
| 136 context_a, ArgumentList()); | 142 context_a, ArgumentList()); |
| 137 int request_b = request_handler.AddPendingRequest(isolate(), function_b, | 143 int request_b = request_handler.AddPendingRequest(isolate(), function_b, |
| 138 context_b, ArgumentList()); | 144 context_b, ArgumentList()); |
| 139 | 145 |
| 140 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 146 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 141 testing::UnorderedElementsAre(request_a, request_b)); | 147 testing::UnorderedElementsAre(request_a, request_b)); |
| 142 | 148 |
| 143 std::unique_ptr<base::ListValue> response_a = | 149 std::unique_ptr<base::ListValue> response_a = |
| 144 ListValueFromString("['response_a:']"); | 150 ListValueFromString("['response_a:']"); |
| 145 ASSERT_TRUE(response_a); | 151 ASSERT_TRUE(response_a); |
| 146 | 152 |
| 147 request_handler.CompleteRequest(request_a, *response_a); | 153 request_handler.CompleteRequest(request_a, *response_a, std::string()); |
| 148 EXPECT_TRUE(did_run_js()); | 154 EXPECT_TRUE(did_run_js()); |
| 149 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 155 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 150 testing::UnorderedElementsAre(request_b)); | 156 testing::UnorderedElementsAre(request_b)); |
| 151 | 157 |
| 152 EXPECT_EQ( | 158 EXPECT_EQ( |
| 153 ReplaceSingleQuotes("'response_a:alpha'"), | 159 ReplaceSingleQuotes("'response_a:alpha'"), |
| 154 GetStringPropertyFromObject(context_a->Global(), context_a, "result")); | 160 GetStringPropertyFromObject(context_a->Global(), context_a, "result")); |
| 155 | 161 |
| 156 std::unique_ptr<base::ListValue> response_b = | 162 std::unique_ptr<base::ListValue> response_b = |
| 157 ListValueFromString("['response_b:']"); | 163 ListValueFromString("['response_b:']"); |
| 158 ASSERT_TRUE(response_b); | 164 ASSERT_TRUE(response_b); |
| 159 | 165 |
| 160 request_handler.CompleteRequest(request_b, *response_b); | 166 request_handler.CompleteRequest(request_b, *response_b, std::string()); |
| 161 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); | 167 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); |
| 162 | 168 |
| 163 EXPECT_EQ( | 169 EXPECT_EQ( |
| 164 ReplaceSingleQuotes("'response_b:beta'"), | 170 ReplaceSingleQuotes("'response_b:beta'"), |
| 165 GetStringPropertyFromObject(context_b->Global(), context_b, "result")); | 171 GetStringPropertyFromObject(context_b->Global(), context_b, "result")); |
| 166 } | 172 } |
| 167 | 173 |
| 168 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) { | 174 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) { |
| 169 v8::HandleScope handle_scope(isolate()); | 175 v8::HandleScope handle_scope(isolate()); |
| 170 v8::Local<v8::Context> context = ContextLocal(); | 176 v8::Local<v8::Context> context = ContextLocal(); |
| 171 | 177 |
| 172 APIRequestHandler request_handler( | 178 APIRequestHandler request_handler( |
| 173 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this))); | 179 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 180 APILastError(APILastError::GetParent())); |
| 174 | 181 |
| 175 ArgumentList custom_callback_args = { | 182 ArgumentList custom_callback_args = { |
| 176 gin::StringToV8(isolate(), "to"), gin::StringToV8(isolate(), "be"), | 183 gin::StringToV8(isolate(), "to"), gin::StringToV8(isolate(), "be"), |
| 177 }; | 184 }; |
| 178 | 185 |
| 179 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); | 186 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); |
| 180 ASSERT_FALSE(function.IsEmpty()); | 187 ASSERT_FALSE(function.IsEmpty()); |
| 181 | 188 |
| 182 int request_id = request_handler.AddPendingRequest( | 189 int request_id = request_handler.AddPendingRequest( |
| 183 isolate(), function, context, custom_callback_args); | 190 isolate(), function, context, custom_callback_args); |
| 184 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 191 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 185 testing::UnorderedElementsAre(request_id)); | 192 testing::UnorderedElementsAre(request_id)); |
| 186 | 193 |
| 187 std::unique_ptr<base::ListValue> response_arguments = | 194 std::unique_ptr<base::ListValue> response_arguments = |
| 188 ListValueFromString("['or','not','to','be']"); | 195 ListValueFromString("['or','not','to','be']"); |
| 189 ASSERT_TRUE(response_arguments); | 196 ASSERT_TRUE(response_arguments); |
| 190 request_handler.CompleteRequest(request_id, *response_arguments); | 197 request_handler.CompleteRequest(request_id, *response_arguments, |
| 198 std::string()); |
| 191 | 199 |
| 192 EXPECT_TRUE(did_run_js()); | 200 EXPECT_TRUE(did_run_js()); |
| 193 EXPECT_EQ(ReplaceSingleQuotes("['to','be','or','not','to','be']"), | 201 EXPECT_EQ(ReplaceSingleQuotes("['to','be','or','not','to','be']"), |
| 194 GetStringPropertyFromObject(context->Global(), context, "result")); | 202 GetStringPropertyFromObject(context->Global(), context, "result")); |
| 195 | 203 |
| 196 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); | 204 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); |
| 197 } | 205 } |
| 198 | 206 |
| 199 // Test user gestures being curried around for API requests. | 207 // Test user gestures being curried around for API requests. |
| 200 TEST_F(APIRequestHandlerTest, UserGestureTest) { | 208 TEST_F(APIRequestHandlerTest, UserGestureTest) { |
| 201 v8::HandleScope handle_scope(isolate()); | 209 v8::HandleScope handle_scope(isolate()); |
| 202 v8::Local<v8::Context> context = ContextLocal(); | 210 v8::Local<v8::Context> context = ContextLocal(); |
| 203 | 211 |
| 204 APIRequestHandler request_handler( | 212 APIRequestHandler request_handler( |
| 205 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this))); | 213 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 214 APILastError(APILastError::GetParent())); |
| 206 | 215 |
| 207 auto callback = [](base::Optional<bool>* ran_with_user_gesture) { | 216 auto callback = [](base::Optional<bool>* ran_with_user_gesture) { |
| 208 *ran_with_user_gesture = | 217 *ran_with_user_gesture = |
| 209 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe(); | 218 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe(); |
| 210 }; | 219 }; |
| 211 | 220 |
| 212 // Set up a callback to be used with the request so we can check if a user | 221 // Set up a callback to be used with the request so we can check if a user |
| 213 // gesture was active. | 222 // gesture was active. |
| 214 base::Optional<bool> ran_with_user_gesture; | 223 base::Optional<bool> ran_with_user_gesture; |
| 215 v8::Local<v8::FunctionTemplate> function_template = | 224 v8::Local<v8::FunctionTemplate> function_template = |
| 216 gin::CreateFunctionTemplate(isolate(), | 225 gin::CreateFunctionTemplate(isolate(), |
| 217 base::Bind(callback, &ran_with_user_gesture)); | 226 base::Bind(callback, &ran_with_user_gesture)); |
| 218 v8::Local<v8::Function> v8_callback = | 227 v8::Local<v8::Function> v8_callback = |
| 219 function_template->GetFunction(context).ToLocalChecked(); | 228 function_template->GetFunction(context).ToLocalChecked(); |
| 220 | 229 |
| 221 // Try first without a user gesture. | 230 // Try first without a user gesture. |
| 222 int request_id = request_handler.AddPendingRequest(isolate(), v8_callback, | 231 int request_id = request_handler.AddPendingRequest(isolate(), v8_callback, |
| 223 context, ArgumentList()); | 232 context, ArgumentList()); |
| 224 request_handler.CompleteRequest(request_id, *ListValueFromString("[]")); | 233 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), |
| 234 std::string()); |
| 225 | 235 |
| 226 ASSERT_TRUE(ran_with_user_gesture); | 236 ASSERT_TRUE(ran_with_user_gesture); |
| 227 EXPECT_FALSE(*ran_with_user_gesture); | 237 EXPECT_FALSE(*ran_with_user_gesture); |
| 228 ran_with_user_gesture.reset(); | 238 ran_with_user_gesture.reset(); |
| 229 | 239 |
| 230 // Next try calling with a user gesture. Since a gesture will be active at the | 240 // Next try calling with a user gesture. Since a gesture will be active at the |
| 231 // time of the call, it should also be active during the callback. | 241 // time of the call, it should also be active during the callback. |
| 232 { | 242 { |
| 233 blink::WebScopedUserGesture user_gesture(nullptr); | 243 blink::WebScopedUserGesture user_gesture(nullptr); |
| 234 EXPECT_TRUE( | 244 EXPECT_TRUE( |
| 235 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); | 245 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); |
| 236 request_id = request_handler.AddPendingRequest(isolate(), v8_callback, | 246 request_id = request_handler.AddPendingRequest(isolate(), v8_callback, |
| 237 context, ArgumentList()); | 247 context, ArgumentList()); |
| 238 } | 248 } |
| 239 EXPECT_FALSE( | 249 EXPECT_FALSE( |
| 240 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); | 250 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); |
| 241 | 251 |
| 242 request_handler.CompleteRequest(request_id, *ListValueFromString("[]")); | 252 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), |
| 253 std::string()); |
| 243 ASSERT_TRUE(ran_with_user_gesture); | 254 ASSERT_TRUE(ran_with_user_gesture); |
| 244 EXPECT_TRUE(*ran_with_user_gesture); | 255 EXPECT_TRUE(*ran_with_user_gesture); |
| 245 // Sanity check - after the callback ran, there shouldn't be an active | 256 // Sanity check - after the callback ran, there shouldn't be an active |
| 246 // gesture. | 257 // gesture. |
| 247 EXPECT_FALSE( | 258 EXPECT_FALSE( |
| 248 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); | 259 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); |
| 249 } | 260 } |
| 250 | 261 |
| 251 } // namespace extensions | 262 } // namespace extensions |
| OLD | NEW |