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

Unified Diff: extensions/renderer/api_signature.cc

Issue 2583273002: [Extensions Bindings] Allow for argument validation without conversion (Closed)
Patch Set: format 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « extensions/renderer/api_signature.h ('k') | extensions/renderer/argument_spec.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/api_signature.cc
diff --git a/extensions/renderer/api_signature.cc b/extensions/renderer/api_signature.cc
index 0edca2f9bf199545c6b3e8f5ec9c65f140e221ca..e82759baaf8bc3cadf0eb76ab1959272e24d8532 100644
--- a/extensions/renderer/api_signature.cc
+++ b/extensions/renderer/api_signature.cc
@@ -21,12 +21,48 @@ APISignature::APISignature(const base::ListValue& specification) {
APISignature::~APISignature() {}
-std::unique_ptr<base::ListValue> APISignature::ParseArguments(
+bool APISignature::ParseArgumentsToV8(gin::Arguments* arguments,
jbroman 2016/12/22 20:01:34 Higher level thought on this (that may cancel some
Devlin 2016/12/22 22:35:04 Interesting idea! I like it a lot, for the most p
+ const ArgumentSpec::RefMap& type_refs,
+ std::vector<v8::Local<v8::Value>>* v8_out,
+ std::string* error) const {
+ return ParseArgumentsImpl(arguments, type_refs, v8_out, nullptr, nullptr,
+ error);
+}
+
+bool APISignature::ParseArgumentsToJSON(
+ gin::Arguments* arguments,
+ const ArgumentSpec::RefMap& type_refs,
+ std::unique_ptr<base::ListValue>* json_out,
+ v8::Local<v8::Function>* callback_out,
+ std::string* error) const {
+ DCHECK(json_out);
+ DCHECK(callback_out);
+ return ParseArgumentsImpl(arguments, type_refs, nullptr, json_out,
+ callback_out, error);
+}
+
+bool APISignature::ParseArgumentsImpl(
gin::Arguments* arguments,
const ArgumentSpec::RefMap& type_refs,
+ std::vector<v8::Local<v8::Value>>* v8_out,
+ std::unique_ptr<base::ListValue>* json_out,
v8::Local<v8::Function>* callback_out,
std::string* error) const {
- auto results = base::MakeUnique<base::ListValue>();
+ DCHECK(error);
+ DCHECK_EQ(!!json_out, !!callback_out);
jbroman 2016/12/22 20:01:34 I found this a little tough to read. Is this equiv
Devlin 2016/12/22 22:35:04 Moot, I think.
+ DCHECK_NE(!!v8_out, !!json_out);
+
+ std::unique_ptr<base::ListValue> json_results;
+ // Only create the base::Values and convert if we need to; otherwise just
+ // look at the v8 values.
+ if (json_out)
+ json_results = base::MakeUnique<base::ListValue>();
+ // Adding v8 values to a vector is cheap enough that we don't need to do it
+ // conditionally.
+ // TODO(devlin): This can also result in creating null values (for absent
+ // optional parameters). Is that expensive enough to warrant making this
+ // conditional?
+ std::vector<v8::Local<v8::Value>> v8_results;
// TODO(devlin): This is how extension APIs have always determined if a
// function has a callback, but it seems a little silly. In the long run (once
@@ -41,56 +77,77 @@ std::unique_ptr<base::ListValue> APISignature::ParseArguments(
size_t end_size =
signature_has_callback ? signature_.size() - 1 : signature_.size();
for (size_t i = 0; i < end_size; ++i) {
- std::unique_ptr<base::Value> parsed =
- ParseArgument(*signature_[i], context, arguments, type_refs, error);
- if (!parsed)
- return nullptr;
- results->Append(std::move(parsed));
+ if (!ParseArgument(*signature_[i], context, arguments, type_refs,
+ &v8_results, json_results.get(), error)) {
+ return false;
+ }
}
v8::Local<v8::Function> callback_value;
if (signature_has_callback &&
!ParseCallback(arguments, *signature_.back(), error, &callback_value)) {
- return nullptr;
+ return false;
}
if (!arguments->PeekNext().IsEmpty())
- return nullptr; // Extra arguments aren't allowed.
+ return false; // Extra arguments aren't allowed.
+
+ if (json_out) {
+ if (!callback_value.IsEmpty())
+ *callback_out = callback_value;
+ *json_out = std::move(json_results);
+ } else {
+ DCHECK(v8_out);
+ if (!callback_value.IsEmpty())
+ v8_results.push_back(callback_value);
+ v8_out->swap(v8_results);
+ }
- *callback_out = callback_value;
- return results;
+ return true;
}
-std::unique_ptr<base::Value> APISignature::ParseArgument(
- const ArgumentSpec& spec,
- v8::Local<v8::Context> context,
- gin::Arguments* arguments,
- const ArgumentSpec::RefMap& type_refs,
- std::string* error) const {
+bool APISignature::ParseArgument(const ArgumentSpec& spec,
+ v8::Local<v8::Context> context,
+ gin::Arguments* arguments,
+ const ArgumentSpec::RefMap& type_refs,
+ std::vector<v8::Local<v8::Value>>* v8_out,
+ base::ListValue* json_out,
+ std::string* error) const {
v8::Local<v8::Value> value = arguments->PeekNext();
if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) {
if (!spec.optional()) {
*error = "Missing required argument: " + spec.name();
- return nullptr;
+ return false;
}
// This is safe to call even if |arguments| is at the end (which can happen
// if n optional arguments are omitted at the end of the signature).
arguments->Skip();
- return base::Value::CreateNullValue();
+
+ v8_out->push_back(v8::Null(context->GetIsolate()));
+ if (json_out)
+ json_out->Append(base::Value::CreateNullValue());
+ return true;
}
- std::unique_ptr<base::Value> result =
- spec.ConvertArgument(context, value, type_refs, error);
- if (!result) {
+ std::unique_ptr<base::Value> json_arg;
+ if (!spec.ParseArgument(context, value, type_refs,
+ json_out ? &json_arg : nullptr, error)) {
if (!spec.optional()) {
*error = "Missing required argument: " + spec.name();
- return nullptr;
+ return false;
}
- return base::Value::CreateNullValue();
+
+ v8_out->push_back(v8::Null(context->GetIsolate()));
jbroman 2016/12/22 20:01:34 It's strange that |v8_out| here is unconditionally
Devlin 2016/12/22 22:35:04 Moot, I think.
+ if (json_out)
+ json_out->Append(base::Value::CreateNullValue());
+ return true;
}
+ v8_out->push_back(value);
+ if (json_out)
+ json_out->Append(std::move(json_arg));
arguments->Skip();
- return result;
+ return true;
}
bool APISignature::ParseCallback(gin::Arguments* arguments,
« no previous file with comments | « extensions/renderer/api_signature.h ('k') | extensions/renderer/argument_spec.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698