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

Unified Diff: chrome/renderer/resources/extension_process_bindings.js

Issue 173034: Validation of extension api callback and event parameters in DEBUG (Closed)
Patch Set: build docs Created 11 years, 4 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
« no previous file with comments | « chrome/renderer/resources/event_bindings.js ('k') | chrome/test/data/extensions/samples/tabs/manifest.json » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/renderer/resources/extension_process_bindings.js
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 3155c053a8a52c067ea6f88d77a7c9d4ed899d17..66872f921e010e338e0425cf2f523ce427fcf9a0 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -26,13 +26,15 @@ var chrome = chrome || {};
var chromeHidden = GetChromeHidden();
// Validate arguments.
- function validate(args, schemas) {
+ chromeHidden.validationTypes = [];
+ chromeHidden.validate = function(args, schemas) {
if (args.length > schemas.length)
throw new Error("Too many arguments.");
for (var i = 0; i < schemas.length; i++) {
if (i in args && args[i] !== null && args[i] !== undefined) {
var validator = new chrome.JSONSchemaValidator();
+ validator.addTypes(chromeHidden.validationTypes);
validator.validate(args[i], schemas[i]);
if (validator.errors.length == 0)
continue;
@@ -57,10 +59,11 @@ var chrome = chrome || {};
}
// Callback handling.
- var callbacks = [];
+ var requests = [];
chromeHidden.handleResponse = function(requestId, name,
success, response, error) {
try {
+ var request = requests[requestId];
if (success) {
delete chrome.extension.lastError;
} else {
@@ -72,16 +75,41 @@ var chrome = chrome || {};
"message": error
};
}
+
+ if (request.callback) {
+ // Callbacks currently only support one callback argument.
+ var callbackArgs = response ? [JSON.parse(response)] : [];
+
+ // Validate callback in debug only -- and only when the
+ // caller has provided a callback. Implementations of api
+ // calls my not return data if they observe the caller
+ // has not provided a callback.
+ if (chromeHidden.validateCallbacks && !error) {
+ try {
+ if (!request.callbackSchema.parameters) {
+ throw "No callback schemas defined";
+ }
+
+ if (request.callbackSchema.parameters.length > 1) {
+ throw "Callbacks may only define one parameter";
+ }
+
+ chromeHidden.validate(callbackArgs,
+ request.callbackSchema.parameters);
+ } catch (exception) {
+ return "Callback validation error during " + name + " -- " +
+ exception;
+ }
+ }
- if (callbacks[requestId]) {
if (response) {
- callbacks[requestId](JSON.parse(response));
+ request.callback(callbackArgs[0]);
} else {
- callbacks[requestId]();
+ request.callback();
}
}
} finally {
- delete callbacks[requestId];
+ delete requests[requestId];
delete chrome.extension.lastError;
}
};
@@ -89,15 +117,16 @@ var chrome = chrome || {};
function prepareRequest(args, argSchemas) {
var request = {};
var argCount = args.length;
-
+
// Look for callback param.
if (argSchemas.length > 0 &&
args.length == argSchemas.length &&
argSchemas[argSchemas.length - 1].type == "function") {
request.callback = args[argSchemas.length - 1];
+ request.callbackSchema = argSchemas[argSchemas.length - 1];
--argCount;
}
-
+
// Calls with one argument expect singular argument. Calls with multiple
// expect a list.
if (argCount == 1) {
@@ -121,12 +150,9 @@ var chrome = chrome || {};
request.args = null;
var sargs = JSON.stringify(request.args);
var requestId = GetNextRequestId();
- var hasCallback = false;
- if (request.callback) {
- hasCallback = true;
- callbacks[requestId] = request.callback;
- }
- return StartRequest(functionName, sargs, requestId, hasCallback);
+ requests[requestId] = request;
+ return StartRequest(functionName, sargs, requestId,
+ request.callback ? true : false);
}
// Using forEach for convenience, and to bind |module|s & |apiDefs|s via
@@ -179,7 +205,14 @@ var chrome = chrome || {};
forEach(apiDefinitions, function(apiDef) {
chrome[apiDef.namespace] = chrome[apiDef.namespace] || {};
var module = chrome[apiDef.namespace];
-
+
+ // Add types to global validationTypes
+ if (apiDef.types) {
+ forEach(apiDef.types, function(t) {
+ chromeHidden.validationTypes.push(t);
+ });
+ }
+
// Setup Functions.
if (apiDef.functions) {
forEach(apiDef.functions, function(functionDef) {
@@ -194,7 +227,7 @@ var chrome = chrome || {};
apiFunctions[apiFunction.name] = apiFunction;
module[functionDef.name] = bind(apiFunction, function() {
- validate(arguments, this.definition.parameters);
+ chromeHidden.validate(arguments, this.definition.parameters);
if (this.handleRequest)
return this.handleRequest.apply(this, arguments);
@@ -214,7 +247,8 @@ var chrome = chrome || {};
return;
var eventName = apiDef.namespace + "." + eventDef.name;
- module[eventDef.name] = new chrome.Event(eventName);
+ module[eventDef.name] = new chrome.Event(eventName,
+ eventDef.parameters);
});
}
});
« no previous file with comments | « chrome/renderer/resources/event_bindings.js ('k') | chrome/test/data/extensions/samples/tabs/manifest.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698