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

Side by Side Diff: chrome/renderer/resources/extensions/binding.js

Issue 14494013: Allow API functions and events to have entries in _api_features.json (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix browser_tests, Stubs now inspects _api_features.json Created 7 years, 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 require('json_schema'); 5 require('json_schema');
6 require('event_bindings'); 6 require('event_bindings');
7 var chrome = requireNative('chrome').GetChrome(); 7 var chrome = requireNative('chrome').GetChrome();
8 var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); 8 var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();
9 var forEach = require('utils').forEach; 9 var forEach = require('utils').forEach;
10 var GetAvailability = requireNative('v8_context').GetAvailability; 10 var GetAvailability = requireNative('v8_context').GetAvailability;
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 schema: this.schema_, 195 schema: this.schema_,
196 compiledApi: api 196 compiledApi: api
197 }, extensionId, contextType); 197 }, extensionId, contextType);
198 }, this); 198 }, this);
199 }, 199 },
200 200
201 // Generates the bindings from |this.schema_| and integrates any custom 201 // Generates the bindings from |this.schema_| and integrates any custom
202 // bindings that might be present. 202 // bindings that might be present.
203 generate: function() { 203 generate: function() {
204 var schema = this.schema_; 204 var schema = this.schema_;
205 var checkUnprivileged = schema['check_unprivileged'];
not at google - send to devlin 2013/05/03 04:58:14 to answer your question in IRC - yeah let's fix th
205 206
206 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the 207 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the
207 // supporting code. 208 // supporting code.
208 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) { 209 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) {
209 console.error('chrome.' + schema.namespace + ' is not supported on ' + 210 console.error('chrome.' + schema.namespace + ' is not supported on ' +
210 'this platform or manifest version'); 211 'this platform or manifest version');
211 return undefined; 212 return undefined;
212 } 213 }
213 214
214 var availability = GetAvailability(schema.namespace);
215 if (!availability.is_available) {
216 console.error('chrome.' + schema.namespace + ' is not available: ' +
217 availability.message);
218 return undefined;
219 }
220
221 // See comment on internalAPIs at the top.
222 var mod = {}; 215 var mod = {};
223 216
224 var namespaces = schema.namespace.split('.'); 217 var namespaces = schema.namespace.split('.');
225 for (var index = 0, name; name = namespaces[index]; index++) { 218 for (var index = 0, name; name = namespaces[index]; index++) {
226 mod[name] = mod[name] || {}; 219 mod[name] = mod[name] || {};
227 mod = mod[name]; 220 mod = mod[name];
228 } 221 }
229 222
230 // Add types to global schemaValidator, the types we depend on from other 223 // Add types to global schemaValidator, the types we depend on from other
231 // namespaces will be added as needed. 224 // namespaces will be added as needed.
232 if (schema.types) { 225 if (schema.types) {
233 forEach(schema.types, function(i, t) { 226 forEach(schema.types, function(i, t) {
234 if (!isSchemaNodeSupported(t, platform, manifestVersion)) 227 if (!isSchemaNodeSupported(t, platform, manifestVersion))
235 return; 228 return;
236 229
237 schemaUtils.schemaValidator.addTypes(t); 230 schemaUtils.schemaValidator.addTypes(t);
238 }, this); 231 }, this);
239 } 232 }
240 233
234 // TODO(cduvall): Take out when all APIs have been converted to features.
241 // Returns whether access to the content of a schema should be denied, 235 // Returns whether access to the content of a schema should be denied,
242 // based on the presence of "unprivileged" and whether this is an 236 // based on the presence of "unprivileged" and whether this is an
243 // extension process (versus e.g. a content script). 237 // extension process (versus e.g. a content script).
244 function isSchemaAccessAllowed(itemSchema) { 238 function isSchemaAccessAllowed(itemSchema) {
245 return (contextType == 'BLESSED_EXTENSION') || 239 return (contextType == 'BLESSED_EXTENSION') ||
246 schema.unprivileged || 240 schema.unprivileged ||
247 itemSchema.unprivileged; 241 itemSchema.unprivileged;
248 }; 242 };
249 243
250 // Adds a getter that throws an access denied error to object |mod|
251 // for property |name|.
252 function addUnprivilegedAccessGetter(mod, name) {
253 mod.__defineGetter__(name, function() {
254 throw new Error(
255 '"' + name + '" can only be used in extension processes. See ' +
256 'the content scripts documentation for more details.');
257 });
258 }
259
260 // Setup Functions. 244 // Setup Functions.
261 if (schema.functions) { 245 if (schema.functions) {
262 forEach(schema.functions, function(i, functionDef) { 246 forEach(schema.functions, function(i, functionDef) {
263 if (functionDef.name in mod) { 247 if (functionDef.name in mod) {
264 throw new Error('Function ' + functionDef.name + 248 throw new Error('Function ' + functionDef.name +
265 ' already defined in ' + schema.namespace); 249 ' already defined in ' + schema.namespace);
266 } 250 }
267 251
268 if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) { 252 if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) {
269 this.apiFunctions_.registerUnavailable(functionDef.name); 253 this.apiFunctions_.registerUnavailable(functionDef.name);
270 return; 254 return;
271 } 255 }
272 if (!isSchemaAccessAllowed(functionDef)) {
273 this.apiFunctions_.registerUnavailable(functionDef.name);
274 addUnprivilegedAccessGetter(mod, functionDef.name);
275 return;
276 }
277 256
278 var apiFunction = {}; 257 var apiFunction = {};
279 apiFunction.definition = functionDef; 258 apiFunction.definition = functionDef;
280 apiFunction.name = schema.namespace + '.' + functionDef.name; 259 apiFunction.name = schema.namespace + '.' + functionDef.name;
281 260
261 if (!GetAvailability(apiFunction.name).is_available ||
262 (checkUnprivileged && !isSchemaAccessAllowed(functionDef))) {
263 this.apiFunctions_.registerUnavailable(functionDef.name);
264 return;
265 }
266
282 // TODO(aa): It would be best to run this in a unit test, but in order 267 // TODO(aa): It would be best to run this in a unit test, but in order
283 // to do that we would need to better factor this code so that it 268 // to do that we would need to better factor this code so that it
284 // doesn't depend on so much v8::Extension machinery. 269 // doesn't depend on so much v8::Extension machinery.
285 if (chromeHidden.validateAPI && 270 if (chromeHidden.validateAPI &&
286 schemaUtils.isFunctionSignatureAmbiguous( 271 schemaUtils.isFunctionSignatureAmbiguous(
287 apiFunction.definition)) { 272 apiFunction.definition)) {
288 throw new Error( 273 throw new Error(
289 apiFunction.name + ' has ambiguous optional arguments. ' + 274 apiFunction.name + ' has ambiguous optional arguments. ' +
290 'To implement custom disambiguation logic, add ' + 275 'To implement custom disambiguation logic, add ' +
291 '"allowAmbiguousOptionalArguments" to the function\'s schema.'); 276 '"allowAmbiguousOptionalArguments" to the function\'s schema.');
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 314
330 // Setup Events 315 // Setup Events
331 if (schema.events) { 316 if (schema.events) {
332 forEach(schema.events, function(i, eventDef) { 317 forEach(schema.events, function(i, eventDef) {
333 if (eventDef.name in mod) { 318 if (eventDef.name in mod) {
334 throw new Error('Event ' + eventDef.name + 319 throw new Error('Event ' + eventDef.name +
335 ' already defined in ' + schema.namespace); 320 ' already defined in ' + schema.namespace);
336 } 321 }
337 if (!isSchemaNodeSupported(eventDef, platform, manifestVersion)) 322 if (!isSchemaNodeSupported(eventDef, platform, manifestVersion))
338 return; 323 return;
339 if (!isSchemaAccessAllowed(eventDef)) { 324
340 addUnprivilegedAccessGetter(mod, eventDef.name); 325 var eventName = schema.namespace + "." + eventDef.name;
326 if (!GetAvailability(eventName).is_available ||
327 (checkUnprivileged && !isSchemaAccessAllowed(eventDef))) {
341 return; 328 return;
342 } 329 }
343 330
344 var eventName = schema.namespace + "." + eventDef.name;
345 var options = eventDef.options || {}; 331 var options = eventDef.options || {};
346
347 if (eventDef.filters && eventDef.filters.length > 0) 332 if (eventDef.filters && eventDef.filters.length > 0)
348 options.supportsFilters = true; 333 options.supportsFilters = true;
349 334
350 if (this.customEvent_) { 335 if (this.customEvent_) {
351 mod[eventDef.name] = new this.customEvent_( 336 mod[eventDef.name] = new this.customEvent_(
352 eventName, eventDef.parameters, eventDef.extraParameters, 337 eventName, eventDef.parameters, eventDef.extraParameters,
353 options); 338 options);
354 } else if (eventDef.anonymous) { 339 } else if (eventDef.anonymous) {
355 mod[eventDef.name] = new chrome.Event(); 340 mod[eventDef.name] = new chrome.Event();
356 } else { 341 } else {
357 mod[eventDef.name] = new chrome.Event( 342 mod[eventDef.name] = new chrome.Event(
358 eventName, eventDef.parameters, options); 343 eventName, eventDef.parameters, options);
359 } 344 }
360 }, this); 345 }, this);
361 } 346 }
362 347
363 function addProperties(m, parentDef) { 348 function addProperties(m, parentDef) {
364 var properties = parentDef.properties; 349 var properties = parentDef.properties;
365 if (!properties) 350 if (!properties)
366 return; 351 return;
367 352
368 forEach(properties, function(propertyName, propertyDef) { 353 forEach(properties, function(propertyName, propertyDef) {
369 if (propertyName in m) 354 if (propertyName in m)
370 return; // TODO(kalman): be strict like functions/events somehow. 355 return; // TODO(kalman): be strict like functions/events somehow.
371 if (!isSchemaNodeSupported(propertyDef, platform, manifestVersion)) 356 if (!isSchemaNodeSupported(propertyDef, platform, manifestVersion))
372 return; 357 return;
373 if (!isSchemaAccessAllowed(propertyDef)) { 358 if (!GetAvailability(schema.namespace + "." +
374 addUnprivilegedAccessGetter(m, propertyName); 359 propertyName).is_available ||
360 (checkUnprivileged && !isSchemaAccessAllowed(propertyDef))) {
375 return; 361 return;
376 } 362 }
377 363
378 var value = propertyDef.value; 364 var value = propertyDef.value;
379 if (value) { 365 if (value) {
380 // Values may just have raw types as defined in the JSON, such 366 // Values may just have raw types as defined in the JSON, such
381 // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here. 367 // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here.
382 // TODO(kalman): enforce that things with a "value" property can't 368 // TODO(kalman): enforce that things with a "value" property can't
383 // define their own types. 369 // define their own types.
384 var type = propertyDef.type || typeof(value); 370 var type = propertyDef.type || typeof(value);
(...skipping 21 matching lines...) Expand all
406 } else if (type !== 'string') { 392 } else if (type !== 'string') {
407 throw new Error('NOT IMPLEMENTED (extension_api.json error): ' + 393 throw new Error('NOT IMPLEMENTED (extension_api.json error): ' +
408 'Cannot parse values for type "' + type + '"'); 394 'Cannot parse values for type "' + type + '"');
409 } 395 }
410 m[propertyName] = value; 396 m[propertyName] = value;
411 } 397 }
412 }); 398 });
413 }; 399 };
414 400
415 addProperties(mod, schema); 401 addProperties(mod, schema);
402
403 var availability = GetAvailability(schema.namespace);
404 if (!availability.is_available && Object.keys(mod).length == 0) {
405 console.error('chrome.' + schema.namespace + ' is not available: ' +
406 availability.message);
407 return;
408 }
409
416 this.runHooks_(mod); 410 this.runHooks_(mod);
417 return mod; 411 return mod;
418 } 412 }
419 }; 413 };
420 414
421 exports.Binding = Binding; 415 exports.Binding = Binding;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698