1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();
var natives = requireNative('sendRequest');
// Callback handling.
var requests = [];
chromeHidden.handleResponse = function(requestId, name,
success, response, error) {
try {
var request = requests[requestId];
if (success) {
delete chrome.extension.lastError;
} else {
if (!error) {
error = "Unknown error.";
}
console.error("Error during " + name + ": " + error);
chrome.extension.lastError = {
"message": error
};
}
if (request.customCallback) {
request.customCallback(name, request, response);
}
if (request.callback) {
// Callbacks currently only support one callback argument.
var callbackArgs = typeof(response) != "undefined" ? [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 new Error("No callback schemas defined");
}
if (request.callbackSchema.parameters.length > 1) {
throw new Error("Callbacks may only define one parameter");
}
chromeHidden.validate(callbackArgs,
request.callbackSchema.parameters);
} catch (exception) {
return "Callback validation error during " + name + " -- " +
exception.stack;
}
}
if (typeof(response) != "undefined") {
request.callback(callbackArgs[0]);
} else {
request.callback();
}
}
} finally {
delete requests[requestId];
delete chrome.extension.lastError;
}
return undefined;
};
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;
}
request.args = [];
for (var k = 0; k < argCount; k++) {
request.args[k] = args[k];
}
return request;
}
// Send an API request and optionally register a callback.
// |opt_args| is an object with optional parameters as follows:
// - noStringify: true if we should not stringify the request arguments.
// - customCallback: a callback that should be called instead of the standard
// callback.
// - nativeFunction: the v8 native function to handle the request, or
// StartRequest if missing.
// - forIOThread: true if this function should be handled on the browser IO
// thread.
function sendRequest(functionName, args, argSchemas, opt_args) {
if (!opt_args)
opt_args = {};
var request = prepareRequest(args, argSchemas);
if (opt_args.customCallback) {
request.customCallback = opt_args.customCallback;
}
// JSON.stringify doesn't support a root object which is undefined.
if (request.args === undefined)
request.args = null;
var sargs = opt_args.noStringify ?
request.args : chromeHidden.JSON.stringify(request.args);
var nativeFunction = opt_args.nativeFunction || natives.StartRequest;
var requestId = natives.GetNextRequestId();
request.id = requestId;
requests[requestId] = request;
var hasCallback =
(request.callback || opt_args.customCallback) ? true : false;
return nativeFunction(functionName, sargs, requestId, hasCallback,
opt_args.forIOThread);
}
exports.sendRequest = sendRequest;
|