Chromium Code Reviews| 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 |