summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/resources/extension_process_bindings.js
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/renderer/resources/extension_process_bindings.js')
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js68
1 files changed, 51 insertions, 17 deletions
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 3155c05..66872f9 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);
});
}
});