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

Unified Diff: chrome/renderer/resources/extensions/schema_generated_bindings.js

Issue 9317072: Allow omitting optional parameters for Extensions API functions (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Don't need this custom binding anymore. Created 8 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/resources/extensions/schema_generated_bindings.js
diff --git a/chrome/renderer/resources/extensions/schema_generated_bindings.js b/chrome/renderer/resources/extensions/schema_generated_bindings.js
index a935ff9db7e14d2a04668a7c42f63e3f3ae8b218..067ca90d5df810ff22527f97194667f7c6ed12cc 100644
--- a/chrome/renderer/resources/extensions/schema_generated_bindings.js
+++ b/chrome/renderer/resources/extensions/schema_generated_bindings.js
@@ -34,37 +34,118 @@ var chrome = chrome || {};
}
}
+ // Returns the defined signature of the API function.
+ chromeHidden.fullSignature = function(name, schemas) {
Aaron Boodman 2012/02/06 01:30:52 Function names should be a verb phrase, like getFu
+ var getTypeName = function(schema) {
+ var typeName = schema.type + " " + schema.name;
+ if (schema.optional)
+ return "optional " + typeName;
+ return typeName;
+ };
+
+ var typeNames = schemas.map(getTypeName);
+ return name +"(" + typeNames.join(", ") + ")";
+ };
+
+ // Return true if arguments match a given candidate's schema.
+ chromeHidden.matchCandidate = function(args, schemas) {
Aaron Boodman 2012/02/06 01:30:52 argumentsMatchSignature()?
+ if (args.length != schemas.length)
+ return false;
+
+ var validator = new chromeHidden.JSONSchemaValidator();
+ validator.addTypes(chromeHidden.validationTypes);
+ for (var i = 0; i < schemas.length; i++) {
+ if (args[i] !== null || !schemas[i].optional)
+ validator.validate(args[i], schemas[i]);
Aaron Boodman 2012/02/06 01:30:52 This does not do the right thing. It will check al
+ }
+ return validator.errors.length == 0;
+ };
+
+ // Generate candidates for a given API function scehma.
+ chromeHidden.getCandidates = function(schemas) {
Aaron Boodman 2012/02/06 01:30:52 Can we call this something other than 'candidate'.
+ if (schemas.length === 0)
+ return [[]];
+
+ var candidates = [];
+ var remaining = chromeHidden.getCandidates(schemas.slice(1));
+ for (var i = 0; i < remaining.length; i++) {
+ var candidate = remaining[i].slice(0);
+ candidate.unshift(schemas[0]);
+ candidates.push(candidate);
+ }
+ if (schemas[0].optional)
+ return candidates.concat(remaining);
+ return candidates;
+ };
+
// Validate arguments.
chromeHidden.validationTypes = [];
chromeHidden.validate = function(args, schemas) {
- if (args.length > schemas.length)
- throw new Error("Too many arguments.");
+ var candidates = chromeHidden.getCandidates(schemas);
+ var match = null;
+ for (var i = 0; i < candidates.length && match === null; i++) {
+ if (chromeHidden.matchCandidate(args, candidates[i]))
+ match = candidates[i];
+ }
+ if (match === null)
+ throw new Error("Invocation does not match definition.");
+
+ // Insert nulls into omitted optional parameters.
+ var normalized_args = [];
+ var ai = 0;
+ for (var si = 0; si < schemas.length; si++) {
+ if (schemas[si] === match[ai])
+ normalized_args.push(args[ai++]);
+ else
+ normalized_args.push(null);
+ }
+ return normalized_args;
Aaron Boodman 2012/02/06 01:30:52 Hm. This doesn't seem right. We never throw the va
+ };
- for (var i = 0; i < schemas.length; i++) {
- if (i in args && args[i] !== null && args[i] !== undefined) {
- var validator = new chromeHidden.JSONSchemaValidator();
- validator.addTypes(chromeHidden.validationTypes);
- validator.validate(args[i], schemas[i]);
- if (validator.errors.length == 0)
- continue;
+ // Returns true if there is a non-null value that both would accept.
+ chromeHidden.schemaOverlap = function(schema1, schema2) {
+ if (schema1.choices) {
+ for (var i = 0; i < schema1.choices.length; i++)
+ if (chromeHidden.schemaOverlap(schema1.choices[i], schema2))
+ return true;
+ } else if (schema2.choices) {
+ for (var i = 0; i < schema2.choices.length; i++)
+ if (chromeHidden.schemaOverlap(schema1, schema2.choices[i]))
+ return true;
+ } else {
+ var type1 = schema1.type ||
+ chromeHidden.validationTypes[schema1['$ref']].type;
+ var type2 = schema2.type ||
+ chromeHidden.validationTypes[schema2['$ref']].type;
- var message = "Invalid value for argument " + (i + 1) + ". ";
- for (var i = 0, err; err = validator.errors[i]; i++) {
- if (err.path) {
- message += "Property '" + err.path + "': ";
- }
- message += err.message;
- message = message.substring(0, message.length - 1);
- message += ", ";
- }
- message = message.substring(0, message.length - 2);
- message += ".";
+ if (type1 == "any" || type2 == "any")
+ return true;
+ return type1 == type2;
+ }
+ return false;
+ };
+
+ // Validate schema for API function.
+ chromeHidden.schemaAmbiguous = function(schema) {
+ var candidatesAmbiguous = function(candidate1, candidate2) {
+ if (candidate1.length != candidate2.length)
+ return false;
- throw new Error(message);
- } else if (!schemas[i].optional) {
- throw new Error("Parameter " + (i + 1) + " is required.");
+ for (var i = 0; i < candidate1.length; i++) {
+ if (!chromeHidden.schemaOverlap(candidate1[i], candidate2[i]))
+ return false;
+ }
+ return true;
+ };
+
+ candidates = chromeHidden.getCandidates(schema);
+ for (var i = 0; i < candidates.length; i++) {
+ for (var j = i + 1; j < candidates.length; j++) {
+ if (candidatesAmbiguous(candidates[i], candidates[j]))
+ return true;
}
}
+ return false;
};
// Callback handling.
@@ -437,13 +518,23 @@ var chrome = chrome || {};
var apiFunction = {};
apiFunction.definition = functionDef;
apiFunction.name = apiDef.namespace + "." + functionDef.name;
+ if (chromeHidden.validateAPI &&
+ chromeHidden.schemaAmbiguous(apiFunction.definition.parameters))
+ throw new Error(apiFunction.name + " is ambiguous");
+
apiFunctions.register(apiFunction.name, apiFunction);
module[functionDef.name] = (function() {
var args = arguments;
if (this.updateArgumentsPreValidate)
args = this.updateArgumentsPreValidate.apply(this, args);
- chromeHidden.validate(args, this.definition.parameters);
+ try {
Aaron Boodman 2012/02/06 01:30:52 I think it would be a bit cleaner to just have val
+ args = chromeHidden.validate(args, this.definition.parameters);
+ } catch (err) {
+ throw new Error("Invocation doesn't match definition " +
+ chromeHidden.fullSignature(this.name,
Aaron Boodman 2012/02/06 01:30:52 Can we also include the signature that was actuall
+ this.definition.parameters));
+ }
if (this.updateArgumentsPostValidate)
args = this.updateArgumentsPostValidate.apply(this, args);

Powered by Google App Engine
This is Rietveld 408576698