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

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

Issue 9423049: Make registering custom hooks with schema_generated_bindings.js safer and (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 9 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 // This script contains privileged chrome extension related javascript APIs. 5 // This script contains privileged chrome extension related javascript APIs.
6 // It is loaded by pages whose URL has the chrome-extension protocol. 6 // It is loaded by pages whose URL has the chrome-extension protocol.
7 7
8 var chrome = chrome || {}; 8 var chrome = chrome || {};
9 (function() { 9 (function() {
10 native function GetChromeHidden(); 10 native function GetChromeHidden();
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 throw new Error( 237 throw new Error(
238 "Either the path or imageData property must be specified."); 238 "Either the path or imageData property must be specified.");
239 } 239 }
240 } 240 }
241 241
242 // Stores the name and definition of each API function, with methods to 242 // Stores the name and definition of each API function, with methods to
243 // modify their behaviour (such as a custom way to handle requests to the 243 // modify their behaviour (such as a custom way to handle requests to the
244 // API, a custom callback, etc). 244 // API, a custom callback, etc).
245 function APIFunctions() { 245 function APIFunctions() {
246 this._apiFunctions = {}; 246 this._apiFunctions = {};
247 this._unavailableApiFunctions = {};
247 } 248 }
248 APIFunctions.prototype.register = function(apiName, apiFunction) { 249 APIFunctions.prototype.register = function(apiName, apiFunction) {
249 this._apiFunctions[apiName] = apiFunction; 250 this._apiFunctions[apiName] = apiFunction;
250 }; 251 };
252 // Registers a function as existing but not available, meaning that calls to
253 // the set* methods that reference this function should be ignored rather
254 // than throwing Errors.
255 APIFunctions.prototype.registerUnavailable = function(apiName) {
256 this._unavailableApiFunctions[apiName] = apiName;
257 };
251 APIFunctions.prototype._setHook = 258 APIFunctions.prototype._setHook =
252 function(apiName, propertyName, customizedFunction) { 259 function(apiName, propertyName, customizedFunction) {
253 if (this._apiFunctions.hasOwnProperty(apiName)) 260 if (this._unavailableApiFunctions.hasOwnProperty(apiName))
254 this._apiFunctions[apiName][propertyName] = customizedFunction; 261 return;
262 if (!this._apiFunctions.hasOwnProperty(apiName))
263 throw new Error('Tried to set hook for unknown API "' + apiName + '"');
264 this._apiFunctions[apiName][propertyName] = customizedFunction;
255 }; 265 };
256 APIFunctions.prototype.setHandleRequest = 266 APIFunctions.prototype.setHandleRequest =
257 function(apiName, customizedFunction) { 267 function(apiName, customizedFunction) {
258 return this._setHook(apiName, 'handleRequest', customizedFunction); 268 return this._setHook(apiName, 'handleRequest', customizedFunction);
259 }; 269 };
260 APIFunctions.prototype.setUpdateArgumentsPostValidate = 270 APIFunctions.prototype.setUpdateArgumentsPostValidate =
261 function(apiName, customizedFunction) { 271 function(apiName, customizedFunction) {
262 return this._setHook( 272 return this._setHook(
263 apiName, 'updateArgumentsPostValidate', customizedFunction); 273 apiName, 'updateArgumentsPostValidate', customizedFunction);
264 }; 274 };
265 APIFunctions.prototype.setUpdateArgumentsPreValidate = 275 APIFunctions.prototype.setUpdateArgumentsPreValidate =
266 function(apiName, customizedFunction) { 276 function(apiName, customizedFunction) {
267 return this._setHook( 277 return this._setHook(
268 apiName, 'updateArgumentsPreValidate', customizedFunction); 278 apiName, 'updateArgumentsPreValidate', customizedFunction);
269 }; 279 };
270 APIFunctions.prototype.setCustomCallback = 280 APIFunctions.prototype.setCustomCallback =
271 function(apiName, customizedFunction) { 281 function(apiName, customizedFunction) {
272 return this._setHook(apiName, 'customCallback', customizedFunction); 282 return this._setHook(apiName, 'customCallback', customizedFunction);
273 }; 283 };
274 284
275 var apiFunctions = new APIFunctions(); 285 var apiFunctions = new APIFunctions();
276 286
287 // Wraps the calls to the set* methods of APIFunctions with the namespace of
288 // an API, and validates that all calls to set* methods aren't prefixed with
289 // a namespace.
290 //
291 // For example, if constructed with 'browserAction', a call to
292 // handleRequest('foo') will be transformed into
293 // handleRequest('browserAction.foo').
294 //
295 // Likewise, if a call to handleRequest is called with 'browserAction.foo',
296 // it will throw an error.
297 //
298 // These help with isolating custom bindings from each other.
299 function NamespacedAPIFunctions(namespace, delegate) {
300 var self = this;
301 function wrap(methodName) {
302 self[methodName] = function(apiName, customizedFunction) {
303 var prefix = namespace + '.';
304 if (apiName.indexOf(prefix) === 0) {
305 throw new Error(methodName + ' called with "' + apiName +
306 '" which has a "' + prefix + '" prefix. ' +
307 'This is unnecessary and must be left out.');
308 }
309 return delegate[methodName].call(delegate,
310 prefix + apiName, customizedFunction);
311 };
312 }
313
314 wrap('contains');
315 wrap('setHandleRequest');
316 wrap('setUpdateArgumentsPostValidate');
317 wrap('setUpdateArgumentsPreValidate');
318 wrap('setCustomCallback');
319 }
320
277 // 321 //
278 // The API through which the ${api_name}_custom_bindings.js files customize 322 // The API through which the ${api_name}_custom_bindings.js files customize
279 // their API bindings beyond what can be generated. 323 // their API bindings beyond what can be generated.
280 // 324 //
281 // There are 2 types of customizations available: those which are required in 325 // There are 2 types of customizations available: those which are required in
282 // order to do the schema generation (registerCustomEvent and 326 // order to do the schema generation (registerCustomEvent and
283 // registerCustomType), and those which can only run after the bindings have 327 // registerCustomType), and those which can only run after the bindings have
284 // been generated (registerCustomHook). 328 // been generated (registerCustomHook).
285 // 329 //
286 330
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 }); 467 });
424 } 468 }
425 469
426 // Setup Functions. 470 // Setup Functions.
427 if (apiDef.functions) { 471 if (apiDef.functions) {
428 apiDef.functions.forEach(function(functionDef) { 472 apiDef.functions.forEach(function(functionDef) {
429 if (functionDef.name in mod) { 473 if (functionDef.name in mod) {
430 throw new Error('Function ' + functionDef.name + 474 throw new Error('Function ' + functionDef.name +
431 ' already defined in ' + apiDef.namespace); 475 ' already defined in ' + apiDef.namespace);
432 } 476 }
433 if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) 477
478 var apiFunctionName = apiDef.namespace + "." + functionDef.name;
479
480 if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) {
481 apiFunctions.registerUnavailable(apiFunctionName);
434 return; 482 return;
483 }
435 if (!isSchemaAccessAllowed(functionDef)) { 484 if (!isSchemaAccessAllowed(functionDef)) {
485 apiFunctions.registerUnavailable(apiFunctionName);
436 addUnprivilegedAccessGetter(mod, functionDef.name); 486 addUnprivilegedAccessGetter(mod, functionDef.name);
437 return; 487 return;
438 } 488 }
439 489
440 var apiFunction = {}; 490 var apiFunction = {};
441 apiFunction.definition = functionDef; 491 apiFunction.definition = functionDef;
442 apiFunction.name = apiDef.namespace + "." + functionDef.name; 492 apiFunction.name = apiFunctionName;
443 apiFunctions.register(apiFunction.name, apiFunction); 493 apiFunctions.register(apiFunctionName, apiFunction);
444 494
445 mod[functionDef.name] = (function() { 495 mod[functionDef.name] = (function() {
446 var args = arguments; 496 var args = arguments;
447 if (this.updateArgumentsPreValidate) 497 if (this.updateArgumentsPreValidate)
448 args = this.updateArgumentsPreValidate.apply(this, args); 498 args = this.updateArgumentsPreValidate.apply(this, args);
449 chromeHidden.validate(args, this.definition.parameters); 499 chromeHidden.validate(args, this.definition.parameters);
450 if (this.updateArgumentsPostValidate) 500 if (this.updateArgumentsPostValidate)
451 args = this.updateArgumentsPostValidate.apply(this, args); 501 args = this.updateArgumentsPostValidate.apply(this, args);
452 502
453 var retval; 503 var retval;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 return; 607 return;
558 608
559 var hook = customHooks[apiDef.namespace]; 609 var hook = customHooks[apiDef.namespace];
560 if (!hook) 610 if (!hook)
561 return; 611 return;
562 612
563 // Pass through the public API of schema_generated_bindings, to be used 613 // Pass through the public API of schema_generated_bindings, to be used
564 // by custom bindings JS files. Create a new one so that bindings can't 614 // by custom bindings JS files. Create a new one so that bindings can't
565 // interfere with each other. 615 // interfere with each other.
566 hook({ 616 hook({
567 apiFunctions: apiFunctions, 617 apiFunctions: new NamespacedAPIFunctions(apiDef.namespace,
618 apiFunctions),
568 sendRequest: sendRequest, 619 sendRequest: sendRequest,
569 setIcon: setIcon, 620 setIcon: setIcon,
570 apiDefinitions: apiDefinitions, 621 apiDefinitions: apiDefinitions,
571 }, extensionId); 622 }, extensionId);
572 }); 623 });
573 624
574 // TODO(mihaip): remove this alias once the webstore stops calling 625 // TODO(mihaip): remove this alias once the webstore stops calling
575 // beginInstallWithManifest2. 626 // beginInstallWithManifest2.
576 // See http://crbug.com/100242 627 // See http://crbug.com/100242
577 if (chrome.webstorePrivate) { 628 if (chrome.webstorePrivate) {
578 chrome.webstorePrivate.beginInstallWithManifest2 = 629 chrome.webstorePrivate.beginInstallWithManifest2 =
579 chrome.webstorePrivate.beginInstallWithManifest3; 630 chrome.webstorePrivate.beginInstallWithManifest3;
580 } 631 }
581 632
582 if (chrome.test) 633 if (chrome.test)
583 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; 634 chrome.test.getApiDefinitions = GetExtensionAPIDefinition;
584 }); 635 });
585 })(); 636 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698