| 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_request_handler.h" |
| 5 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/memory/ptr_util.h" |
| 6 #include "base/optional.h" | 8 #include "base/optional.h" |
| 7 #include "base/values.h" | 9 #include "base/values.h" |
| 8 #include "extensions/renderer/api_binding_test.h" | 10 #include "extensions/renderer/api_binding_test.h" |
| 9 #include "extensions/renderer/api_binding_test_util.h" | 11 #include "extensions/renderer/api_binding_test_util.h" |
| 10 #include "extensions/renderer/api_request_handler.h" | |
| 11 #include "gin/converter.h" | 12 #include "gin/converter.h" |
| 12 #include "gin/function_template.h" | 13 #include "gin/function_template.h" |
| 13 #include "gin/public/context_holder.h" | 14 #include "gin/public/context_holder.h" |
| 14 #include "gin/public/isolate_holder.h" | 15 #include "gin/public/isolate_holder.h" |
| 15 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 16 #include "third_party/WebKit/public/web/WebScopedUserGesture.h" | 17 #include "third_party/WebKit/public/web/WebScopedUserGesture.h" |
| 17 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" | 18 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
| 18 | 19 |
| 19 namespace extensions { | 20 namespace extensions { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 const char kEchoArgs[] = | 24 const char kEchoArgs[] = |
| 24 "(function() { this.result = Array.from(arguments); })"; | 25 "(function() { this.result = Array.from(arguments); })"; |
| 25 | 26 |
| 27 const char kMethod[] = "method"; |
| 28 |
| 26 // TODO(devlin): We should probably hoist this up to e.g. api_binding_types.h. | 29 // TODO(devlin): We should probably hoist this up to e.g. api_binding_types.h. |
| 27 using ArgumentList = std::vector<v8::Local<v8::Value>>; | 30 using ArgumentList = std::vector<v8::Local<v8::Value>>; |
| 28 | 31 |
| 32 // TODO(devlin): Should we move some parts of api_binding_unittest.cc to here? |
| 33 void DoNothingWithRequest(std::unique_ptr<APIRequestHandler::Request> request, |
| 34 v8::Local<v8::Context> context) {} |
| 35 |
| 29 } // namespace | 36 } // namespace |
| 30 | 37 |
| 31 class APIRequestHandlerTest : public APIBindingTest { | 38 class APIRequestHandlerTest : public APIBindingTest { |
| 32 public: | 39 public: |
| 33 // Runs the given |function|. | 40 // Runs the given |function|. |
| 34 void RunJS(v8::Local<v8::Function> function, | 41 void RunJS(v8::Local<v8::Function> function, |
| 35 v8::Local<v8::Context> context, | 42 v8::Local<v8::Context> context, |
| 36 int argc, | 43 int argc, |
| 37 v8::Local<v8::Value> argv[]) { | 44 v8::Local<v8::Value> argv[]) { |
| 38 RunFunctionOnGlobal(function, context, argc, argv); | 45 RunFunctionOnGlobal(function, context, argc, argv); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 51 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest); | 58 DISALLOW_COPY_AND_ASSIGN(APIRequestHandlerTest); |
| 52 }; | 59 }; |
| 53 | 60 |
| 54 // Tests adding a request to the request handler, and then triggering the | 61 // Tests adding a request to the request handler, and then triggering the |
| 55 // response. | 62 // response. |
| 56 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) { | 63 TEST_F(APIRequestHandlerTest, AddRequestAndCompleteRequestTest) { |
| 57 v8::HandleScope handle_scope(isolate()); | 64 v8::HandleScope handle_scope(isolate()); |
| 58 v8::Local<v8::Context> context = ContextLocal(); | 65 v8::Local<v8::Context> context = ContextLocal(); |
| 59 | 66 |
| 60 APIRequestHandler request_handler( | 67 APIRequestHandler request_handler( |
| 68 base::Bind(&DoNothingWithRequest), |
| 61 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), | 69 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 62 APILastError(APILastError::GetParent())); | 70 APILastError(APILastError::GetParent())); |
| 63 | 71 |
| 64 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); | 72 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); |
| 65 | 73 |
| 66 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); | 74 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); |
| 67 ASSERT_FALSE(function.IsEmpty()); | 75 ASSERT_FALSE(function.IsEmpty()); |
| 68 | 76 |
| 69 int request_id = request_handler.AddPendingRequest(isolate(), function, | 77 int request_id = request_handler.StartRequest( |
| 70 context, ArgumentList()); | 78 context, kMethod, base::MakeUnique<base::ListValue>(), function, |
| 79 v8::Local<v8::Function>()); |
| 71 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 80 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 72 testing::UnorderedElementsAre(request_id)); | 81 testing::UnorderedElementsAre(request_id)); |
| 73 | 82 |
| 74 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; | 83 const char kArguments[] = "['foo',1,{'prop1':'bar'}]"; |
| 75 std::unique_ptr<base::ListValue> response_arguments = | 84 std::unique_ptr<base::ListValue> response_arguments = |
| 76 ListValueFromString(kArguments); | 85 ListValueFromString(kArguments); |
| 77 ASSERT_TRUE(response_arguments); | 86 ASSERT_TRUE(response_arguments); |
| 78 request_handler.CompleteRequest(request_id, *response_arguments, | 87 request_handler.CompleteRequest(request_id, *response_arguments, |
| 79 std::string()); | 88 std::string()); |
| 80 | 89 |
| 81 EXPECT_TRUE(did_run_js()); | 90 EXPECT_TRUE(did_run_js()); |
| 82 EXPECT_EQ(ReplaceSingleQuotes(kArguments), | 91 EXPECT_EQ(ReplaceSingleQuotes(kArguments), |
| 83 GetStringPropertyFromObject(context->Global(), context, "result")); | 92 GetStringPropertyFromObject(context->Global(), context, "result")); |
| 84 | 93 |
| 85 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); | 94 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); |
| 86 } | 95 } |
| 87 | 96 |
| 88 // Tests that trying to run non-existent or invalided requests is a no-op. | 97 // Tests that trying to run non-existent or invalided requests is a no-op. |
| 89 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) { | 98 TEST_F(APIRequestHandlerTest, InvalidRequestsTest) { |
| 90 v8::HandleScope handle_scope(isolate()); | 99 v8::HandleScope handle_scope(isolate()); |
| 91 v8::Local<v8::Context> context = ContextLocal(); | 100 v8::Local<v8::Context> context = ContextLocal(); |
| 92 | 101 |
| 93 APIRequestHandler request_handler( | 102 APIRequestHandler request_handler( |
| 103 base::Bind(&DoNothingWithRequest), |
| 94 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), | 104 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 95 APILastError(APILastError::GetParent())); | 105 APILastError(APILastError::GetParent())); |
| 96 | 106 |
| 97 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); | 107 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); |
| 98 ASSERT_FALSE(function.IsEmpty()); | 108 ASSERT_FALSE(function.IsEmpty()); |
| 99 | 109 |
| 100 int request_id = request_handler.AddPendingRequest(isolate(), function, | 110 int request_id = request_handler.StartRequest( |
| 101 context, ArgumentList()); | 111 context, kMethod, base::MakeUnique<base::ListValue>(), function, |
| 112 v8::Local<v8::Function>()); |
| 102 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 113 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 103 testing::UnorderedElementsAre(request_id)); | 114 testing::UnorderedElementsAre(request_id)); |
| 104 | 115 |
| 105 std::unique_ptr<base::ListValue> response_arguments = | 116 std::unique_ptr<base::ListValue> response_arguments = |
| 106 ListValueFromString("['foo']"); | 117 ListValueFromString("['foo']"); |
| 107 ASSERT_TRUE(response_arguments); | 118 ASSERT_TRUE(response_arguments); |
| 108 | 119 |
| 109 // Try running with a non-existent request id. | 120 // Try running with a non-existent request id. |
| 110 int fake_request_id = 42; | 121 int fake_request_id = 42; |
| 111 request_handler.CompleteRequest(fake_request_id, *response_arguments, | 122 request_handler.CompleteRequest(fake_request_id, *response_arguments, |
| 112 std::string()); | 123 std::string()); |
| 113 EXPECT_FALSE(did_run_js()); | 124 EXPECT_FALSE(did_run_js()); |
| 114 | 125 |
| 115 // Try running with a request from an invalidated context. | 126 // Try running with a request from an invalidated context. |
| 116 request_handler.InvalidateContext(context); | 127 request_handler.InvalidateContext(context); |
| 117 request_handler.CompleteRequest(request_id, *response_arguments, | 128 request_handler.CompleteRequest(request_id, *response_arguments, |
| 118 std::string()); | 129 std::string()); |
| 119 EXPECT_FALSE(did_run_js()); | 130 EXPECT_FALSE(did_run_js()); |
| 120 } | 131 } |
| 121 | 132 |
| 122 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) { | 133 TEST_F(APIRequestHandlerTest, MultipleRequestsAndContexts) { |
| 123 v8::HandleScope handle_scope(isolate()); | 134 v8::HandleScope handle_scope(isolate()); |
| 124 v8::Local<v8::Context> context_a = ContextLocal(); | 135 v8::Local<v8::Context> context_a = ContextLocal(); |
| 125 v8::Local<v8::Context> context_b = v8::Context::New(isolate()); | 136 v8::Local<v8::Context> context_b = v8::Context::New(isolate()); |
| 126 gin::ContextHolder holder_b(isolate()); | 137 gin::ContextHolder holder_b(isolate()); |
| 127 holder_b.SetContext(context_b); | 138 holder_b.SetContext(context_b); |
| 128 | 139 |
| 129 APIRequestHandler request_handler( | 140 APIRequestHandler request_handler( |
| 141 base::Bind(&DoNothingWithRequest), |
| 130 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), | 142 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 131 APILastError(APILastError::GetParent())); | 143 APILastError(APILastError::GetParent())); |
| 132 | 144 |
| 133 // By having both different arguments and different behaviors in the | 145 // By having both different arguments and different behaviors in the |
| 134 // callbacks, we can easily verify that the right function is called in the | 146 // callbacks, we can easily verify that the right function is called in the |
| 135 // right context. | 147 // right context. |
| 136 v8::Local<v8::Function> function_a = FunctionFromString( | 148 v8::Local<v8::Function> function_a = FunctionFromString( |
| 137 context_a, "(function(res) { this.result = res + 'alpha'; })"); | 149 context_a, "(function(res) { this.result = res + 'alpha'; })"); |
| 138 v8::Local<v8::Function> function_b = FunctionFromString( | 150 v8::Local<v8::Function> function_b = FunctionFromString( |
| 139 context_b, "(function(res) { this.result = res + 'beta'; })"); | 151 context_b, "(function(res) { this.result = res + 'beta'; })"); |
| 140 | 152 |
| 141 int request_a = request_handler.AddPendingRequest(isolate(), function_a, | 153 int request_a = request_handler.StartRequest( |
| 142 context_a, ArgumentList()); | 154 context_a, kMethod, base::MakeUnique<base::ListValue>(), function_a, |
| 143 int request_b = request_handler.AddPendingRequest(isolate(), function_b, | 155 v8::Local<v8::Function>()); |
| 144 context_b, ArgumentList()); | 156 int request_b = request_handler.StartRequest( |
| 157 context_b, kMethod, base::MakeUnique<base::ListValue>(), function_b, |
| 158 v8::Local<v8::Function>()); |
| 145 | 159 |
| 146 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 160 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 147 testing::UnorderedElementsAre(request_a, request_b)); | 161 testing::UnorderedElementsAre(request_a, request_b)); |
| 148 | 162 |
| 149 std::unique_ptr<base::ListValue> response_a = | 163 std::unique_ptr<base::ListValue> response_a = |
| 150 ListValueFromString("['response_a:']"); | 164 ListValueFromString("['response_a:']"); |
| 151 ASSERT_TRUE(response_a); | 165 ASSERT_TRUE(response_a); |
| 152 | 166 |
| 153 request_handler.CompleteRequest(request_a, *response_a, std::string()); | 167 request_handler.CompleteRequest(request_a, *response_a, std::string()); |
| 154 EXPECT_TRUE(did_run_js()); | 168 EXPECT_TRUE(did_run_js()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 169 EXPECT_EQ( | 183 EXPECT_EQ( |
| 170 ReplaceSingleQuotes("'response_b:beta'"), | 184 ReplaceSingleQuotes("'response_b:beta'"), |
| 171 GetStringPropertyFromObject(context_b->Global(), context_b, "result")); | 185 GetStringPropertyFromObject(context_b->Global(), context_b, "result")); |
| 172 } | 186 } |
| 173 | 187 |
| 174 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) { | 188 TEST_F(APIRequestHandlerTest, CustomCallbackArguments) { |
| 175 v8::HandleScope handle_scope(isolate()); | 189 v8::HandleScope handle_scope(isolate()); |
| 176 v8::Local<v8::Context> context = ContextLocal(); | 190 v8::Local<v8::Context> context = ContextLocal(); |
| 177 | 191 |
| 178 APIRequestHandler request_handler( | 192 APIRequestHandler request_handler( |
| 193 base::Bind(&DoNothingWithRequest), |
| 179 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), | 194 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 180 APILastError(APILastError::GetParent())); | 195 APILastError(APILastError::GetParent())); |
| 181 | 196 |
| 182 ArgumentList custom_callback_args = { | 197 v8::Local<v8::Function> custom_callback = |
| 183 gin::StringToV8(isolate(), "to"), gin::StringToV8(isolate(), "be"), | 198 FunctionFromString(context, kEchoArgs); |
| 184 }; | 199 v8::Local<v8::Function> callback = |
| 200 FunctionFromString(context, "(function() {})"); |
| 201 ASSERT_FALSE(callback.IsEmpty()); |
| 202 ASSERT_FALSE(custom_callback.IsEmpty()); |
| 185 | 203 |
| 186 v8::Local<v8::Function> function = FunctionFromString(context, kEchoArgs); | 204 int request_id = request_handler.StartRequest( |
| 187 ASSERT_FALSE(function.IsEmpty()); | 205 context, "method", base::MakeUnique<base::ListValue>(), callback, |
| 188 | 206 custom_callback); |
| 189 int request_id = request_handler.AddPendingRequest( | |
| 190 isolate(), function, context, custom_callback_args); | |
| 191 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), | 207 EXPECT_THAT(request_handler.GetPendingRequestIdsForTesting(), |
| 192 testing::UnorderedElementsAre(request_id)); | 208 testing::UnorderedElementsAre(request_id)); |
| 193 | 209 |
| 194 std::unique_ptr<base::ListValue> response_arguments = | 210 std::unique_ptr<base::ListValue> response_arguments = |
| 195 ListValueFromString("['or','not','to','be']"); | 211 ListValueFromString("['response', 'arguments']"); |
| 196 ASSERT_TRUE(response_arguments); | 212 ASSERT_TRUE(response_arguments); |
| 197 request_handler.CompleteRequest(request_id, *response_arguments, | 213 request_handler.CompleteRequest(request_id, *response_arguments, |
| 198 std::string()); | 214 std::string()); |
| 199 | 215 |
| 200 EXPECT_TRUE(did_run_js()); | 216 EXPECT_TRUE(did_run_js()); |
| 201 EXPECT_EQ(ReplaceSingleQuotes("['to','be','or','not','to','be']"), | 217 v8::Local<v8::Value> result = |
| 202 GetStringPropertyFromObject(context->Global(), context, "result")); | 218 GetPropertyFromObject(context->Global(), context, "result"); |
| 219 ASSERT_FALSE(result.IsEmpty()); |
| 220 ASSERT_TRUE(result->IsArray()); |
| 221 ArgumentList args; |
| 222 ASSERT_TRUE(gin::Converter<ArgumentList>::FromV8(isolate(), result, &args)); |
| 223 ASSERT_EQ(5u, args.size()); |
| 224 EXPECT_EQ("\"method\"", V8ToString(args[0], context)); |
| 225 EXPECT_EQ("{}", V8ToString(args[1], context)); |
| 226 EXPECT_EQ(callback, args[2]); |
| 227 EXPECT_EQ("\"response\"", V8ToString(args[3], context)); |
| 228 EXPECT_EQ("\"arguments\"", V8ToString(args[4], context)); |
| 203 | 229 |
| 204 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); | 230 EXPECT_TRUE(request_handler.GetPendingRequestIdsForTesting().empty()); |
| 205 } | 231 } |
| 206 | 232 |
| 207 // Test user gestures being curried around for API requests. | 233 // Test user gestures being curried around for API requests. |
| 208 TEST_F(APIRequestHandlerTest, UserGestureTest) { | 234 TEST_F(APIRequestHandlerTest, UserGestureTest) { |
| 209 v8::HandleScope handle_scope(isolate()); | 235 v8::HandleScope handle_scope(isolate()); |
| 210 v8::Local<v8::Context> context = ContextLocal(); | 236 v8::Local<v8::Context> context = ContextLocal(); |
| 211 | 237 |
| 212 APIRequestHandler request_handler( | 238 APIRequestHandler request_handler( |
| 239 base::Bind(&DoNothingWithRequest), |
| 213 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), | 240 base::Bind(&APIRequestHandlerTest::RunJS, base::Unretained(this)), |
| 214 APILastError(APILastError::GetParent())); | 241 APILastError(APILastError::GetParent())); |
| 215 | 242 |
| 216 auto callback = [](base::Optional<bool>* ran_with_user_gesture) { | 243 auto callback = [](base::Optional<bool>* ran_with_user_gesture) { |
| 217 *ran_with_user_gesture = | 244 *ran_with_user_gesture = |
| 218 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe(); | 245 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe(); |
| 219 }; | 246 }; |
| 220 | 247 |
| 221 // Set up a callback to be used with the request so we can check if a user | 248 // Set up a callback to be used with the request so we can check if a user |
| 222 // gesture was active. | 249 // gesture was active. |
| 223 base::Optional<bool> ran_with_user_gesture; | 250 base::Optional<bool> ran_with_user_gesture; |
| 224 v8::Local<v8::FunctionTemplate> function_template = | 251 v8::Local<v8::FunctionTemplate> function_template = |
| 225 gin::CreateFunctionTemplate(isolate(), | 252 gin::CreateFunctionTemplate(isolate(), |
| 226 base::Bind(callback, &ran_with_user_gesture)); | 253 base::Bind(callback, &ran_with_user_gesture)); |
| 227 v8::Local<v8::Function> v8_callback = | 254 v8::Local<v8::Function> v8_callback = |
| 228 function_template->GetFunction(context).ToLocalChecked(); | 255 function_template->GetFunction(context).ToLocalChecked(); |
| 229 | 256 |
| 230 // Try first without a user gesture. | 257 // Try first without a user gesture. |
| 231 int request_id = request_handler.AddPendingRequest(isolate(), v8_callback, | 258 int request_id = request_handler.StartRequest( |
| 232 context, ArgumentList()); | 259 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback, |
| 260 v8::Local<v8::Function>()); |
| 233 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), | 261 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), |
| 234 std::string()); | 262 std::string()); |
| 235 | 263 |
| 236 ASSERT_TRUE(ran_with_user_gesture); | 264 ASSERT_TRUE(ran_with_user_gesture); |
| 237 EXPECT_FALSE(*ran_with_user_gesture); | 265 EXPECT_FALSE(*ran_with_user_gesture); |
| 238 ran_with_user_gesture.reset(); | 266 ran_with_user_gesture.reset(); |
| 239 | 267 |
| 240 // Next try calling with a user gesture. Since a gesture will be active at the | 268 // Next try calling with a user gesture. Since a gesture will be active at the |
| 241 // time of the call, it should also be active during the callback. | 269 // time of the call, it should also be active during the callback. |
| 242 { | 270 { |
| 243 blink::WebScopedUserGesture user_gesture(nullptr); | 271 blink::WebScopedUserGesture user_gesture(nullptr); |
| 244 EXPECT_TRUE( | 272 EXPECT_TRUE( |
| 245 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); | 273 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); |
| 246 request_id = request_handler.AddPendingRequest(isolate(), v8_callback, | 274 request_id = request_handler.StartRequest( |
| 247 context, ArgumentList()); | 275 context, kMethod, base::MakeUnique<base::ListValue>(), v8_callback, |
| 276 v8::Local<v8::Function>()); |
| 248 } | 277 } |
| 249 EXPECT_FALSE( | 278 EXPECT_FALSE( |
| 250 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); | 279 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); |
| 251 | 280 |
| 252 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), | 281 request_handler.CompleteRequest(request_id, *ListValueFromString("[]"), |
| 253 std::string()); | 282 std::string()); |
| 254 ASSERT_TRUE(ran_with_user_gesture); | 283 ASSERT_TRUE(ran_with_user_gesture); |
| 255 EXPECT_TRUE(*ran_with_user_gesture); | 284 EXPECT_TRUE(*ran_with_user_gesture); |
| 256 // Sanity check - after the callback ran, there shouldn't be an active | 285 // Sanity check - after the callback ran, there shouldn't be an active |
| 257 // gesture. | 286 // gesture. |
| 258 EXPECT_FALSE( | 287 EXPECT_FALSE( |
| 259 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); | 288 blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe()); |
| 260 } | 289 } |
| 261 | 290 |
| 262 } // namespace extensions | 291 } // namespace extensions |
| OLD | NEW |