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

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: fixes 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
« no previous file with comments | « chrome/renderer/extensions/dispatcher.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 var schema = this.schema_; 204 var schema = this.schema_;
205 205
206 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the 206 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the
207 // supporting code. 207 // supporting code.
208 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) { 208 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) {
209 console.error('chrome.' + schema.namespace + ' is not supported on ' + 209 console.error('chrome.' + schema.namespace + ' is not supported on ' +
210 'this platform or manifest version'); 210 'this platform or manifest version');
211 return undefined; 211 return undefined;
212 } 212 }
213 213
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 = {}; 214 var mod = {};
223 215
224 var namespaces = schema.namespace.split('.'); 216 var namespaces = schema.namespace.split('.');
225 for (var index = 0, name; name = namespaces[index]; index++) { 217 for (var index = 0, name; name = namespaces[index]; index++) {
226 mod[name] = mod[name] || {}; 218 mod[name] = mod[name] || {};
227 mod = mod[name]; 219 mod = mod[name];
228 } 220 }
229 221
230 // Add types to global schemaValidator, the types we depend on from other 222 // Add types to global schemaValidator, the types we depend on from other
231 // namespaces will be added as needed. 223 // namespaces will be added as needed.
232 if (schema.types) { 224 if (schema.types) {
233 forEach(schema.types, function(i, t) { 225 forEach(schema.types, function(i, t) {
234 if (!isSchemaNodeSupported(t, platform, manifestVersion)) 226 if (!isSchemaNodeSupported(t, platform, manifestVersion))
235 return; 227 return;
236 228
237 schemaUtils.schemaValidator.addTypes(t); 229 schemaUtils.schemaValidator.addTypes(t);
238 }, this); 230 }, this);
239 } 231 }
240 232
241 // Returns whether access to the content of a schema should be denied,
242 // based on the presence of "unprivileged" and whether this is an
243 // extension process (versus e.g. a content script).
244 function isSchemaAccessAllowed(itemSchema) {
245 return (contextType == 'BLESSED_EXTENSION') ||
246 schema.unprivileged ||
247 itemSchema.unprivileged;
248 };
249
250 // Adds a getter that throws an access denied error to object |mod| 233 // Adds a getter that throws an access denied error to object |mod|
251 // for property |name|. 234 // for property |name|.
252 function addUnprivilegedAccessGetter(mod, name) { 235 function addUnprivilegedAccessGetter(mod, name) {
253 mod.__defineGetter__(name, function() { 236 mod.__defineGetter__(name, function() {
254 throw new Error( 237 throw new Error(
255 '"' + name + '" can only be used in extension processes. See ' + 238 '"' + name + '" can only be used in extension processes. See ' +
256 'the content scripts documentation for more details.'); 239 'the content scripts documentation for more details.');
257 }); 240 });
258 } 241 }
259 242
260 // Setup Functions. 243 // Setup Functions.
261 if (schema.functions) { 244 if (schema.functions) {
262 forEach(schema.functions, function(i, functionDef) { 245 forEach(schema.functions, function(i, functionDef) {
263 if (functionDef.name in mod) { 246 if (functionDef.name in mod) {
264 throw new Error('Function ' + functionDef.name + 247 throw new Error('Function ' + functionDef.name +
265 ' already defined in ' + schema.namespace); 248 ' already defined in ' + schema.namespace);
266 } 249 }
267 250
268 if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) { 251 if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) {
269 this.apiFunctions_.registerUnavailable(functionDef.name); 252 this.apiFunctions_.registerUnavailable(functionDef.name);
270 return; 253 return;
271 } 254 }
272 if (!isSchemaAccessAllowed(functionDef)) {
273 this.apiFunctions_.registerUnavailable(functionDef.name);
274 addUnprivilegedAccessGetter(mod, functionDef.name);
275 return;
276 }
277 255
278 var apiFunction = {}; 256 var apiFunction = {};
279 apiFunction.definition = functionDef; 257 apiFunction.definition = functionDef;
280 apiFunction.name = schema.namespace + '.' + functionDef.name; 258 apiFunction.name = schema.namespace + '.' + functionDef.name;
281 259
260 if (!GetAvailability(apiFunction.name).is_available) {
261 this.apiFunctions_.registerUnavailable(functionDef.name);
262 addUnprivilegedAccessGetter(mod, functionDef.name);
not at google - send to devlin 2013/05/01 20:47:04 Just leave it blank. No need for the unprivileged
cduvall 2013/05/01 23:47:10 Done.
263 return;
264 }
265
282 // TODO(aa): It would be best to run this in a unit test, but in order 266 // 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 267 // to do that we would need to better factor this code so that it
284 // doesn't depend on so much v8::Extension machinery. 268 // doesn't depend on so much v8::Extension machinery.
285 if (chromeHidden.validateAPI && 269 if (chromeHidden.validateAPI &&
286 schemaUtils.isFunctionSignatureAmbiguous( 270 schemaUtils.isFunctionSignatureAmbiguous(
287 apiFunction.definition)) { 271 apiFunction.definition)) {
288 throw new Error( 272 throw new Error(
289 apiFunction.name + ' has ambiguous optional arguments. ' + 273 apiFunction.name + ' has ambiguous optional arguments. ' +
290 'To implement custom disambiguation logic, add ' + 274 'To implement custom disambiguation logic, add ' +
291 '"allowAmbiguousOptionalArguments" to the function\'s schema.'); 275 '"allowAmbiguousOptionalArguments" to the function\'s schema.');
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 313
330 // Setup Events 314 // Setup Events
331 if (schema.events) { 315 if (schema.events) {
332 forEach(schema.events, function(i, eventDef) { 316 forEach(schema.events, function(i, eventDef) {
333 if (eventDef.name in mod) { 317 if (eventDef.name in mod) {
334 throw new Error('Event ' + eventDef.name + 318 throw new Error('Event ' + eventDef.name +
335 ' already defined in ' + schema.namespace); 319 ' already defined in ' + schema.namespace);
336 } 320 }
337 if (!isSchemaNodeSupported(eventDef, platform, manifestVersion)) 321 if (!isSchemaNodeSupported(eventDef, platform, manifestVersion))
338 return; 322 return;
339 if (!isSchemaAccessAllowed(eventDef)) { 323
324 var eventName = schema.namespace + "." + eventDef.name;
325 var options = eventDef.options || {};
not at google - send to devlin 2013/05/01 20:47:04 might as well define options after this block.
cduvall 2013/05/01 23:47:10 Done.
326 if (!GetAvailability(eventName).is_available) {
340 addUnprivilegedAccessGetter(mod, eventDef.name); 327 addUnprivilegedAccessGetter(mod, eventDef.name);
not at google - send to devlin 2013/05/01 20:47:04 ditto - no unprivileged access getter, just leave
cduvall 2013/05/01 23:47:10 Done.
341 return; 328 return;
342 } 329 }
343 330
344 var eventName = schema.namespace + "." + eventDef.name;
345 var options = eventDef.options || {};
346
347 if (eventDef.filters && eventDef.filters.length > 0) 331 if (eventDef.filters && eventDef.filters.length > 0)
348 options.supportsFilters = true; 332 options.supportsFilters = true;
349 333
350 if (this.customEvent_) { 334 if (this.customEvent_) {
351 mod[eventDef.name] = new this.customEvent_( 335 mod[eventDef.name] = new this.customEvent_(
352 eventName, eventDef.parameters, eventDef.extraParameters, 336 eventName, eventDef.parameters, eventDef.extraParameters,
353 options); 337 options);
354 } else if (eventDef.anonymous) { 338 } else if (eventDef.anonymous) {
355 mod[eventDef.name] = new chrome.Event(); 339 mod[eventDef.name] = new chrome.Event();
356 } else { 340 } else {
357 mod[eventDef.name] = new chrome.Event( 341 mod[eventDef.name] = new chrome.Event(
358 eventName, eventDef.parameters, options); 342 eventName, eventDef.parameters, options);
359 } 343 }
360 }, this); 344 }, this);
361 } 345 }
362 346
363 function addProperties(m, parentDef) { 347 function addProperties(m, parentDef) {
364 var properties = parentDef.properties; 348 var properties = parentDef.properties;
365 if (!properties) 349 if (!properties)
366 return; 350 return;
367 351
368 forEach(properties, function(propertyName, propertyDef) { 352 forEach(properties, function(propertyName, propertyDef) {
369 if (propertyName in m) 353 if (propertyName in m)
370 return; // TODO(kalman): be strict like functions/events somehow. 354 return; // TODO(kalman): be strict like functions/events somehow.
371 if (!isSchemaNodeSupported(propertyDef, platform, manifestVersion)) 355 if (!isSchemaNodeSupported(propertyDef, platform, manifestVersion))
372 return; 356 return;
373 if (!isSchemaAccessAllowed(propertyDef)) { 357 if (!GetAvailability(schema.namespace + "." +
374 addUnprivilegedAccessGetter(m, propertyName); 358 propertyName).is_available) {
359 addUnprivilegedAccessGetter(mod, propertyName);
not at google - send to devlin 2013/05/01 20:47:04 ditto
cduvall 2013/05/01 23:47:10 Done.
375 return; 360 return;
376 } 361 }
377 362
378 var value = propertyDef.value; 363 var value = propertyDef.value;
379 if (value) { 364 if (value) {
380 // Values may just have raw types as defined in the JSON, such 365 // Values may just have raw types as defined in the JSON, such
381 // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here. 366 // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here.
382 // TODO(kalman): enforce that things with a "value" property can't 367 // TODO(kalman): enforce that things with a "value" property can't
383 // define their own types. 368 // define their own types.
384 var type = propertyDef.type || typeof(value); 369 var type = propertyDef.type || typeof(value);
(...skipping 22 matching lines...) Expand all
407 throw new Error('NOT IMPLEMENTED (extension_api.json error): ' + 392 throw new Error('NOT IMPLEMENTED (extension_api.json error): ' +
408 'Cannot parse values for type "' + type + '"'); 393 'Cannot parse values for type "' + type + '"');
409 } 394 }
410 m[propertyName] = value; 395 m[propertyName] = value;
411 } 396 }
412 }); 397 });
413 }; 398 };
414 399
415 addProperties(mod, schema); 400 addProperties(mod, schema);
416 this.runHooks_(mod); 401 this.runHooks_(mod);
402
403 var availability = GetAvailability(schema.namespace);
404
405 function hasItemOfType(typeArray) {
406 return typeArray.length && !typeArray.filter(function (def) {
407 return mod.hasOwnProperty(def.name);
408 }).length;
409 }
410
411 if (!availability.is_available &&
412 (hasItemOfType(schema.events) || hasItemOfType(schema.functions))) {
not at google - send to devlin 2013/05/01 20:47:04 a simpler test may be to just check whether the mo
cduvall 2013/05/01 23:47:10 Done.
413 console.error('chrome.' + schema.namespace + ' is not available: ' +
414 availability.message);
415 return;
416 }
417
417 return mod; 418 return mod;
418 } 419 }
419 }; 420 };
420 421
421 exports.Binding = Binding; 422 exports.Binding = Binding;
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/dispatcher.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698