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

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

Issue 2552343006: [Extensions Binding] Allow for registering custom hooks (Closed)
Patch Set: jbroman Created 4 years 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.h" 5 #include "extensions/renderer/api_binding.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "extensions/common/extension_api.h" 14 #include "extensions/common/extension_api.h"
15 #include "extensions/renderer/api_binding_hooks.h"
16 #include "extensions/renderer/api_binding_types.h"
15 #include "extensions/renderer/api_event_handler.h" 17 #include "extensions/renderer/api_event_handler.h"
16 #include "extensions/renderer/v8_helpers.h" 18 #include "extensions/renderer/v8_helpers.h"
17 #include "gin/arguments.h" 19 #include "gin/arguments.h"
18 #include "gin/per_context_data.h" 20 #include "gin/per_context_data.h"
19 21
20 namespace extensions { 22 namespace extensions {
21 23
22 namespace { 24 namespace {
23 25
24 const char kExtensionAPIPerContextKey[] = "extension_api_binding"; 26 const char kExtensionAPIPerContextKey[] = "extension_api_binding";
25 27
26 using APISignature = std::vector<std::unique_ptr<ArgumentSpec>>;
27
28 // Returns the expected APISignature for a dictionary describing an API method. 28 // Returns the expected APISignature for a dictionary describing an API method.
29 std::unique_ptr<APISignature> GetAPISignature( 29 std::unique_ptr<binding::APISignature> GetAPISignature(
30 const base::DictionaryValue& dict) { 30 const base::DictionaryValue& dict) {
31 std::unique_ptr<APISignature> signature = base::MakeUnique<APISignature>(); 31 auto signature = base::MakeUnique<binding::APISignature>();
32 const base::ListValue* params = nullptr; 32 const base::ListValue* params = nullptr;
33 CHECK(dict.GetList("parameters", &params)); 33 CHECK(dict.GetList("parameters", &params));
34 signature->reserve(params->GetSize()); 34 signature->reserve(params->GetSize());
35 for (const auto& value : *params) { 35 for (const auto& value : *params) {
36 const base::DictionaryValue* param = nullptr; 36 const base::DictionaryValue* param = nullptr;
37 CHECK(value->GetAsDictionary(&param)); 37 CHECK(value->GetAsDictionary(&param));
38 std::string name; 38 std::string name;
39 CHECK(param->GetString("name", &name)); 39 CHECK(param->GetString("name", &name));
40 signature->push_back(base::MakeUnique<ArgumentSpec>(*param)); 40 signature->push_back(base::MakeUnique<ArgumentSpec>(*param));
41 } 41 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 return false; 103 return false;
104 } 104 }
105 105
106 *callback_out = value.As<v8::Function>(); 106 *callback_out = value.As<v8::Function>();
107 arguments->Skip(); 107 arguments->Skip();
108 return true; 108 return true;
109 } 109 }
110 110
111 // Parses |args| against |signature| and populates error with any errors. 111 // Parses |args| against |signature| and populates error with any errors.
112 std::unique_ptr<base::ListValue> ParseArguments( 112 std::unique_ptr<base::ListValue> ParseArguments(
113 const APISignature* signature, 113 const binding::APISignature* signature,
114 gin::Arguments* arguments, 114 gin::Arguments* arguments,
115 const ArgumentSpec::RefMap& type_refs, 115 const ArgumentSpec::RefMap& type_refs,
116 v8::Local<v8::Function>* callback, 116 v8::Local<v8::Function>* callback,
117 std::string* error) { 117 std::string* error) {
118 auto results = base::MakeUnique<base::ListValue>(); 118 auto results = base::MakeUnique<base::ListValue>();
119 119
120 // TODO(devlin): This is how extension APIs have always determined if a 120 // TODO(devlin): This is how extension APIs have always determined if a
121 // function has a callback, but it seems a little silly. In the long run (once 121 // function has a callback, but it seems a little silly. In the long run (once
122 // signatures are generated), it probably makes sense to indicate this 122 // signatures are generated), it probably makes sense to indicate this
123 // differently. 123 // differently.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 callback->Run(&args); 186 callback->Run(&args);
187 } 187 }
188 188
189 } // namespace 189 } // namespace
190 190
191 APIBinding::APIBinding(const std::string& api_name, 191 APIBinding::APIBinding(const std::string& api_name,
192 const base::ListValue& function_definitions, 192 const base::ListValue& function_definitions,
193 const base::ListValue* type_definitions, 193 const base::ListValue* type_definitions,
194 const base::ListValue* event_definitions, 194 const base::ListValue* event_definitions,
195 const APIMethodCallback& callback, 195 const APIMethodCallback& callback,
196 std::unique_ptr<APIBindingHooks> binding_hooks,
196 ArgumentSpec::RefMap* type_refs) 197 ArgumentSpec::RefMap* type_refs)
197 : api_name_(api_name), 198 : api_name_(api_name),
198 method_callback_(callback), 199 method_callback_(callback),
200 binding_hooks_(std::move(binding_hooks)),
199 type_refs_(type_refs), 201 type_refs_(type_refs),
200 weak_factory_(this) { 202 weak_factory_(this) {
201 DCHECK(!method_callback_.is_null()); 203 DCHECK(!method_callback_.is_null());
202 for (const auto& func : function_definitions) { 204 for (const auto& func : function_definitions) {
203 const base::DictionaryValue* func_dict = nullptr; 205 const base::DictionaryValue* func_dict = nullptr;
204 CHECK(func->GetAsDictionary(&func_dict)); 206 CHECK(func->GetAsDictionary(&func_dict));
205 std::string name; 207 std::string name;
206 CHECK(func_dict->GetString("name", &name)); 208 CHECK(func_dict->GetString("name", &name));
207 std::unique_ptr<APISignature> spec = GetAPISignature(*func_dict); 209 std::unique_ptr<binding::APISignature> spec = GetAPISignature(*func_dict);
208 signatures_[name] = std::move(spec); 210 signatures_[name] = std::move(spec);
209 } 211 }
210 if (type_definitions) { 212 if (type_definitions) {
211 for (const auto& type : *type_definitions) { 213 for (const auto& type : *type_definitions) {
212 const base::DictionaryValue* type_dict = nullptr; 214 const base::DictionaryValue* type_dict = nullptr;
213 CHECK(type->GetAsDictionary(&type_dict)); 215 CHECK(type->GetAsDictionary(&type_dict));
214 std::string id; 216 std::string id;
215 CHECK(type_dict->GetString("id", &id)); 217 CHECK(type_dict->GetString("id", &id));
216 DCHECK(type_refs->find(id) == type_refs->end()); 218 DCHECK(type_refs->find(id) == type_refs->end());
217 // TODO(devlin): refs are sometimes preceeded by the API namespace; we 219 // TODO(devlin): refs are sometimes preceeded by the API namespace; we
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 v8::Maybe<bool> success = object->CreateDataProperty( 287 v8::Maybe<bool> success = object->CreateDataProperty(
286 context, gin::StringToSymbol(isolate, event_name), event); 288 context, gin::StringToSymbol(isolate, event_name), event);
287 DCHECK(success.IsJust()); 289 DCHECK(success.IsJust());
288 DCHECK(success.FromJust()); 290 DCHECK(success.FromJust());
289 } 291 }
290 292
291 return object; 293 return object;
292 } 294 }
293 295
294 void APIBinding::HandleCall(const std::string& name, 296 void APIBinding::HandleCall(const std::string& name,
295 const APISignature* signature, 297 const binding::APISignature* signature,
296 gin::Arguments* arguments) { 298 gin::Arguments* arguments) {
297 std::string error; 299 std::string error;
298 v8::Isolate* isolate = arguments->isolate(); 300 v8::Isolate* isolate = arguments->isolate();
299 v8::HandleScope handle_scope(isolate); 301 v8::HandleScope handle_scope(isolate);
302
303 if (binding_hooks_) {
304 // Check for a custom hook to handle the method.
305 APIBindingHooks::HandleRequestHook handler =
306 binding_hooks_->GetHandleRequest(name);
307 if (!handler.is_null()) {
308 handler.Run(signature, arguments);
309 return;
310 }
311 }
312
300 std::unique_ptr<base::ListValue> parsed_arguments; 313 std::unique_ptr<base::ListValue> parsed_arguments;
301 v8::Local<v8::Function> callback; 314 v8::Local<v8::Function> callback;
302 { 315 {
303 v8::TryCatch try_catch(isolate); 316 v8::TryCatch try_catch(isolate);
304 parsed_arguments = 317 parsed_arguments =
305 ParseArguments(signature, arguments, *type_refs_, &callback, &error); 318 ParseArguments(signature, arguments, *type_refs_, &callback, &error);
306 if (try_catch.HasCaught()) { 319 if (try_catch.HasCaught()) {
307 DCHECK(!parsed_arguments); 320 DCHECK(!parsed_arguments);
308 try_catch.ReThrow(); 321 try_catch.ReThrow();
309 return; 322 return;
310 } 323 }
311 } 324 }
312 if (!parsed_arguments) { 325 if (!parsed_arguments) {
313 arguments->ThrowTypeError("Invalid invocation"); 326 arguments->ThrowTypeError("Invalid invocation");
314 return; 327 return;
315 } 328 }
316 329
317 // Since this is called synchronously from the JS entry point, 330 // Since this is called synchronously from the JS entry point,
318 // GetCurrentContext() should always be correct. 331 // GetCurrentContext() should always be correct.
319 method_callback_.Run(name, std::move(parsed_arguments), isolate, 332 method_callback_.Run(name, std::move(parsed_arguments), isolate,
320 isolate->GetCurrentContext(), callback); 333 isolate->GetCurrentContext(), callback);
321 } 334 }
322 335
323 } // namespace extensions 336 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698