| 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 |