OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 GetExtensionAPIDefinition(); | 10 native function GetExtensionAPIDefinition(); |
(...skipping 20 matching lines...) Expand all Loading... | |
31 return; | 31 return; |
32 } | 32 } |
33 chrome.initExtension(extensionId, false); | 33 chrome.initExtension(extensionId, false); |
34 }); | 34 }); |
35 return; | 35 return; |
36 } | 36 } |
37 | 37 |
38 if (!chrome) | 38 if (!chrome) |
39 chrome = {}; | 39 chrome = {}; |
40 | 40 |
41 function forEach(dict, f) { | |
42 for (key in dict) { | |
43 if (dict.hasOwnProperty(key)) | |
44 f(key, dict[key]); | |
45 } | |
46 } | |
47 | |
41 // Validate arguments. | 48 // Validate arguments. |
42 chromeHidden.validationTypes = []; | 49 chromeHidden.validationTypes = {}; |
43 chromeHidden.validate = function(args, schemas) { | 50 chromeHidden.validate = function(args, schemas) { |
44 if (args.length > schemas.length) | 51 if (args.length > schemas.length) |
45 throw new Error("Too many arguments."); | 52 throw new Error("Too many arguments."); |
46 | 53 |
47 for (var i = 0; i < schemas.length; i++) { | 54 for (var i = 0; i < schemas.length; i++) { |
48 if (i in args && args[i] !== null && args[i] !== undefined) { | 55 if (i in args && args[i] !== null && args[i] !== undefined) { |
49 var validator = new chromeHidden.JSONSchemaValidator(); | 56 var validator = new chromeHidden.JSONSchemaValidator(); |
50 validator.addTypes(chromeHidden.validationTypes); | 57 forEach(chromeHidden.validationTypes, function(id, type) { |
58 validator.addTypes(type); | |
59 }); | |
51 validator.validate(args[i], schemas[i]); | 60 validator.validate(args[i], schemas[i]); |
52 if (validator.errors.length == 0) | 61 if (validator.errors.length == 0) |
53 continue; | 62 continue; |
54 | 63 |
55 var message = "Invalid value for argument " + (i + 1) + ". "; | 64 var message = "Invalid value for argument " + (i + 1) + ". "; |
56 for (var i = 0, err; err = validator.errors[i]; i++) { | 65 for (var i = 0, err; err = validator.errors[i]; i++) { |
57 if (err.path) { | 66 if (err.path) { |
58 message += "Property '" + err.path + "': "; | 67 message += "Property '" + err.path + "': "; |
59 } | 68 } |
60 message += err.message; | 69 message += err.message; |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 var callback = function(errorMessage) { | 418 var callback = function(errorMessage) { |
410 if (errorMessage) | 419 if (errorMessage) |
411 chrome.experimental.tts.speakCompleted(requestId, errorMessage); | 420 chrome.experimental.tts.speakCompleted(requestId, errorMessage); |
412 else | 421 else |
413 chrome.experimental.tts.speakCompleted(requestId); | 422 chrome.experimental.tts.speakCompleted(requestId); |
414 }; | 423 }; |
415 chrome.Event.prototype.dispatch.apply(this, [text, options, callback]); | 424 chrome.Event.prototype.dispatch.apply(this, [text, options, callback]); |
416 }; | 425 }; |
417 } | 426 } |
418 | 427 |
428 var customInitializers = {}; | |
429 | |
430 function setupPreferences() { | |
431 var parameters = {}; | |
432 chromeHidden.validationTypes['Preference'].functions.forEach(function(f) { | |
433 parameters[f.name] = f.parameters; | |
434 }); | |
435 | |
436 customInitializers['Preference'] = function(prefKey, valueSchema) { | |
437 var getSchema = parameters.get; | |
438 var extendedGetSchema = getSchema.slice(); | |
Aaron Boodman
2011/02/23 01:17:26
Can you find a way to generalize this such that ev
Bernhard Bauer
2011/02/23 17:33:27
Done. I pulled out a function |extendSchema|.
| |
439 extendedGetSchema.unshift({'type': 'string'}); | |
440 this.get = function(details, callback) { | |
441 chromeHidden.validate([details, callback], getSchema); | |
442 return sendRequest('experimental.preferences.get', | |
443 [prefKey, details, callback], | |
444 extendedGetSchema); | |
445 }; | |
446 var setSchema = parameters.set.slice(); | |
447 setSchema[0].properties.value = valueSchema; | |
448 var extendedSetSchema = setSchema.slice(); | |
449 extendedSetSchema.unshift({'type': 'string'}); | |
450 this.set = function(details, callback) { | |
451 chromeHidden.validate([details, callback], setSchema); | |
452 return sendRequest('experimental.preferences.set', | |
453 [prefKey, details, callback], | |
454 extendedSetSchema); | |
455 }; | |
456 }; | |
457 } | |
458 | |
419 chromeHidden.onLoad.addListener(function (extensionId) { | 459 chromeHidden.onLoad.addListener(function (extensionId) { |
420 if (!extensionId) { | 460 if (!extensionId) { |
421 return; | 461 return; |
422 } | 462 } |
423 chrome.initExtension(extensionId, false, IsIncognitoProcess()); | 463 chrome.initExtension(extensionId, false, IsIncognitoProcess()); |
424 | 464 |
425 // |apiFunctions| is a hash of name -> object that stores the | 465 // |apiFunctions| is a hash of name -> object that stores the |
426 // name & definition of the apiFunction. Custom handling of api functions | 466 // name & definition of the apiFunction. Custom handling of api functions |
427 // is implemented by adding a "handleRequest" function to the object. | 467 // is implemented by adding a "handleRequest" function to the object. |
428 var apiFunctions = {}; | 468 var apiFunctions = {}; |
429 | 469 |
470 var customObjects = {}; | |
471 | |
430 // Read api definitions and setup api functions in the chrome namespace. | 472 // Read api definitions and setup api functions in the chrome namespace. |
431 // TODO(rafaelw): Consider defining a json schema for an api definition | 473 // TODO(rafaelw): Consider defining a json schema for an api definition |
432 // and validating either here, in a unit_test or both. | 474 // and validating either here, in a unit_test or both. |
433 // TODO(rafaelw): Handle synchronous functions. | 475 // TODO(rafaelw): Handle synchronous functions. |
434 // TOOD(rafaelw): Consider providing some convenient override points | 476 // TOOD(rafaelw): Consider providing some convenient override points |
435 // for api functions that wish to insert themselves into the call. | 477 // for api functions that wish to insert themselves into the call. |
436 var apiDefinitions = chromeHidden.JSON.parse(GetExtensionAPIDefinition()); | 478 var apiDefinitions = chromeHidden.JSON.parse(GetExtensionAPIDefinition()); |
437 | 479 |
438 apiDefinitions.forEach(function(apiDef) { | 480 apiDefinitions.forEach(function(apiDef) { |
439 var module = chrome; | 481 var module = chrome; |
440 var namespaces = apiDef.namespace.split('.'); | 482 var namespaces = apiDef.namespace.split('.'); |
441 for (var index = 0, name; name = namespaces[index]; index++) { | 483 for (var index = 0, name; name = namespaces[index]; index++) { |
442 module[name] = module[name] || {}; | 484 module[name] = module[name] || {}; |
443 module = module[name]; | 485 module = module[name]; |
444 } | 486 } |
445 | 487 |
446 // Add types to global validationTypes | 488 // Add types to global validationTypes |
447 if (apiDef.types) { | 489 if (apiDef.types) { |
448 apiDef.types.forEach(function(t) { | 490 apiDef.types.forEach(function(t) { |
449 chromeHidden.validationTypes.push(t); | 491 chromeHidden.validationTypes[t.id] = t; |
492 if (t.type == 'object' && t.customBindings) { | |
Aaron Boodman
2011/02/23 01:17:26
The customBindings flag seems unnecessary since yo
Bernhard Bauer
2011/02/23 17:33:27
Done.
| |
493 function CustomBindingsObject(args) { | |
Aaron Boodman
2011/02/23 01:17:26
This object doesn't seem to do a lot right now. I
Bernhard Bauer
2011/02/23 17:33:27
Done. I'm still using CustomBindingsObject as a ba
| |
494 this.initArgs = args; | |
495 } | |
496 customObjects[t.id] = CustomBindingsObject; | |
497 | |
498 t.functions.forEach(function(f) { | |
499 CustomBindingsObject.prototype[f.name] = function() { | |
500 customInitializers[t.customBindings].apply(this, this.initArgs); | |
501 delete this.initArgs; | |
502 this[f.name].apply(this, arguments); | |
503 }; | |
504 }); | |
505 } | |
450 }); | 506 }); |
451 } | 507 } |
452 | 508 |
453 // Setup Functions. | 509 // Setup Functions. |
454 if (apiDef.functions) { | 510 if (apiDef.functions) { |
455 apiDef.functions.forEach(function(functionDef) { | 511 apiDef.functions.forEach(function(functionDef) { |
456 // Module functions may have been defined earlier by hand. Don't | 512 // Module functions may have been defined earlier by hand. Don't |
457 // clobber them. | 513 // clobber them. |
458 if (module[functionDef.name]) | 514 if (module[functionDef.name]) |
459 return; | 515 return; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
507 } else { | 563 } else { |
508 module[eventDef.name] = new chrome.Event(eventName, | 564 module[eventDef.name] = new chrome.Event(eventName, |
509 eventDef.parameters); | 565 eventDef.parameters); |
510 } | 566 } |
511 }); | 567 }); |
512 } | 568 } |
513 | 569 |
514 | 570 |
515 // Parse any values defined for properties. | 571 // Parse any values defined for properties. |
516 if (apiDef.properties) { | 572 if (apiDef.properties) { |
517 for (var prop in apiDef.properties) { | 573 forEach(apiDef.properties, function(prop, property) { |
518 if (!apiDef.properties.hasOwnProperty(prop)) | |
519 continue; | |
520 | |
521 var property = apiDef.properties[prop]; | |
522 if (property.value) { | 574 if (property.value) { |
523 var value = property.value; | 575 var value = property.value; |
524 if (property.type === 'integer') { | 576 if (property.type === 'integer') { |
525 value = parseInt(value); | 577 value = parseInt(value); |
526 } else if (property.type === 'boolean') { | 578 } else if (property.type === 'boolean') { |
527 value = value === "true"; | 579 value = value === "true"; |
580 } else if (property["$ref"]) { | |
581 var proto = customObjects[property["$ref"]]; | |
Aaron Boodman
2011/02/23 01:17:26
naming nit: I think this should really be 'ctor' o
Bernhard Bauer
2011/02/23 17:33:27
Done. I think constructor only has a special meani
| |
582 value = new proto(value); | |
528 } else if (property.type !== 'string') { | 583 } else if (property.type !== 'string') { |
529 throw "NOT IMPLEMENTED (extension_api.json error): Cannot " + | 584 throw "NOT IMPLEMENTED (extension_api.json error): Cannot " + |
530 "parse values for type \"" + property.type + "\""; | 585 "parse values for type \"" + property.type + "\""; |
531 } | 586 } |
532 module[prop] = value; | 587 module[prop] = value; |
533 } | 588 } |
534 } | 589 }); |
535 } | 590 } |
536 | 591 |
537 // getTabContentses is retained for backwards compatibility | 592 // getTabContentses is retained for backwards compatibility |
538 // See http://crbug.com/21433 | 593 // See http://crbug.com/21433 |
539 chrome.extension.getTabContentses = chrome.extension.getExtensionTabs; | 594 chrome.extension.getTabContentses = chrome.extension.getExtensionTabs; |
540 }); | 595 }); |
541 | 596 |
542 apiFunctions["tabs.connect"].handleRequest = function(tabId, connectInfo) { | 597 apiFunctions["tabs.connect"].handleRequest = function(tabId, connectInfo) { |
543 var name = ""; | 598 var name = ""; |
544 if (connectInfo) { | 599 if (connectInfo) { |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 | 836 |
782 if (chrome.test) { | 837 if (chrome.test) { |
783 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; | 838 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; |
784 } | 839 } |
785 | 840 |
786 setupPageActionEvents(extensionId); | 841 setupPageActionEvents(extensionId); |
787 setupToolstripEvents(GetRenderViewId()); | 842 setupToolstripEvents(GetRenderViewId()); |
788 setupHiddenContextMenuEvent(extensionId); | 843 setupHiddenContextMenuEvent(extensionId); |
789 setupOmniboxEvents(); | 844 setupOmniboxEvents(); |
790 setupTtsEvents(); | 845 setupTtsEvents(); |
846 setupPreferences(); | |
791 }); | 847 }); |
792 | 848 |
793 if (!chrome.experimental) | 849 if (!chrome.experimental) |
794 chrome.experimental = {}; | 850 chrome.experimental = {}; |
795 | 851 |
796 if (!chrome.experimental.accessibility) | 852 if (!chrome.experimental.accessibility) |
797 chrome.experimental.accessibility = {}; | 853 chrome.experimental.accessibility = {}; |
798 | 854 |
799 if (!chrome.experimental.tts) | 855 if (!chrome.experimental.tts) |
800 chrome.experimental.tts = {}; | 856 chrome.experimental.tts = {}; |
801 })(); | 857 })(); |
OLD | NEW |