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

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

Issue 2617423003: [Extensions Bindings] Add support for updateArgumentsPostValidate (Closed)
Patch Set: . 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
« no previous file with comments | « extensions/renderer/api_binding_hooks.h ('k') | extensions/renderer/api_binding_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 15 matching lines...) Expand all
26 : api_name_(api_name) {} 26 : api_name_(api_name) {}
27 27
28 static gin::WrapperInfo kWrapperInfo; 28 static gin::WrapperInfo kWrapperInfo;
29 29
30 // gin::Wrappable: 30 // gin::Wrappable:
31 gin::ObjectTemplateBuilder GetObjectTemplateBuilder( 31 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
32 v8::Isolate* isolate) override { 32 v8::Isolate* isolate) override {
33 return Wrappable<JSHookInterface>::GetObjectTemplateBuilder(isolate) 33 return Wrappable<JSHookInterface>::GetObjectTemplateBuilder(isolate)
34 .SetMethod("setHandleRequest", &JSHookInterface::SetHandleRequest) 34 .SetMethod("setHandleRequest", &JSHookInterface::SetHandleRequest)
35 .SetMethod("setUpdateArgumentsPreValidate", 35 .SetMethod("setUpdateArgumentsPreValidate",
36 &JSHookInterface::SetUpdateArgumentsPreValidate); 36 &JSHookInterface::SetUpdateArgumentsPreValidate)
37 .SetMethod("setUpdateArgumentsPostValidate",
38 &JSHookInterface::SetUpdateArgumentsPostValidate);
37 } 39 }
38 40
39 void ClearHooks() { 41 void ClearHooks() {
40 handle_request_hooks_.clear(); 42 handle_request_hooks_.clear();
41 pre_validation_hooks_.clear(); 43 pre_validation_hooks_.clear();
44 post_validation_hooks_.clear();
42 } 45 }
43 46
44 v8::Local<v8::Function> GetHandleRequestHook(const std::string& method_name, 47 v8::Local<v8::Function> GetHandleRequestHook(const std::string& method_name,
45 v8::Isolate* isolate) const { 48 v8::Isolate* isolate) const {
46 return GetHookFromMap(handle_request_hooks_, method_name, isolate); 49 return GetHookFromMap(handle_request_hooks_, method_name, isolate);
47 } 50 }
48 51
49 v8::Local<v8::Function> GetPreValidationHook(const std::string& method_name, 52 v8::Local<v8::Function> GetPreValidationHook(const std::string& method_name,
50 v8::Isolate* isolate) const { 53 v8::Isolate* isolate) const {
51 return GetHookFromMap(pre_validation_hooks_, method_name, isolate); 54 return GetHookFromMap(pre_validation_hooks_, method_name, isolate);
52 } 55 }
53 56
57 v8::Local<v8::Function> GetPostValidationHook(const std::string& method_name,
58 v8::Isolate* isolate) const {
59 return GetHookFromMap(post_validation_hooks_, method_name, isolate);
60 }
61
54 private: 62 private:
55 using JSHooks = std::map<std::string, v8::Global<v8::Function>>; 63 using JSHooks = std::map<std::string, v8::Global<v8::Function>>;
56 64
57 v8::Local<v8::Function> GetHookFromMap(const JSHooks& map, 65 v8::Local<v8::Function> GetHookFromMap(const JSHooks& map,
58 const std::string& method_name, 66 const std::string& method_name,
59 v8::Isolate* isolate) const { 67 v8::Isolate* isolate) const {
60 auto iter = map.find(method_name); 68 auto iter = map.find(method_name);
61 if (iter == map.end()) 69 if (iter == map.end())
62 return v8::Local<v8::Function>(); 70 return v8::Local<v8::Function>();
63 return iter->second.Get(isolate); 71 return iter->second.Get(isolate);
(...skipping 21 matching lines...) Expand all
85 } 93 }
86 94
87 // Adds a hook to update the arguments passed to the API method before we do 95 // Adds a hook to update the arguments passed to the API method before we do
88 // any kind of validation. 96 // any kind of validation.
89 void SetUpdateArgumentsPreValidate(v8::Isolate* isolate, 97 void SetUpdateArgumentsPreValidate(v8::Isolate* isolate,
90 const std::string& method_name, 98 const std::string& method_name,
91 v8::Local<v8::Function> hook) { 99 v8::Local<v8::Function> hook) {
92 AddHookToMap(&pre_validation_hooks_, isolate, method_name, hook); 100 AddHookToMap(&pre_validation_hooks_, isolate, method_name, hook);
93 } 101 }
94 102
103 void SetUpdateArgumentsPostValidate(v8::Isolate* isolate,
104 const std::string& method_name,
105 v8::Local<v8::Function> hook) {
106 AddHookToMap(&post_validation_hooks_, isolate, method_name, hook);
107 }
108
95 std::string api_name_; 109 std::string api_name_;
96 110
97 JSHooks handle_request_hooks_; 111 JSHooks handle_request_hooks_;
98 JSHooks pre_validation_hooks_; 112 JSHooks pre_validation_hooks_;
113 JSHooks post_validation_hooks_;
99 114
100 DISALLOW_COPY_AND_ASSIGN(JSHookInterface); 115 DISALLOW_COPY_AND_ASSIGN(JSHookInterface);
101 }; 116 };
102 117
103 const char kExtensionAPIHooksPerContextKey[] = "extension_api_hooks"; 118 const char kExtensionAPIHooksPerContextKey[] = "extension_api_hooks";
104 119
105 struct APIHooksPerContextData : public base::SupportsUserData::Data { 120 struct APIHooksPerContextData : public base::SupportsUserData::Data {
106 APIHooksPerContextData(v8::Isolate* isolate) : isolate(isolate) {} 121 APIHooksPerContextData(v8::Isolate* isolate) : isolate(isolate) {}
107 ~APIHooksPerContextData() override { 122 ~APIHooksPerContextData() override {
108 v8::HandleScope scope(isolate); 123 v8::HandleScope scope(isolate);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; 193 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!";
179 request_hooks_[method_name] = hook; 194 request_hooks_[method_name] = hook;
180 } 195 }
181 196
182 void APIBindingHooks::RegisterJsSource(v8::Global<v8::String> source, 197 void APIBindingHooks::RegisterJsSource(v8::Global<v8::String> source,
183 v8::Global<v8::String> resource_name) { 198 v8::Global<v8::String> resource_name) {
184 js_hooks_source_ = std::move(source); 199 js_hooks_source_ = std::move(source);
185 js_resource_name_ = std::move(resource_name); 200 js_resource_name_ = std::move(resource_name);
186 } 201 }
187 202
188 APIBindingHooks::RequestResult APIBindingHooks::HandleRequest( 203 APIBindingHooks::RequestResult APIBindingHooks::RunHooks(
189 const std::string& api_name, 204 const std::string& api_name,
190 const std::string& method_name, 205 const std::string& method_name,
191 v8::Local<v8::Context> context, 206 v8::Local<v8::Context> context,
192 const APISignature* signature, 207 const APISignature* signature,
193 std::vector<v8::Local<v8::Value>>* arguments, 208 std::vector<v8::Local<v8::Value>>* arguments,
194 const ArgumentSpec::RefMap& type_refs) { 209 const ArgumentSpec::RefMap& type_refs) {
195 // Easy case: a native custom hook. 210 // Easy case: a native custom hook.
196 auto request_hooks_iter = request_hooks_.find(method_name); 211 auto request_hooks_iter = request_hooks_.find(method_name);
197 if (request_hooks_iter != request_hooks_.end()) { 212 if (request_hooks_iter != request_hooks_.end()) {
198 RequestResult result = 213 RequestResult result =
(...skipping 26 matching lines...) Expand all
225 v8::TryCatch try_catch(isolate); 240 v8::TryCatch try_catch(isolate);
226 // TODO(devlin): What to do with the result of this function call? Can it 241 // TODO(devlin): What to do with the result of this function call? Can it
227 // only fail in the case we've already thrown? 242 // only fail in the case we've already thrown?
228 UpdateArguments(pre_validate_hook, context, arguments); 243 UpdateArguments(pre_validate_hook, context, arguments);
229 if (try_catch.HasCaught()) { 244 if (try_catch.HasCaught()) {
230 try_catch.ReThrow(); 245 try_catch.ReThrow();
231 return RequestResult(RequestResult::THROWN); 246 return RequestResult(RequestResult::THROWN);
232 } 247 }
233 } 248 }
234 249
250 v8::Local<v8::Function> post_validate_hook =
251 hook_interface->GetPostValidationHook(method_name, isolate);
235 v8::Local<v8::Function> handle_request = 252 v8::Local<v8::Function> handle_request =
236 hook_interface->GetHandleRequestHook(method_name, isolate); 253 hook_interface->GetHandleRequestHook(method_name, isolate);
237 if (!handle_request.IsEmpty()) { 254 // If both the post validation hook and the handle request hook are empty,
255 // we're done...
256 if (post_validate_hook.IsEmpty() && handle_request.IsEmpty())
257 return RequestResult(RequestResult::NOT_HANDLED);
258
259 {
260 // ... otherwise, we have to validate the arguments.
238 v8::TryCatch try_catch(isolate); 261 v8::TryCatch try_catch(isolate);
239 std::vector<v8::Local<v8::Value>> parsed_v8_args; 262 std::vector<v8::Local<v8::Value>> parsed_v8_args;
240 std::string error; 263 std::string error;
241 bool success = signature->ParseArgumentsToV8(context, *arguments, type_refs, 264 bool success = signature->ParseArgumentsToV8(context, *arguments, type_refs,
242 &parsed_v8_args, &error); 265 &parsed_v8_args, &error);
243 if (try_catch.HasCaught()) { 266 if (try_catch.HasCaught()) {
244 try_catch.ReThrow(); 267 try_catch.ReThrow();
245 return RequestResult(RequestResult::THROWN); 268 return RequestResult(RequestResult::THROWN);
246 } 269 }
247 if (!success) 270 if (!success)
248 return RequestResult(RequestResult::INVALID_INVOCATION); 271 return RequestResult(RequestResult::INVALID_INVOCATION);
272 arguments->swap(parsed_v8_args);
273 }
249 274
250 v8::Global<v8::Value> global_result = 275 if (!post_validate_hook.IsEmpty()) {
251 run_js_.Run(handle_request, context, parsed_v8_args.size(), 276 v8::TryCatch try_catch(isolate);
jbroman 2017/01/11 20:01:48 nit: A thought here: I don't see any place here wh
Devlin 2017/01/13 17:11:58 Done.
252 parsed_v8_args.data()); 277 UpdateArguments(post_validate_hook, context, arguments);
253 if (try_catch.HasCaught()) { 278 if (try_catch.HasCaught()) {
254 try_catch.ReThrow(); 279 try_catch.ReThrow();
255 return RequestResult(RequestResult::THROWN); 280 return RequestResult(RequestResult::THROWN);
256 } 281 }
257 RequestResult result(RequestResult::HANDLED);
258 if (!global_result.IsEmpty())
259 result.return_value = global_result.Get(isolate);
260 return result;
261 } 282 }
262 283
263 return RequestResult(RequestResult::NOT_HANDLED); 284 if (handle_request.IsEmpty())
285 return RequestResult(RequestResult::NOT_HANDLED);
286
287 v8::TryCatch try_catch(isolate);
288 v8::Global<v8::Value> global_result =
289 run_js_.Run(handle_request, context, arguments->size(),
290 arguments->data());
291 if (try_catch.HasCaught()) {
292 try_catch.ReThrow();
293 return RequestResult(RequestResult::THROWN);
294 }
295 RequestResult result(RequestResult::HANDLED);
296 if (!global_result.IsEmpty())
297 result.return_value = global_result.Get(isolate);
298 return result;
264 } 299 }
265 300
266 void APIBindingHooks::InitializeInContext( 301 void APIBindingHooks::InitializeInContext(
267 v8::Local<v8::Context> context, 302 v8::Local<v8::Context> context,
268 const std::string& api_name) { 303 const std::string& api_name) {
269 if (js_hooks_source_.IsEmpty()) 304 if (js_hooks_source_.IsEmpty())
270 return; 305 return;
271 306
272 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); 307 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate());
273 v8::Local<v8::String> resource_name = 308 v8::Local<v8::String> resource_name =
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 if (result.IsEmpty() || 346 if (result.IsEmpty() ||
312 !gin::Converter<std::vector<v8::Local<v8::Value>>>::FromV8( 347 !gin::Converter<std::vector<v8::Local<v8::Value>>>::FromV8(
313 context->GetIsolate(), result, &new_args)) { 348 context->GetIsolate(), result, &new_args)) {
314 return false; 349 return false;
315 } 350 }
316 arguments->swap(new_args); 351 arguments->swap(new_args);
317 return true; 352 return true;
318 } 353 }
319 354
320 } // namespace extensions 355 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/api_binding_hooks.h ('k') | extensions/renderer/api_binding_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698