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_binding_hooks.h" | 5 #include "extensions/renderer/api_binding_hooks.h" |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/supports_user_data.h" | 9 #include "base/supports_user_data.h" |
10 #include "extensions/renderer/api_signature.h" | 10 #include "extensions/renderer/api_signature.h" |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 gin::CreateHandle(context->GetIsolate(), new JSHookInterface(api_name)); | 157 gin::CreateHandle(context->GetIsolate(), new JSHookInterface(api_name)); |
158 CHECK(!hooks.IsEmpty()); | 158 CHECK(!hooks.IsEmpty()); |
159 v8::Local<v8::Object> hooks_object = hooks.ToV8().As<v8::Object>(); | 159 v8::Local<v8::Object> hooks_object = hooks.ToV8().As<v8::Object>(); |
160 data->hook_interfaces[api_name].Reset(context->GetIsolate(), hooks_object); | 160 data->hook_interfaces[api_name].Reset(context->GetIsolate(), hooks_object); |
161 | 161 |
162 return hooks_object; | 162 return hooks_object; |
163 } | 163 } |
164 | 164 |
165 } // namespace | 165 } // namespace |
166 | 166 |
| 167 APIBindingHooks::RequestResult::RequestResult(ResultCode code) : code(code) {} |
| 168 APIBindingHooks::RequestResult::~RequestResult() {} |
| 169 APIBindingHooks::RequestResult::RequestResult(const RequestResult& other) = |
| 170 default; |
| 171 |
167 APIBindingHooks::APIBindingHooks(const binding::RunJSFunctionSync& run_js) | 172 APIBindingHooks::APIBindingHooks(const binding::RunJSFunctionSync& run_js) |
168 : run_js_(run_js) {} | 173 : run_js_(run_js) {} |
169 APIBindingHooks::~APIBindingHooks() {} | 174 APIBindingHooks::~APIBindingHooks() {} |
170 | 175 |
171 void APIBindingHooks::RegisterHandleRequest(const std::string& method_name, | 176 void APIBindingHooks::RegisterHandleRequest(const std::string& method_name, |
172 const HandleRequestHook& hook) { | 177 const HandleRequestHook& hook) { |
173 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; | 178 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; |
174 request_hooks_[method_name] = hook; | 179 request_hooks_[method_name] = hook; |
175 } | 180 } |
176 | 181 |
(...skipping 11 matching lines...) Expand all Loading... |
188 std::vector<v8::Local<v8::Value>>* arguments, | 193 std::vector<v8::Local<v8::Value>>* arguments, |
189 const ArgumentSpec::RefMap& type_refs) { | 194 const ArgumentSpec::RefMap& type_refs) { |
190 // Easy case: a native custom hook. | 195 // Easy case: a native custom hook. |
191 auto request_hooks_iter = request_hooks_.find(method_name); | 196 auto request_hooks_iter = request_hooks_.find(method_name); |
192 if (request_hooks_iter != request_hooks_.end()) { | 197 if (request_hooks_iter != request_hooks_.end()) { |
193 RequestResult result = | 198 RequestResult result = |
194 request_hooks_iter->second.Run( | 199 request_hooks_iter->second.Run( |
195 signature, context, arguments, type_refs); | 200 signature, context, arguments, type_refs); |
196 // Right now, it doesn't make sense to register a request handler that | 201 // Right now, it doesn't make sense to register a request handler that |
197 // doesn't handle the request. | 202 // doesn't handle the request. |
198 DCHECK_NE(RequestResult::NOT_HANDLED, result); | 203 DCHECK_NE(RequestResult::NOT_HANDLED, result.code); |
199 return result; | 204 return result; |
200 } | 205 } |
201 | 206 |
202 // Harder case: looking up a custom hook registered on the context (since | 207 // Harder case: looking up a custom hook registered on the context (since |
203 // these are JS, each context has a separate instance). | 208 // these are JS, each context has a separate instance). |
204 v8::Local<v8::Object> hook_interface_object = | 209 v8::Local<v8::Object> hook_interface_object = |
205 GetJSHookInterfaceObject(api_name, context, false); | 210 GetJSHookInterfaceObject(api_name, context, false); |
206 if (hook_interface_object.IsEmpty()) | 211 if (hook_interface_object.IsEmpty()) |
207 return RequestResult::NOT_HANDLED; | 212 return RequestResult(RequestResult::NOT_HANDLED); |
208 | 213 |
209 v8::Isolate* isolate = context->GetIsolate(); | 214 v8::Isolate* isolate = context->GetIsolate(); |
210 | 215 |
211 JSHookInterface* hook_interface = nullptr; | 216 JSHookInterface* hook_interface = nullptr; |
212 gin::Converter<JSHookInterface*>::FromV8( | 217 gin::Converter<JSHookInterface*>::FromV8( |
213 isolate, | 218 isolate, |
214 hook_interface_object, &hook_interface); | 219 hook_interface_object, &hook_interface); |
215 CHECK(hook_interface); | 220 CHECK(hook_interface); |
216 | 221 |
217 v8::Local<v8::Function> pre_validate_hook = | 222 v8::Local<v8::Function> pre_validate_hook = |
218 hook_interface->GetPreValidationHook(method_name, isolate); | 223 hook_interface->GetPreValidationHook(method_name, isolate); |
219 if (!pre_validate_hook.IsEmpty()) { | 224 if (!pre_validate_hook.IsEmpty()) { |
220 v8::TryCatch try_catch(isolate); | 225 v8::TryCatch try_catch(isolate); |
221 // TODO(devlin): What to do with the result of this function call? Can it | 226 // TODO(devlin): What to do with the result of this function call? Can it |
222 // only fail in the case we've already thrown? | 227 // only fail in the case we've already thrown? |
223 UpdateArguments(pre_validate_hook, context, arguments); | 228 UpdateArguments(pre_validate_hook, context, arguments); |
224 if (try_catch.HasCaught()) { | 229 if (try_catch.HasCaught()) { |
225 try_catch.ReThrow(); | 230 try_catch.ReThrow(); |
226 return RequestResult::THROWN; | 231 return RequestResult(RequestResult::THROWN); |
227 } | 232 } |
228 } | 233 } |
229 | 234 |
230 v8::Local<v8::Function> handle_request = | 235 v8::Local<v8::Function> handle_request = |
231 hook_interface->GetHandleRequestHook(method_name, isolate); | 236 hook_interface->GetHandleRequestHook(method_name, isolate); |
232 if (!handle_request.IsEmpty()) { | 237 if (!handle_request.IsEmpty()) { |
233 v8::TryCatch try_catch(isolate); | 238 v8::TryCatch try_catch(isolate); |
234 std::vector<v8::Local<v8::Value>> parsed_v8_args; | 239 std::vector<v8::Local<v8::Value>> parsed_v8_args; |
235 std::string error; | 240 std::string error; |
236 bool success = signature->ParseArgumentsToV8(context, *arguments, type_refs, | 241 bool success = signature->ParseArgumentsToV8(context, *arguments, type_refs, |
237 &parsed_v8_args, &error); | 242 &parsed_v8_args, &error); |
238 if (try_catch.HasCaught()) { | 243 if (try_catch.HasCaught()) { |
239 try_catch.ReThrow(); | 244 try_catch.ReThrow(); |
240 return RequestResult::THROWN; | 245 return RequestResult(RequestResult::THROWN); |
241 } | 246 } |
242 if (!success) | 247 if (!success) |
243 return RequestResult::INVALID_INVOCATION; | 248 return RequestResult(RequestResult::INVALID_INVOCATION); |
244 | 249 |
245 run_js_.Run(handle_request, context, parsed_v8_args.size(), | 250 v8::Global<v8::Value> global_result = |
246 parsed_v8_args.data()); | 251 run_js_.Run(handle_request, context, parsed_v8_args.size(), |
247 return RequestResult::HANDLED; | 252 parsed_v8_args.data()); |
| 253 if (try_catch.HasCaught()) { |
| 254 try_catch.ReThrow(); |
| 255 return RequestResult(RequestResult::THROWN); |
| 256 } |
| 257 RequestResult result(RequestResult::HANDLED); |
| 258 if (!global_result.IsEmpty()) |
| 259 result.return_value = global_result.Get(isolate); |
| 260 return result; |
248 } | 261 } |
249 | 262 |
250 return RequestResult::NOT_HANDLED; | 263 return RequestResult(RequestResult::NOT_HANDLED); |
251 } | 264 } |
252 | 265 |
253 void APIBindingHooks::InitializeInContext( | 266 void APIBindingHooks::InitializeInContext( |
254 v8::Local<v8::Context> context, | 267 v8::Local<v8::Context> context, |
255 const std::string& api_name) { | 268 const std::string& api_name) { |
256 if (js_hooks_source_.IsEmpty()) | 269 if (js_hooks_source_.IsEmpty()) |
257 return; | 270 return; |
258 | 271 |
259 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); | 272 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); |
260 v8::Local<v8::String> resource_name = | 273 v8::Local<v8::String> resource_name = |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 if (result.IsEmpty() || | 311 if (result.IsEmpty() || |
299 !gin::Converter<std::vector<v8::Local<v8::Value>>>::FromV8( | 312 !gin::Converter<std::vector<v8::Local<v8::Value>>>::FromV8( |
300 context->GetIsolate(), result, &new_args)) { | 313 context->GetIsolate(), result, &new_args)) { |
301 return false; | 314 return false; |
302 } | 315 } |
303 arguments->swap(new_args); | 316 arguments->swap(new_args); |
304 return true; | 317 return true; |
305 } | 318 } |
306 | 319 |
307 } // namespace extensions | 320 } // namespace extensions |
OLD | NEW |