| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_H_ |
| #define CHROME_COMMON_EXTENSIONS_EXTENSION_H_ |
| |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/file_path.h" |
| #include "base/scoped_ptr.h" |
| #include "base/values.h" |
| #include "base/version.h" |
| #include "chrome/common/extensions/extension_action.h" |
| #include "chrome/common/extensions/extension_resource.h" |
| #include "chrome/common/extensions/user_script.h" |
| #include "chrome/common/extensions/url_pattern.h" |
| #include "googleurl/src/gurl.h" |
| #include "testing/gtest/include/gtest/gtest_prod.h" |
| |
| // Represents a Chrome extension. |
| class Extension { |
| public: |
| typedef std::vector<URLPattern> URLPatternList; |
| typedef std::map<const std::string, GURL> URLOverrideMap; |
| |
| // What an extension was loaded from. |
| // NOTE: These values are stored as integers in the preferences, so you |
| // really don't want to change any existing ones. |
| enum Location { |
| INVALID, |
| INTERNAL, // A crx file from the internal Extensions directory. |
| EXTERNAL_PREF, // A crx file from an external directory (via prefs). |
| EXTERNAL_REGISTRY, // A crx file from an external directory (via eg the |
| // registry on Windows). |
| LOAD, // --load-extension. |
| COMPONENT // An integral component of Chrome itself, which happens |
| // to be implemented as an extension. We don't show |
| // these in the management UI. |
| }; |
| |
| enum State { |
| DISABLED = 0, |
| ENABLED, |
| KILLBIT, // Don't install/upgrade (applies to external extensions only). |
| |
| NUM_STATES |
| }; |
| |
| enum InstallType { |
| INSTALL_ERROR, |
| DOWNGRADE, |
| REINSTALL, |
| UPGRADE, |
| NEW_INSTALL |
| }; |
| |
| // NOTE: If you change this list, you should also change kIconSizes in the cc |
| // file. |
| enum Icons { |
| EXTENSION_ICON_LARGE = 128, |
| EXTENSION_ICON_MEDIUM = 48, |
| EXTENSION_ICON_SMALL = 32, |
| EXTENSION_ICON_BITTY = 16, |
| }; |
| |
| enum AppLaunchWindowType { |
| APP, |
| PANEL |
| }; |
| |
| // Icon sizes used by the extension system. |
| static const int kIconSizes[]; |
| |
| // Max size (both dimensions) for browser and page actions. |
| static const int kPageActionIconMaxSize; |
| static const int kBrowserActionIconMaxSize; |
| |
| // Each permission is a module that the extension is permitted to use. |
| static const char* kTabPermission; |
| static const char* kBookmarkPermission; |
| static const char* kNotificationPermission; |
| static const char* kExperimentalPermission; |
| static const char* kIncognitoPermission; |
| static const char* kUnlimitedStoragePermission; |
| |
| static const char* kPermissionNames[]; |
| static const size_t kNumPermissions; |
| |
| // An NPAPI plugin included in the extension. |
| struct PluginInfo { |
| FilePath path; // Path to the plugin. |
| bool is_public; // False if only this extension can load this plugin. |
| }; |
| |
| // A toolstrip and its associated mole. |
| struct ToolstripInfo { |
| ToolstripInfo() : mole_height(0) {} |
| |
| GURL toolstrip; |
| GURL mole; |
| int mole_height; |
| }; |
| |
| // The name of the manifest inside an extension. |
| static const FilePath::CharType kManifestFilename[]; |
| |
| // The name of locale folder inside an extension. |
| static const FilePath::CharType kLocaleFolder[]; |
| |
| // The name of the messages file inside an extension. |
| static const FilePath::CharType kMessagesFilename[]; |
| |
| #if defined(OS_WIN) |
| static const char* kExtensionRegistryPath; |
| #endif |
| |
| // The number of bytes in a legal id. |
| static const size_t kIdSize; |
| |
| // The mimetype used for extensions. |
| static const char kMimeType[]; |
| |
| explicit Extension(const FilePath& path); |
| virtual ~Extension(); |
| |
| // Checks to see if the extension has a valid ID. |
| static bool IdIsValid(const std::string& id); |
| |
| // Returns true if the specified file is an extension. |
| static bool IsExtension(const FilePath& file_name); |
| |
| // Whether the |location| is external or not. |
| static inline bool IsExternalLocation(Location location) { |
| return location == Extension::EXTERNAL_PREF || |
| location == Extension::EXTERNAL_REGISTRY; |
| } |
| |
| // Returns an absolute url to a resource inside of an extension. The |
| // |extension_url| argument should be the url() from an Extension object. The |
| // |relative_path| can be untrusted user input. The returned URL will either |
| // be invalid() or a child of |extension_url|. |
| // NOTE: Static so that it can be used from multiple threads. |
| static GURL GetResourceURL(const GURL& extension_url, |
| const std::string& relative_path); |
| GURL GetResourceURL(const std::string& relative_path) { |
| return GetResourceURL(url(), relative_path); |
| } |
| |
| // Returns an extension resource object. |relative_path| should be UTF8 |
| // encoded. |
| ExtensionResource GetResource(const std::string& relative_path); |
| |
| // As above, but with |relative_path| following the file system's encoding. |
| ExtensionResource GetResource(const FilePath& relative_path); |
| |
| // |input| is expected to be the text of an rsa public or private key. It |
| // tolerates the presence or absence of bracking header/footer like this: |
| // -----(BEGIN|END) [RSA PUBLIC/PRIVATE] KEY----- |
| // and may contain newlines. |
| static bool ParsePEMKeyBytes(const std::string& input, std::string* output); |
| |
| // Does a simple base64 encoding of |input| into |output|. |
| static bool ProducePEM(const std::string& input, std::string* output); |
| |
| // Generates an extension ID from arbitrary input. The same input string will |
| // always generate the same output ID. |
| static bool GenerateId(const std::string& input, std::string* output); |
| |
| // Expects base64 encoded |input| and formats into |output| including |
| // the appropriate header & footer. |
| static bool FormatPEMForFileOutput(const std::string input, |
| std::string* output, bool is_public); |
| |
| // Determine whether |new_extension| has increased privileges compared to |
| // |old_extension|. |
| static bool IsPrivilegeIncrease(Extension* old_extension, |
| Extension* new_extension); |
| |
| // Given an extension and icon size, read it if present and decode it into |
| // result. |
| static void DecodeIcon(Extension* extension, |
| Icons icon_size, |
| scoped_ptr<SkBitmap>* result); |
| |
| // Given an icon_path and icon size, read it if present and decode it into |
| // result. |
| static void DecodeIconFromPath(const FilePath& icon_path, |
| Icons icon_size, |
| scoped_ptr<SkBitmap>* result); |
| |
| // Initialize the extension from a parsed manifest. |
| // Usually, the id of an extension is generated by the "key" property of |
| // its manifest, but if |require_key| is |false|, a temporary ID will be |
| // generated based on the path. |
| bool InitFromValue(const DictionaryValue& value, bool require_key, |
| std::string* error); |
| |
| const FilePath& path() const { return path_; } |
| void set_path(const FilePath& path) { path_ = path; } |
| const GURL& url() const { return extension_url_; } |
| Location location() const { return location_; } |
| void set_location(Location location) { location_ = location; } |
| const std::string& id() const { return id_; } |
| const Version* version() const { return version_.get(); } |
| // String representation of the version number. |
| const std::string VersionString() const; |
| const std::string& name() const { return name_; } |
| const std::string& public_key() const { return public_key_; } |
| const std::string& description() const { return description_; } |
| bool converted_from_user_script() const { |
| return converted_from_user_script_; |
| } |
| const UserScriptList& content_scripts() const { return content_scripts_; } |
| ExtensionAction* page_action() const { return page_action_.get(); } |
| ExtensionAction* browser_action() const { return browser_action_.get(); } |
| const std::vector<PluginInfo>& plugins() const { return plugins_; } |
| const GURL& background_url() const { return background_url_; } |
| const GURL& options_url() const { return options_url_; } |
| const std::vector<ToolstripInfo>& toolstrips() const { return toolstrips_; } |
| const std::vector<std::string>& api_permissions() const { |
| return api_permissions_; |
| } |
| const URLPatternList& host_permissions() const { |
| return host_permissions_; |
| } |
| |
| // Returns true if the extension has permission to execute script on a |
| // particular host. |
| // TODO(aa): Also use this in the renderer, for normal content script |
| // injection. Currently, that has its own copy of this code. |
| bool CanExecuteScriptOnHost(const GURL& url, std::string* error) const; |
| |
| // Returns true if the extension has the specified API permission. |
| bool HasApiPermission(const std::string& permission) const { |
| return std::find(api_permissions_.begin(), api_permissions_.end(), |
| permission) != api_permissions_.end(); |
| } |
| |
| // Returns the set of hosts that the extension effectively has access to. This |
| // is used in the permissions UI and is a combination of the hosts accessible |
| // through content scripts and the hosts accessible through XHR. |
| const std::set<std::string> GetEffectiveHostPermissions() const; |
| |
| // Whether the extension has access to all hosts. This is true if there is |
| // a content script that matches all hosts, or if there is a host permission |
| // for all hosts. |
| bool HasAccessToAllHosts() const; |
| |
| const GURL& update_url() const { return update_url_; } |
| const std::map<int, std::string>& icons() const { return icons_; } |
| |
| // Theme-related. |
| DictionaryValue* GetThemeImages() const { return theme_images_.get(); } |
| DictionaryValue* GetThemeColors() const { return theme_colors_.get(); } |
| DictionaryValue* GetThemeTints() const { return theme_tints_.get(); } |
| DictionaryValue* GetThemeDisplayProperties() const { |
| return theme_display_properties_.get(); |
| } |
| bool IsTheme() const { return is_theme_; } |
| |
| // Returns a list of paths (relative to the extension dir) for images that |
| // the browser might load (like themes and page action icons). |
| std::set<FilePath> GetBrowserImages(); |
| |
| // Returns an absolute path to the given icon inside of the extension. Returns |
| // an empty FilePath if the extension does not have that icon. |
| ExtensionResource GetIconPath(Icons icon); |
| |
| const DictionaryValue* manifest_value() const { |
| return manifest_value_.get(); |
| } |
| |
| const std::string default_locale() const { return default_locale_; } |
| |
| // Chrome URL overrides (see ExtensionOverrideUI). |
| const URLOverrideMap& GetChromeURLOverrides() const { |
| return chrome_url_overrides_; |
| } |
| |
| // Runtime data: |
| // Put dynamic data about the state of a running extension below. |
| |
| // Whether the background page, if any, is ready. We don't load other |
| // components until then. If there is no background page, we consider it to |
| // be ready. |
| bool GetBackgroundPageReady(); |
| void SetBackgroundPageReady(); |
| |
| // Getter and setter for the flag that specifies whether the extension is |
| // being upgraded. |
| bool being_upgraded() const { return being_upgraded_; } |
| void set_being_upgraded(bool value) { being_upgraded_ = value; } |
| |
| // App stuff. |
| const URLPatternList& app_extent() const { return app_extent_; } |
| const GURL& app_launch_url() const { return app_launch_url_; } |
| bool IsApp() const { return !app_launch_url_.is_empty(); } |
| AppLaunchWindowType app_launch_window_type() { |
| return app_launch_window_type_; |
| } |
| |
| private: |
| // Helper method that loads a UserScript object from a |
| // dictionary in the content_script list of the manifest. |
| bool LoadUserScriptHelper(const DictionaryValue* content_script, |
| int definition_index, |
| std::string* error, |
| UserScript* result); |
| |
| // Helper method that loads either the include_globs or exclude_globs list |
| // from an entry in the content_script lists of the manifest. |
| bool LoadGlobsHelper(const DictionaryValue* content_script, |
| int content_script_index, |
| const wchar_t* globs_property_name, |
| std::string* error, |
| void(UserScript::*add_method)(const std::string& glob), |
| UserScript *instance); |
| |
| // Helper method to load an ExtensionAction from the page_action or |
| // browser_action entries in the manifest. |
| ExtensionAction* LoadExtensionActionHelper( |
| const DictionaryValue* extension_action, std::string* error); |
| |
| // Figures out if a source contains keys not associated with themes - we |
| // don't want to allow scripts and such to be bundled with themes. |
| bool ContainsNonThemeKeys(const DictionaryValue& source); |
| |
| // Apps don't have access to all extension features. This enforces those |
| // restrictions. |
| bool ContainsNonAppKeys(const DictionaryValue& source); |
| |
| // Helper method to verify the app section of the manifest. |
| bool LoadAppHelper(const DictionaryValue* app, std::string* error); |
| |
| // Returns true if the string is one of the known api permissions (see |
| // kPermissionNames). |
| bool IsAPIPermission(const std::string& permission); |
| |
| // The absolute path to the directory the extension is stored in. |
| FilePath path_; |
| |
| // The base extension url for the extension. |
| GURL extension_url_; |
| |
| // The location the extension was loaded from. |
| Location location_; |
| |
| // A human-readable ID for the extension. The convention is to use something |
| // like 'com.example.myextension', but this is not currently enforced. An |
| // extension's ID is used in things like directory structures and URLs, and |
| // is expected to not change across versions. In the case of conflicts, |
| // updates will only be allowed if the extension can be validated using the |
| // previous version's update key. |
| std::string id_; |
| |
| // The extension's version. |
| scoped_ptr<Version> version_; |
| |
| // The extension's human-readable name. |
| std::string name_; |
| |
| // An optional longer description of the extension. |
| std::string description_; |
| |
| // True if the extension was generated from a user script. (We show slightly |
| // different UI if so). |
| bool converted_from_user_script_; |
| |
| // Paths to the content scripts the extension contains. |
| UserScriptList content_scripts_; |
| |
| // The extension's page action, if any. |
| scoped_ptr<ExtensionAction> page_action_; |
| |
| // The extension's browser action, if any. |
| scoped_ptr<ExtensionAction> browser_action_; |
| |
| // Optional list of NPAPI plugins and associated properties. |
| std::vector<PluginInfo> plugins_; |
| |
| // Optional URL to a master page of which a single instance should be always |
| // loaded in the background. |
| GURL background_url_; |
| |
| // Optional URL to a page for setting options/preferences. |
| GURL options_url_; |
| |
| // Optional list of toolstrips_ and associated properties. |
| std::vector<ToolstripInfo> toolstrips_; |
| |
| // The public key ('key' in the manifest) used to sign the contents of the |
| // crx package ('signature' in the manifest) |
| std::string public_key_; |
| |
| // A map of resource id's to relative file paths. |
| scoped_ptr<DictionaryValue> theme_images_; |
| |
| // A map of color names to colors. |
| scoped_ptr<DictionaryValue> theme_colors_; |
| |
| // A map of color names to colors. |
| scoped_ptr<DictionaryValue> theme_tints_; |
| |
| // A map of display properties. |
| scoped_ptr<DictionaryValue> theme_display_properties_; |
| |
| // Whether the extension is a theme - if it is, certain things are disabled. |
| bool is_theme_; |
| |
| // The set of module-level APIs this extension can use. |
| std::vector<std::string> api_permissions_; |
| |
| // The sites this extension has permission to talk to (using XHR, etc). |
| URLPatternList host_permissions_; |
| |
| // The paths to the icons the extension contains mapped by their width. |
| std::map<int, std::string> icons_; |
| |
| // URL for fetching an update manifest |
| GURL update_url_; |
| |
| // A copy of the manifest that this extension was created from. |
| scoped_ptr<DictionaryValue> manifest_value_; |
| |
| // Default locale for fall back. Can be empty if extension is not localized. |
| std::string default_locale_; |
| |
| // A map of chrome:// hostnames (newtab, downloads, etc.) to Extension URLs |
| // which override the handling of those URLs. |
| URLOverrideMap chrome_url_overrides_; |
| |
| // Describes the space of URLs that are displayed in the app's custom frame. |
| URLPatternList app_extent_; |
| |
| // The URL an app should launch to. |
| GURL app_launch_url_; |
| |
| // The type of window to start when the application is launched. |
| AppLaunchWindowType app_launch_window_type_; |
| |
| // Runtime data: |
| |
| // True if the background page is ready. |
| bool background_page_ready_; |
| |
| // True while the extension is being upgraded. |
| bool being_upgraded_; |
| |
| FRIEND_TEST(ExtensionTest, LoadPageActionHelper); |
| FRIEND_TEST(TabStripModelTest, Apps); |
| |
| DISALLOW_COPY_AND_ASSIGN(Extension); |
| }; |
| |
| typedef std::vector<Extension*> ExtensionList; |
| |
| // Handy struct to pass core extension info around. |
| struct ExtensionInfo { |
| ExtensionInfo(const DictionaryValue* manifest, |
| const std::string& id, |
| const FilePath& path, |
| Extension::Location location) |
| : extension_id(id), |
| extension_path(path), |
| extension_location(location) { |
| if (manifest) |
| extension_manifest.reset( |
| static_cast<DictionaryValue*>(manifest->DeepCopy())); |
| } |
| |
| scoped_ptr<DictionaryValue> extension_manifest; |
| std::string extension_id; |
| FilePath extension_path; |
| Extension::Location extension_location; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ExtensionInfo); |
| }; |
| |
| #endif // CHROME_COMMON_EXTENSIONS_EXTENSION_H_ |