extension.h revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file. 4 5#ifndef EXTENSIONS_COMMON_EXTENSION_H_ 6#define EXTENSIONS_COMMON_EXTENSION_H_ 7 8#include <algorithm> 9#include <iosfwd> 10#include <map> 11#include <set> 12#include <string> 13#include <utility> 14#include <vector> 15 16#include "base/containers/hash_tables.h" 17#include "base/files/file_path.h" 18#include "base/memory/linked_ptr.h" 19#include "base/memory/ref_counted.h" 20#include "base/memory/scoped_ptr.h" 21#include "base/synchronization/lock.h" 22#include "base/threading/thread_checker.h" 23#include "extensions/common/extension_resource.h" 24#include "extensions/common/install_warning.h" 25#include "extensions/common/manifest.h" 26#include "extensions/common/url_pattern_set.h" 27#include "ui/base/accelerators/accelerator.h" 28#include "ui/gfx/size.h" 29#include "url/gurl.h" 30 31namespace base { 32class DictionaryValue; 33class Version; 34} 35 36namespace extensions { 37class PermissionSet; 38class PermissionsData; 39class PermissionsParser; 40 41// Uniquely identifies an Extension, using 32 characters from the alphabet 42// 'a'-'p'. An empty string represents "no extension". 43// 44// Note: If this gets used heavily in files that don't otherwise need to include 45// extension.h, we should pull it into a dedicated header. 46typedef std::string ExtensionId; 47 48// Represents a Chrome extension. 49// Once created, an Extension object is immutable, with the exception of its 50// RuntimeData. This makes it safe to use on any thread, since access to the 51// RuntimeData is protected by a lock. 52class Extension : public base::RefCountedThreadSafe<Extension> { 53 public: 54 struct ManifestData; 55 56 typedef std::map<const std::string, linked_ptr<ManifestData> > 57 ManifestDataMap; 58 59 enum State { 60 DISABLED = 0, 61 ENABLED, 62 // An external extension that the user uninstalled. We should not reinstall 63 // such extensions on startup. 64 EXTERNAL_EXTENSION_UNINSTALLED, 65 // DEPRECATED: Special state for component extensions. 66 // Maintained as a placeholder since states may be stored to disk. 67 ENABLED_COMPONENT_DEPRECATED, 68 NUM_STATES 69 }; 70 71 // Used to record the reason an extension was disabled. 72 enum DeprecatedDisableReason { 73 DEPRECATED_DISABLE_UNKNOWN, 74 DEPRECATED_DISABLE_USER_ACTION, 75 DEPRECATED_DISABLE_PERMISSIONS_INCREASE, 76 DEPRECATED_DISABLE_RELOAD, 77 DEPRECATED_DISABLE_LAST, // Not used. 78 }; 79 80 // Reasons an extension may be disabled. These are used in histograms, so do 81 // not remove/reorder entries - only add at the end just before 82 // DISABLE_REASON_LAST (and update the shift value for it). Also remember to 83 // update the enum listing in tools/metrics/histograms.xml. 84 enum DisableReason { 85 DISABLE_NONE = 0, 86 DISABLE_USER_ACTION = 1 << 0, 87 DISABLE_PERMISSIONS_INCREASE = 1 << 1, 88 DISABLE_RELOAD = 1 << 2, 89 DISABLE_UNSUPPORTED_REQUIREMENT = 1 << 3, 90 DISABLE_SIDELOAD_WIPEOUT = 1 << 4, 91 DISABLE_UNKNOWN_FROM_SYNC = 1 << 5, 92 // DISABLE_PERMISSIONS_CONSENT = 1 << 6, // Deprecated. 93 // DISABLE_KNOWN_DISABLED = 1 << 7, // Deprecated. 94 DISABLE_NOT_VERIFIED = 1 << 8, // Disabled because we could not verify 95 // the install. 96 DISABLE_GREYLIST = 1 << 9, 97 DISABLE_CORRUPTED = 1 << 10, 98 DISABLE_REMOTE_INSTALL = 1 << 11, 99 DISABLE_INACTIVE_EPHEMERAL_APP = 1 << 12, // Cached ephemeral apps are 100 // disabled to prevent activity. 101 DISABLE_REASON_LAST = 1 << 13, // This should always be the last value 102 }; 103 104 // A base class for parsed manifest data that APIs want to store on 105 // the extension. Related to base::SupportsUserData, but with an immutable 106 // thread-safe interface to match Extension. 107 struct ManifestData { 108 virtual ~ManifestData() {} 109 }; 110 111 // Do not change the order of entries or remove entries in this list 112 // as this is used in UMA_HISTOGRAM_ENUMERATIONs about extensions. 113 enum InitFromValueFlags { 114 NO_FLAGS = 0, 115 116 // Usually, the id of an extension is generated by the "key" property of 117 // its manifest, but if |REQUIRE_KEY| is not set, a temporary ID will be 118 // generated based on the path. 119 REQUIRE_KEY = 1 << 0, 120 121 // Requires the extension to have an up-to-date manifest version. 122 // Typically, we'll support multiple manifest versions during a version 123 // transition. This flag signals that we want to require the most modern 124 // manifest version that Chrome understands. 125 REQUIRE_MODERN_MANIFEST_VERSION = 1 << 1, 126 127 // |ALLOW_FILE_ACCESS| indicates that the user is allowing this extension 128 // to have file access. If it's not present, then permissions and content 129 // scripts that match file:/// URLs will be filtered out. 130 ALLOW_FILE_ACCESS = 1 << 2, 131 132 // |FROM_WEBSTORE| indicates that the extension was installed from the 133 // Chrome Web Store. 134 FROM_WEBSTORE = 1 << 3, 135 136 // |FROM_BOOKMARK| indicates the extension is a bookmark app which has been 137 // generated from a web page. Bookmark apps have no permissions or extent 138 // and launch the web page they are created from when run. 139 FROM_BOOKMARK = 1 << 4, 140 141 // |FOLLOW_SYMLINKS_ANYWHERE| means that resources can be symlinks to 142 // anywhere in the filesystem, rather than being restricted to the 143 // extension directory. 144 FOLLOW_SYMLINKS_ANYWHERE = 1 << 5, 145 146 // |ERROR_ON_PRIVATE_KEY| means that private keys inside an 147 // extension should be errors rather than warnings. 148 ERROR_ON_PRIVATE_KEY = 1 << 6, 149 150 // |WAS_INSTALLED_BY_DEFAULT| installed by default when the profile was 151 // created. 152 WAS_INSTALLED_BY_DEFAULT = 1 << 7, 153 154 // Unused - was part of an abandoned experiment. 155 REQUIRE_PERMISSIONS_CONSENT = 1 << 8, 156 157 // Unused - this flag has been moved to ExtensionPrefs. 158 IS_EPHEMERAL = 1 << 9, 159 160 // |WAS_INSTALLED_BY_OEM| installed by an OEM (e.g on Chrome OS) and should 161 // be placed in a special OEM folder in the App Launcher. Note: OEM apps are 162 // also installed by Default (i.e. WAS_INSTALLED_BY_DEFAULT is also true). 163 WAS_INSTALLED_BY_OEM = 1 << 10, 164 165 // |WAS_INSTALLED_BY_CUSTODIAN| means this extension was installed by the 166 // custodian of a supervised user. 167 WAS_INSTALLED_BY_CUSTODIAN = 1 << 11, 168 169 // When adding new flags, make sure to update kInitFromValueFlagBits. 170 }; 171 172 // This is the highest bit index of the flags defined above. 173 static const int kInitFromValueFlagBits; 174 175 static scoped_refptr<Extension> Create(const base::FilePath& path, 176 Manifest::Location location, 177 const base::DictionaryValue& value, 178 int flags, 179 std::string* error); 180 181 // In a few special circumstances, we want to create an Extension and give it 182 // an explicit id. Most consumers should just use the other Create() method. 183 static scoped_refptr<Extension> Create(const base::FilePath& path, 184 Manifest::Location location, 185 const base::DictionaryValue& value, 186 int flags, 187 const ExtensionId& explicit_id, 188 std::string* error); 189 190 // Valid schemes for web extent URLPatterns. 191 static const int kValidWebExtentSchemes; 192 193 // Valid schemes for host permission URLPatterns. 194 static const int kValidHostPermissionSchemes; 195 196 // The mimetype used for extensions. 197 static const char kMimeType[]; 198 199 // Checks to see if the extension has a valid ID. 200 static bool IdIsValid(const std::string& id); 201 202 // See Type definition in Manifest. 203 Manifest::Type GetType() const; 204 205 // Returns an absolute url to a resource inside of an extension. The 206 // |extension_url| argument should be the url() from an Extension object. The 207 // |relative_path| can be untrusted user input. The returned URL will either 208 // be invalid() or a child of |extension_url|. 209 // NOTE: Static so that it can be used from multiple threads. 210 static GURL GetResourceURL(const GURL& extension_url, 211 const std::string& relative_path); 212 GURL GetResourceURL(const std::string& relative_path) const { 213 return GetResourceURL(url(), relative_path); 214 } 215 216 // Returns true if the resource matches a pattern in the pattern_set. 217 bool ResourceMatches(const URLPatternSet& pattern_set, 218 const std::string& resource) const; 219 220 // Returns an extension resource object. |relative_path| should be UTF8 221 // encoded. 222 ExtensionResource GetResource(const std::string& relative_path) const; 223 224 // As above, but with |relative_path| following the file system's encoding. 225 ExtensionResource GetResource(const base::FilePath& relative_path) const; 226 227 // |input| is expected to be the text of an rsa public or private key. It 228 // tolerates the presence or absence of bracking header/footer like this: 229 // -----(BEGIN|END) [RSA PUBLIC/PRIVATE] KEY----- 230 // and may contain newlines. 231 static bool ParsePEMKeyBytes(const std::string& input, std::string* output); 232 233 // Does a simple base64 encoding of |input| into |output|. 234 static bool ProducePEM(const std::string& input, std::string* output); 235 236 // Expects base64 encoded |input| and formats into |output| including 237 // the appropriate header & footer. 238 static bool FormatPEMForFileOutput(const std::string& input, 239 std::string* output, 240 bool is_public); 241 242 // Returns the base extension url for a given |extension_id|. 243 static GURL GetBaseURLFromExtensionId(const ExtensionId& extension_id); 244 245 // Whether context menu should be shown for page and browser actions. 246 bool ShowConfigureContextMenus() const; 247 248 // Returns true if this extension or app includes areas within |origin|. 249 bool OverlapsWithOrigin(const GURL& origin) const; 250 251 // Returns true if the extension requires a valid ordinal for sorting, e.g., 252 // for displaying in a launcher or new tab page. 253 bool RequiresSortOrdinal() const; 254 255 // Returns true if the extension should be displayed in the app launcher. 256 bool ShouldDisplayInAppLauncher() const; 257 258 // Returns true if the extension should be displayed in the browser NTP. 259 bool ShouldDisplayInNewTabPage() const; 260 261 // Returns true if the extension should be displayed in the extension 262 // settings page (i.e. chrome://extensions). 263 bool ShouldDisplayInExtensionSettings() const; 264 265 // Returns true if the extension should not be shown anywhere. This is 266 // mostly the same as the extension being a component extension, but also 267 // includes non-component apps that are hidden from the app launcher and ntp. 268 bool ShouldNotBeVisible() const; 269 270 // Get the manifest data associated with the key, or NULL if there is none. 271 // Can only be called after InitValue is finished. 272 ManifestData* GetManifestData(const std::string& key) const; 273 274 // Sets |data| to be associated with the key. Takes ownership of |data|. 275 // Can only be called before InitValue is finished. Not thread-safe; 276 // all SetManifestData calls should be on only one thread. 277 void SetManifestData(const std::string& key, ManifestData* data); 278 279 // Accessors: 280 281 const base::FilePath& path() const { return path_; } 282 const GURL& url() const { return extension_url_; } 283 Manifest::Location location() const; 284 const ExtensionId& id() const; 285 const base::Version* version() const { return version_.get(); } 286 const std::string VersionString() const; 287 const std::string& name() const { return name_; } 288 const std::string& short_name() const { return short_name_; } 289 const std::string& non_localized_name() const { return non_localized_name_; } 290 // Base64-encoded version of the key used to sign this extension. 291 // In pseudocode, returns 292 // base::Base64Encode(RSAPrivateKey(pem_file).ExportPublicKey()). 293 const std::string& public_key() const { return public_key_; } 294 const std::string& description() const { return description_; } 295 int manifest_version() const { return manifest_version_; } 296 bool converted_from_user_script() const { 297 return converted_from_user_script_; 298 } 299 PermissionsParser* permissions_parser() { return permissions_parser_.get(); } 300 const PermissionsParser* permissions_parser() const { 301 return permissions_parser_.get(); 302 } 303 304 const PermissionsData* permissions_data() const { 305 return permissions_data_.get(); 306 } 307 308 // Appends |new_warning[s]| to install_warnings_. 309 void AddInstallWarning(const InstallWarning& new_warning); 310 void AddInstallWarnings(const std::vector<InstallWarning>& new_warnings); 311 const std::vector<InstallWarning>& install_warnings() const { 312 return install_warnings_; 313 } 314 const extensions::Manifest* manifest() const { 315 return manifest_.get(); 316 } 317 bool wants_file_access() const { return wants_file_access_; } 318 // TODO(rdevlin.cronin): This is needed for ContentScriptsHandler, and should 319 // be moved out as part of crbug.com/159265. This should not be used anywhere 320 // else. 321 void set_wants_file_access(bool wants_file_access) { 322 wants_file_access_ = wants_file_access; 323 } 324 int creation_flags() const { return creation_flags_; } 325 bool from_webstore() const { return (creation_flags_ & FROM_WEBSTORE) != 0; } 326 bool from_bookmark() const { return (creation_flags_ & FROM_BOOKMARK) != 0; } 327 bool was_installed_by_default() const { 328 return (creation_flags_ & WAS_INSTALLED_BY_DEFAULT) != 0; 329 } 330 bool was_installed_by_oem() const { 331 return (creation_flags_ & WAS_INSTALLED_BY_OEM) != 0; 332 } 333 bool was_installed_by_custodian() const { 334 return (creation_flags_ & WAS_INSTALLED_BY_CUSTODIAN) != 0; 335 } 336 337 // Type-related queries. 338 bool is_app() const; 339 bool is_platform_app() const; 340 bool is_hosted_app() const; 341 bool is_legacy_packaged_app() const; 342 bool is_extension() const; 343 bool is_shared_module() const; 344 bool is_theme() const; 345 346 bool can_be_incognito_enabled() const; 347 348 void AddWebExtentPattern(const URLPattern& pattern); 349 const URLPatternSet& web_extent() const { return extent_; } 350 351 private: 352 friend class base::RefCountedThreadSafe<Extension>; 353 354 // Chooses the extension ID for an extension based on a variety of criteria. 355 // The chosen ID will be set in |manifest|. 356 static bool InitExtensionID(extensions::Manifest* manifest, 357 const base::FilePath& path, 358 const ExtensionId& explicit_id, 359 int creation_flags, 360 base::string16* error); 361 362 Extension(const base::FilePath& path, 363 scoped_ptr<extensions::Manifest> manifest); 364 virtual ~Extension(); 365 366 // Initialize the extension from a parsed manifest. 367 // TODO(aa): Rename to just Init()? There's no Value here anymore. 368 // TODO(aa): It is really weird the way this class essentially contains a copy 369 // of the underlying DictionaryValue in its members. We should decide to 370 // either wrap the DictionaryValue and go with that only, or we should parse 371 // into strong types and discard the value. But doing both is bad. 372 bool InitFromValue(int flags, base::string16* error); 373 374 // The following are helpers for InitFromValue to load various features of the 375 // extension from the manifest. 376 377 bool LoadRequiredFeatures(base::string16* error); 378 bool LoadName(base::string16* error); 379 bool LoadVersion(base::string16* error); 380 381 bool LoadAppFeatures(base::string16* error); 382 bool LoadExtent(const char* key, 383 URLPatternSet* extent, 384 const char* list_error, 385 const char* value_error, 386 base::string16* error); 387 388 bool LoadSharedFeatures(base::string16* error); 389 bool LoadDescription(base::string16* error); 390 bool LoadManifestVersion(base::string16* error); 391 bool LoadShortName(base::string16* error); 392 393 bool CheckMinimumChromeVersion(base::string16* error) const; 394 395 // The extension's human-readable name. Name is used for display purpose. It 396 // might be wrapped with unicode bidi control characters so that it is 397 // displayed correctly in RTL context. 398 // NOTE: Name is UTF-8 and may contain non-ascii characters. 399 std::string name_; 400 401 // A non-localized version of the extension's name. This is useful for 402 // debug output. 403 std::string non_localized_name_; 404 405 // A short version of the extension's name. This can be used as an alternative 406 // to the name where there is insufficient space to display the full name. If 407 // an extension has not explicitly specified a short name, the value of this 408 // member variable will be the full name rather than an empty string. 409 std::string short_name_; 410 411 // The version of this extension's manifest. We increase the manifest 412 // version when making breaking changes to the extension system. 413 // Version 1 was the first manifest version (implied by a lack of a 414 // manifest_version attribute in the extension's manifest). We initialize 415 // this member variable to 0 to distinguish the "uninitialized" case from 416 // the case when we know the manifest version actually is 1. 417 int manifest_version_; 418 419 // The absolute path to the directory the extension is stored in. 420 base::FilePath path_; 421 422 // Defines the set of URLs in the extension's web content. 423 URLPatternSet extent_; 424 425 // The parser for the manifest's permissions. This is NULL anytime not during 426 // initialization. 427 // TODO(rdevlin.cronin): This doesn't really belong here. 428 scoped_ptr<PermissionsParser> permissions_parser_; 429 430 // The active permissions for the extension. 431 scoped_ptr<PermissionsData> permissions_data_; 432 433 // Any warnings that occurred when trying to create/parse the extension. 434 std::vector<InstallWarning> install_warnings_; 435 436 // The base extension url for the extension. 437 GURL extension_url_; 438 439 // The extension's version. 440 scoped_ptr<base::Version> version_; 441 442 // An optional longer description of the extension. 443 std::string description_; 444 445 // True if the extension was generated from a user script. (We show slightly 446 // different UI if so). 447 bool converted_from_user_script_; 448 449 // The public key used to sign the contents of the crx package. 450 std::string public_key_; 451 452 // The manifest from which this extension was created. 453 scoped_ptr<Manifest> manifest_; 454 455 // Stored parsed manifest data. 456 ManifestDataMap manifest_data_; 457 458 // Set to true at the end of InitValue when initialization is finished. 459 bool finished_parsing_manifest_; 460 461 // Ensures that any call to GetManifestData() prior to finishing 462 // initialization happens from the same thread (this can happen when certain 463 // parts of the initialization process need information from previous parts). 464 base::ThreadChecker thread_checker_; 465 466 // Should this app be shown in the app launcher. 467 bool display_in_launcher_; 468 469 // Should this app be shown in the browser New Tab Page. 470 bool display_in_new_tab_page_; 471 472 // Whether the extension has host permissions or user script patterns that 473 // imply access to file:/// scheme URLs (the user may not have actually 474 // granted it that access). 475 bool wants_file_access_; 476 477 // The flags that were passed to InitFromValue. 478 int creation_flags_; 479 480 DISALLOW_COPY_AND_ASSIGN(Extension); 481}; 482 483typedef std::vector<scoped_refptr<const Extension> > ExtensionList; 484typedef std::set<ExtensionId> ExtensionIdSet; 485typedef std::vector<ExtensionId> ExtensionIdList; 486 487// Handy struct to pass core extension info around. 488struct ExtensionInfo { 489 ExtensionInfo(const base::DictionaryValue* manifest, 490 const ExtensionId& id, 491 const base::FilePath& path, 492 Manifest::Location location); 493 ~ExtensionInfo(); 494 495 scoped_ptr<base::DictionaryValue> extension_manifest; 496 ExtensionId extension_id; 497 base::FilePath extension_path; 498 Manifest::Location extension_location; 499 500 private: 501 DISALLOW_COPY_AND_ASSIGN(ExtensionInfo); 502}; 503 504struct InstalledExtensionInfo { 505 // The extension being installed - this should always be non-NULL. 506 const Extension* extension; 507 508 // True if the extension is being updated; false if it is being installed. 509 bool is_update; 510 511 // True if the extension was previously installed ephemerally and is now 512 // a regular installed extension. 513 bool from_ephemeral; 514 515 // The name of the extension prior to this update. Will be empty if 516 // |is_update| is false. 517 std::string old_name; 518 519 InstalledExtensionInfo(const Extension* extension, 520 bool is_update, 521 bool from_ephemeral, 522 const std::string& old_name); 523}; 524 525struct UnloadedExtensionInfo { 526 // TODO(DHNishi): Move this enum to ExtensionRegistryObserver. 527 enum Reason { 528 REASON_UNDEFINED, // Undefined state used to initialize variables. 529 REASON_DISABLE, // Extension is being disabled. 530 REASON_UPDATE, // Extension is being updated to a newer version. 531 REASON_UNINSTALL, // Extension is being uninstalled. 532 REASON_TERMINATE, // Extension has terminated. 533 REASON_BLACKLIST, // Extension has been blacklisted. 534 REASON_PROFILE_SHUTDOWN, // Profile is being shut down. 535 }; 536 537 Reason reason; 538 539 // The extension being unloaded - this should always be non-NULL. 540 const Extension* extension; 541 542 UnloadedExtensionInfo(const Extension* extension, Reason reason); 543}; 544 545// The details sent for EXTENSION_PERMISSIONS_UPDATED notifications. 546struct UpdatedExtensionPermissionsInfo { 547 enum Reason { 548 ADDED, // The permissions were added to the extension. 549 REMOVED, // The permissions were removed from the extension. 550 }; 551 552 Reason reason; 553 554 // The extension who's permissions have changed. 555 const Extension* extension; 556 557 // The permissions that have changed. For Reason::ADDED, this would contain 558 // only the permissions that have added, and for Reason::REMOVED, this would 559 // only contain the removed permissions. 560 const PermissionSet* permissions; 561 562 UpdatedExtensionPermissionsInfo( 563 const Extension* extension, 564 const PermissionSet* permissions, 565 Reason reason); 566}; 567 568} // namespace extensions 569 570#endif // EXTENSIONS_COMMON_EXTENSION_H_ 571