Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / extensions / renderer / resources / send_request.js
blob7cdc7d16936a19a267258e217ccc4fd0a853433c
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var exceptionHandler = require('uncaught_exception_handler');
6 var lastError = require('lastError');
7 var logging = requireNative('logging');
8 var natives = requireNative('sendRequest');
9 var validate = require('schemaUtils').validate;
11 // All outstanding requests from sendRequest().
12 var requests = {};
14 // Used to prevent double Activity Logging for API calls that use both custom
15 // bindings and ExtensionFunctions (via sendRequest).
16 var calledSendRequest = false;
18 // Runs a user-supplied callback safely.
19 function safeCallbackApply(name, request, callback, args) {
20 try {
21 $Function.apply(callback, request, args);
22 } catch (e) {
23 exceptionHandler.handle('Error in response to ' + name, e, request.stack);
27 // Callback handling.
28 function handleResponse(requestId, name, success, responseList, error) {
29 // The chrome objects we will set lastError on. Really we should only be
30 // setting this on the callback's chrome object, but set on ours too since
31 // it's conceivable that something relies on that.
32 var callerChrome = chrome;
34 try {
35 var request = requests[requestId];
36 logging.DCHECK(request != null);
38 // lastError needs to be set on the caller's chrome object no matter what,
39 // though chances are it's the same as ours (it will be different when
40 // calling API methods on other contexts).
41 if (request.callback)
42 callerChrome = natives.GetGlobal(request.callback).chrome;
44 lastError.clear(chrome);
45 if (callerChrome !== chrome)
46 lastError.clear(callerChrome);
48 if (!success) {
49 if (!error)
50 error = "Unknown error.";
51 lastError.set(name, error, request.stack, chrome);
52 if (callerChrome !== chrome)
53 lastError.set(name, error, request.stack, callerChrome);
56 if (request.customCallback) {
57 safeCallbackApply(name,
58 request,
59 request.customCallback,
60 $Array.concat([name, request], responseList));
63 if (request.callback) {
64 // Validate callback in debug only -- and only when the
65 // caller has provided a callback. Implementations of api
66 // calls may not return data if they observe the caller
67 // has not provided a callback.
68 if (logging.DCHECK_IS_ON() && !error) {
69 if (!request.callbackSchema.parameters)
70 throw new Error(name + ": no callback schema defined");
71 validate(responseList, request.callbackSchema.parameters);
73 safeCallbackApply(name, request, request.callback, responseList);
76 if (error &&
77 !lastError.hasAccessed(chrome) &&
78 !lastError.hasAccessed(callerChrome)) {
79 // The native call caused an error, but the developer didn't check
80 // runtime.lastError.
81 // Notify the developer of the error via the (error) console.
82 console.error("Unchecked runtime.lastError while running " +
83 (name || "unknown") + ": " + error +
84 (request.stack ? "\n" + request.stack : ""));
86 } finally {
87 delete requests[requestId];
88 lastError.clear(chrome);
89 if (callerChrome !== chrome)
90 lastError.clear(callerChrome);
94 function prepareRequest(args, argSchemas) {
95 var request = {};
96 var argCount = args.length;
98 // Look for callback param.
99 if (argSchemas.length > 0 &&
100 argSchemas[argSchemas.length - 1].type == "function") {
101 request.callback = args[args.length - 1];
102 request.callbackSchema = argSchemas[argSchemas.length - 1];
103 --argCount;
106 request.args = [];
107 for (var k = 0; k < argCount; k++) {
108 request.args[k] = args[k];
111 return request;
114 // Send an API request and optionally register a callback.
115 // |optArgs| is an object with optional parameters as follows:
116 // - customCallback: a callback that should be called instead of the standard
117 // callback.
118 // - nativeFunction: the v8 native function to handle the request, or
119 // StartRequest if missing.
120 // - forIOThread: true if this function should be handled on the browser IO
121 // thread.
122 // - preserveNullInObjects: true if it is safe for null to be in objects.
123 function sendRequest(functionName, args, argSchemas, optArgs) {
124 calledSendRequest = true;
125 if (!optArgs)
126 optArgs = {};
127 var request = prepareRequest(args, argSchemas);
128 request.stack = exceptionHandler.getExtensionStackTrace();
129 if (optArgs.customCallback) {
130 request.customCallback = optArgs.customCallback;
133 var nativeFunction = optArgs.nativeFunction || natives.StartRequest;
135 var requestId = natives.GetNextRequestId();
136 request.id = requestId;
137 requests[requestId] = request;
139 var hasCallback = request.callback || optArgs.customCallback;
140 return nativeFunction(functionName,
141 request.args,
142 requestId,
143 hasCallback,
144 optArgs.forIOThread,
145 optArgs.preserveNullInObjects);
148 function getCalledSendRequest() {
149 return calledSendRequest;
152 function clearCalledSendRequest() {
153 calledSendRequest = false;
156 exports.sendRequest = sendRequest;
157 exports.getCalledSendRequest = getCalledSendRequest;
158 exports.clearCalledSendRequest = clearCalledSendRequest;
159 exports.safeCallbackApply = safeCallbackApply;
161 // Called by C++.
162 exports.handleResponse = handleResponse;