OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 for (var i = 0; i < platforms.length; i++) { | 567 for (var i = 0; i < platforms.length; i++) { |
568 if (platforms[i][0].test(navigator.appVersion)) { | 568 if (platforms[i][0].test(navigator.appVersion)) { |
569 return platforms[i][1]; | 569 return platforms[i][1]; |
570 } | 570 } |
571 } | 571 } |
572 return "unknown"; | 572 return "unknown"; |
573 } | 573 } |
574 | 574 |
575 chromeHidden.onLoad.addListener(function(extensionId, isExtensionProcess, | 575 chromeHidden.onLoad.addListener(function(extensionId, isExtensionProcess, |
576 isIncognitoProcess) { | 576 isIncognitoProcess) { |
577 if (!isExtensionProcess) | |
578 return; | |
579 | |
580 // Setup the ChromeSetting class so we can use it to construct | 577 // Setup the ChromeSetting class so we can use it to construct |
581 // ChromeSetting objects from the API definition. | 578 // ChromeSetting objects from the API definition. |
582 setupChromeSetting(); | 579 setupChromeSetting(); |
583 | 580 |
584 // Setup the ContentSetting class so we can use it to construct | 581 // Setup the ContentSetting class so we can use it to construct |
585 // ContentSetting objects from the API definition. | 582 // ContentSetting objects from the API definition. |
586 setupContentSetting(); | 583 setupContentSetting(); |
587 | 584 |
588 // |apiFunctions| is a hash of name -> object that stores the | 585 // |apiFunctions| is a hash of name -> object that stores the |
589 // name & definition of the apiFunction. Custom handling of api functions | 586 // name & definition of the apiFunction. Custom handling of api functions |
590 // is implemented by adding a "handleRequest" function to the object. | 587 // is implemented by adding a "handleRequest" function to the object. |
591 var apiFunctions = {}; | 588 var apiFunctions = {}; |
592 | 589 |
593 // Read api definitions and setup api functions in the chrome namespace. | 590 // Read api definitions and setup api functions in the chrome namespace. |
594 // TODO(rafaelw): Consider defining a json schema for an api definition | 591 // TODO(rafaelw): Consider defining a json schema for an api definition |
595 // and validating either here, in a unit_test or both. | 592 // and validating either here, in a unit_test or both. |
596 // TODO(rafaelw): Handle synchronous functions. | 593 // TODO(rafaelw): Handle synchronous functions. |
597 // TOOD(rafaelw): Consider providing some convenient override points | 594 // TOOD(rafaelw): Consider providing some convenient override points |
598 // for api functions that wish to insert themselves into the call. | 595 // for api functions that wish to insert themselves into the call. |
599 var apiDefinitions = chromeHidden.JSON.parse(GetExtensionAPIDefinition()); | 596 var apiDefinitions = GetExtensionAPIDefinition(); |
600 var platform = getPlatform(); | 597 var platform = getPlatform(); |
601 | 598 |
602 apiDefinitions.forEach(function(apiDef) { | 599 apiDefinitions.forEach(function(apiDef) { |
603 // Check platform, if apiDef has platforms key. | 600 // Check platform, if apiDef has platforms key. |
604 if (apiDef.platforms && apiDef.platforms.indexOf(platform) == -1) { | 601 if (apiDef.platforms && apiDef.platforms.indexOf(platform) == -1) { |
605 return; | 602 return; |
606 } | 603 } |
607 | 604 |
608 var module = chrome; | 605 var module = chrome; |
609 var namespaces = apiDef.namespace.split('.'); | 606 var namespaces = apiDef.namespace.split('.'); |
610 for (var index = 0, name; name = namespaces[index]; index++) { | 607 for (var index = 0, name; name = namespaces[index]; index++) { |
611 module[name] = module[name] || {}; | 608 module[name] = module[name] || {}; |
612 module = module[name]; | 609 module = module[name]; |
613 } | 610 } |
614 | 611 |
615 // Add types to global validationTypes | 612 // Add types to global validationTypes |
616 if (apiDef.types) { | 613 if (apiDef.types) { |
617 apiDef.types.forEach(function(t) { | 614 apiDef.types.forEach(function(t) { |
618 chromeHidden.validationTypes.push(t); | 615 chromeHidden.validationTypes.push(t); |
619 if (t.type == 'object' && customBindings[t.id]) { | 616 if (t.type == 'object' && customBindings[t.id]) { |
620 customBindings[t.id].prototype.setSchema(t); | 617 customBindings[t.id].prototype.setSchema(t); |
621 } | 618 } |
622 }); | 619 }); |
623 } | 620 } |
624 | 621 |
| 622 // Adds a getter that throws an access denied error to object |module| |
| 623 // for property |name| described by |schemaNode| if necessary. |
| 624 // |
| 625 // Returns true if the getter was necessary (access is disallowed), or |
| 626 // false otherwise. |
| 627 function addUnprivilegedAccessGetter(module, name, allowUnprivileged) { |
| 628 if (allowUnprivileged || isExtensionProcess) |
| 629 return false; |
| 630 |
| 631 module.__defineGetter__(name, function() { |
| 632 throw new Error( |
| 633 '"' + name + '" can only be used in extension processes. See ' + |
| 634 'the content scripts documentation for more details.'); |
| 635 }); |
| 636 return true; |
| 637 } |
| 638 |
625 // Setup Functions. | 639 // Setup Functions. |
626 if (apiDef.functions) { | 640 if (apiDef.functions) { |
627 apiDef.functions.forEach(function(functionDef) { | 641 apiDef.functions.forEach(function(functionDef) { |
628 // Module functions may have been defined earlier by hand. Don't | 642 if (functionDef.name in module || |
629 // clobber them. | 643 addUnprivilegedAccessGetter(module, functionDef.name, |
630 if (module[functionDef.name]) | 644 functionDef.unprivileged)) { |
631 return; | 645 return; |
| 646 } |
632 | 647 |
633 var apiFunction = {}; | 648 var apiFunction = {}; |
634 apiFunction.definition = functionDef; | 649 apiFunction.definition = functionDef; |
635 apiFunction.name = apiDef.namespace + "." + functionDef.name; | 650 apiFunction.name = apiDef.namespace + "." + functionDef.name; |
636 apiFunctions[apiFunction.name] = apiFunction; | 651 apiFunctions[apiFunction.name] = apiFunction; |
637 | 652 |
638 module[functionDef.name] = (function() { | 653 module[functionDef.name] = (function() { |
639 var args = arguments; | 654 var args = arguments; |
640 if (this.updateArgumentsPreValidate) | 655 if (this.updateArgumentsPreValidate) |
641 args = this.updateArgumentsPreValidate.apply(this, args); | 656 args = this.updateArgumentsPreValidate.apply(this, args); |
(...skipping 17 matching lines...) Expand all Loading... |
659 chromeHidden.validate([retval], [this.definition.returns]); | 674 chromeHidden.validate([retval], [this.definition.returns]); |
660 } | 675 } |
661 return retval; | 676 return retval; |
662 }).bind(apiFunction); | 677 }).bind(apiFunction); |
663 }); | 678 }); |
664 } | 679 } |
665 | 680 |
666 // Setup Events | 681 // Setup Events |
667 if (apiDef.events) { | 682 if (apiDef.events) { |
668 apiDef.events.forEach(function(eventDef) { | 683 apiDef.events.forEach(function(eventDef) { |
669 // Module events may have been defined earlier by hand. Don't clobber | 684 if (eventDef.name in module || |
670 // them. | 685 addUnprivilegedAccessGetter(module, eventDef.name, |
671 if (module[eventDef.name]) | 686 eventDef.unprivileged)) { |
672 return; | 687 return; |
| 688 } |
673 | 689 |
674 var eventName = apiDef.namespace + "." + eventDef.name; | 690 var eventName = apiDef.namespace + "." + eventDef.name; |
675 if (apiDef.namespace == "experimental.webRequest") { | 691 if (apiDef.namespace == "experimental.webRequest") { |
676 module[eventDef.name] = new chrome.WebRequestEvent(eventName, | 692 module[eventDef.name] = new chrome.WebRequestEvent(eventName, |
677 eventDef.parameters, eventDef.extraParameters); | 693 eventDef.parameters, eventDef.extraParameters); |
678 } else { | 694 } else { |
679 module[eventDef.name] = new chrome.Event(eventName, | 695 module[eventDef.name] = new chrome.Event(eventName, |
680 eventDef.parameters); | 696 eventDef.parameters); |
681 } | 697 } |
682 }); | 698 }); |
683 } | 699 } |
684 | 700 |
685 function addProperties(m, def) { | 701 function addProperties(m, def) { |
686 // Parse any values defined for properties. | 702 // Parse any values defined for properties. |
687 if (def.properties) { | 703 if (def.properties) { |
688 forEach(def.properties, function(prop, property) { | 704 forEach(def.properties, function(prop, property) { |
| 705 if (prop in m || |
| 706 addUnprivilegedAccessGetter(m, prop, property.unprivileged)) { |
| 707 return; |
| 708 } |
| 709 |
689 var value = property.value; | 710 var value = property.value; |
690 if (value) { | 711 if (value) { |
691 if (property.type === 'integer') { | 712 if (property.type === 'integer') { |
692 value = parseInt(value); | 713 value = parseInt(value); |
693 } else if (property.type === 'boolean') { | 714 } else if (property.type === 'boolean') { |
694 value = value === "true"; | 715 value = value === "true"; |
695 } else if (property["$ref"]) { | 716 } else if (property["$ref"]) { |
696 var constructor = customBindings[property["$ref"]]; | 717 var constructor = customBindings[property["$ref"]]; |
697 var args = value; | 718 var args = value; |
698 // For an object property, |value| is an array of constructor | 719 // For an object property, |value| is an array of constructor |
(...skipping 13 matching lines...) Expand all Loading... |
712 if (value) { | 733 if (value) { |
713 m[prop] = value; | 734 m[prop] = value; |
714 } | 735 } |
715 }); | 736 }); |
716 } | 737 } |
717 } | 738 } |
718 | 739 |
719 addProperties(module, apiDef); | 740 addProperties(module, apiDef); |
720 }); | 741 }); |
721 | 742 |
| 743 // TODO(aa): The rest of the crap below this really needs to be factored out |
| 744 // with a clean API boundary. Right now it is too soupy for me to feel |
| 745 // comfortable running in content scripts. What if people are just |
| 746 // overwriting random APIs? That would bypass our content script access |
| 747 // checks. |
| 748 if (!isExtensionProcess) |
| 749 return; |
| 750 |
722 // getTabContentses is retained for backwards compatibility | 751 // getTabContentses is retained for backwards compatibility |
723 // See http://crbug.com/21433 | 752 // See http://crbug.com/21433 |
724 chrome.extension.getTabContentses = chrome.extension.getExtensionTabs; | 753 chrome.extension.getTabContentses = chrome.extension.getExtensionTabs; |
725 // TOOD(mihaip): remove this alias once the webstore stops calling | 754 // TOOD(mihaip): remove this alias once the webstore stops calling |
726 // beginInstallWithManifest2. | 755 // beginInstallWithManifest2. |
727 // See http://crbug.com/100242 | 756 // See http://crbug.com/100242 |
728 chrome.webstorePrivate.beginInstallWithManifest2 = | 757 chrome.webstorePrivate.beginInstallWithManifest2 = |
729 chrome.webstorePrivate.beginInstallWithManifest3; | 758 chrome.webstorePrivate.beginInstallWithManifest3; |
730 | 759 |
731 apiFunctions["tabs.connect"].handleRequest = function(tabId, connectInfo) { | 760 apiFunctions["tabs.connect"].handleRequest = function(tabId, connectInfo) { |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 | 1078 |
1050 if (!chrome.tts) | 1079 if (!chrome.tts) |
1051 chrome.tts = {}; | 1080 chrome.tts = {}; |
1052 | 1081 |
1053 if (!chrome.ttsEngine) | 1082 if (!chrome.ttsEngine) |
1054 chrome.ttsEngine = {}; | 1083 chrome.ttsEngine = {}; |
1055 | 1084 |
1056 if (!chrome.experimental.downloads) | 1085 if (!chrome.experimental.downloads) |
1057 chrome.experimental.downloads = {}; | 1086 chrome.experimental.downloads = {}; |
1058 })(); | 1087 })(); |
OLD | NEW |