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

Side by Side Diff: extensions/renderer/api_binding_hooks.cc

Issue 2609553003: [Extensions Bindings] Allow custom hooks to return values, throw (Closed)
Patch Set: jbroman Created 3 years, 11 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 "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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698