// Copyright 2013 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 EXTENSIONS_COMMON_MANIFEST_H_ #define EXTENSIONS_COMMON_MANIFEST_H_ #include #include #include #include #include #include "extensions/common/extension_id.h" #include "extensions/common/hashed_extension_id.h" #include "extensions/common/mojom/manifest.mojom-shared.h" namespace base { class DictionaryValue; class Value; } // namespace base namespace extensions { struct InstallWarning; // Wraps the DictionaryValue form of extension's manifest. Enforces access to // properties of the manifest using ManifestFeatureProvider. class Manifest final { public: // Do not change the order of entries or remove entries in this list as this // is used in ExtensionType enum in tools/metrics/histograms/enums.xml. enum Type { TYPE_UNKNOWN = 0, TYPE_EXTENSION = 1, TYPE_THEME = 2, TYPE_USER_SCRIPT = 3, TYPE_HOSTED_APP = 4, // This is marked legacy because platform apps are preferred. For // backwards compatibility, we can't remove support for packaged apps TYPE_LEGACY_PACKAGED_APP = 5, TYPE_PLATFORM_APP = 6, TYPE_SHARED_MODULE = 7, TYPE_LOGIN_SCREEN_EXTENSION = 8, TYPE_CHROMEOS_SYSTEM_EXTENSION = 9, // New enum values must go above here. NUM_LOAD_TYPES }; // Given two install sources, return the one which should take priority // over the other. If an extension is installed from two sources A and B, // its install source should be set to GetHigherPriorityLocation(A, B). static mojom::ManifestLocation GetHigherPriorityLocation( mojom::ManifestLocation loc1, mojom::ManifestLocation loc2); // Whether the |location| is external or not. static inline bool IsExternalLocation(mojom::ManifestLocation location) { return location == mojom::ManifestLocation::kExternalPref || location == mojom::ManifestLocation::kExternalRegistry || location == mojom::ManifestLocation::kExternalPrefDownload || location == mojom::ManifestLocation::kExternalPolicy || location == mojom::ManifestLocation::kExternalPolicyDownload || location == mojom::ManifestLocation::kExternalComponent; } // Whether the |location| is unpacked (no CRX) or not. static inline bool IsUnpackedLocation(mojom::ManifestLocation location) { return location == mojom::ManifestLocation::kUnpacked || location == mojom::ManifestLocation::kCommandLine; } // Whether extensions with |location| are auto-updatable or not. static inline bool IsAutoUpdateableLocation( mojom::ManifestLocation location) { // Only internal and external extensions can be autoupdated. return location == mojom::ManifestLocation::kInternal || IsExternalLocation(location); } // Whether the |location| is a source of extensions force-installed through // policy. static inline bool IsPolicyLocation(mojom::ManifestLocation location) { return location == mojom::ManifestLocation::kExternalPolicy || location == mojom::ManifestLocation::kExternalPolicyDownload; } // Whether the |location| is an extension intended to be an internal part of // Chrome. static inline bool IsComponentLocation(mojom::ManifestLocation location) { return location == mojom::ManifestLocation::kComponent || location == mojom::ManifestLocation::kExternalComponent; } static inline bool IsValidLocation(mojom::ManifestLocation location) { return location > mojom::ManifestLocation::kInvalidLocation && location <= mojom::ManifestLocation::kMaxValue; } // Unpacked extensions start off with file access since they are a developer // feature. static inline bool ShouldAlwaysAllowFileAccess( mojom::ManifestLocation location) { return IsUnpackedLocation(location); } // Returns the Manifest::Type for the given |value|. static Type GetTypeFromManifestValue(const base::DictionaryValue& value, bool for_login_screen = false); // Returns true if an item with the given |location| should always be loaded, // even if extensions are otherwise disabled. static bool ShouldAlwaysLoadExtension(mojom::ManifestLocation location, bool is_theme); // Creates a Manifest for a login screen context. Note that this won't always // result in a Manifest of TYPE_LOGIN_SCREEN_EXTENSION, since other items // (like platform apps) may be installed in the same login screen profile. static std::unique_ptr CreateManifestForLoginScreen( mojom::ManifestLocation location, std::unique_ptr value, ExtensionId extension_id); Manifest(mojom::ManifestLocation location, std::unique_ptr value, ExtensionId extension_id); Manifest(const Manifest&) = delete; Manifest& operator=(const Manifest&) = delete; ~Manifest(); const ExtensionId& extension_id() const { return extension_id_; } const HashedExtensionId& hashed_id() const { return hashed_id_; } mojom::ManifestLocation location() const { return location_; } // Returns false and |error| will be non-empty if the manifest is malformed. // |warnings| will be populated if there are keys in the manifest that cannot // be specified by the extension type. bool ValidateManifest(std::string* error, std::vector* warnings) const; // The version of this extension's manifest. We increase the manifest // version when making breaking changes to the extension system. If the // manifest contains no explicit manifest version, this returns the current // system default. int manifest_version() const { return manifest_version_; } // Returns the manifest type. Type type() const { return type_; } bool is_theme() const { return type_ == TYPE_THEME; } bool is_app() const { return is_legacy_packaged_app() || is_hosted_app() || is_platform_app(); } bool is_platform_app() const { return type_ == TYPE_PLATFORM_APP; } bool is_hosted_app() const { return type_ == TYPE_HOSTED_APP; } bool is_legacy_packaged_app() const { return type_ == TYPE_LEGACY_PACKAGED_APP; } bool is_extension() const { return type_ == TYPE_EXTENSION; } bool is_login_screen_extension() const { return type_ == TYPE_LOGIN_SCREEN_EXTENSION; } bool is_shared_module() const { return type_ == TYPE_SHARED_MODULE; } bool is_chromeos_system_extension() const { return type_ == TYPE_CHROMEOS_SYSTEM_EXTENSION; } // These access the wrapped manifest value, returning nullptr/nullopt when the // property does not exist or if the manifest type can't access it. const base::Value* FindKey(base::StringPiece path) const; const base::Value* FindPath(base::StringPiece path) const; absl::optional FindBoolPath(base::StringPiece path) const; absl::optional FindIntPath(base::StringPiece path) const; const std::string* FindStringPath(base::StringPiece path) const; // Deprecated: Use the GetDictionary() overload that accepts a base::Value // output parameter instead. bool GetDictionary(const std::string& path, const base::DictionaryValue** out_value) const; bool GetDictionary(const std::string& path, const base::Value** out_value) const; bool GetList(const std::string& path, const base::Value** out_value) const; // Returns true if this equals the |other| manifest. bool EqualsForTesting(const Manifest& other) const; // Gets the underlying DictionaryValue representing the manifest. // Note: only use this when you KNOW you don't need the validation. const base::DictionaryValue* value() const { return value_.get(); } // Gets the underlying DictionaryValue representing the manifest with all // unavailable manifest keys removed. const base::DictionaryValue& available_values() const { return *available_values_; } private: Manifest(mojom::ManifestLocation location, std::unique_ptr value, ExtensionId extension_id, bool for_login_screen); // A persistent, globally unique ID. An extension's ID is used in things // like directory structures and URLs, and is expected to not change across // versions. It is generated as a SHA-256 hash of the extension's public // key, or as a hash of the path in the case of unpacked extensions. const std::string extension_id_; // The hex-encoding of the SHA1 of the extension id; used to determine feature // availability. const HashedExtensionId hashed_id_; // The location the extension was loaded from. const mojom::ManifestLocation location_; // The underlying dictionary representation of the manifest. const std::unique_ptr value_; // Same as |value_| but comprises only of keys available to this manifest. std::unique_ptr available_values_; const Type type_; const int manifest_version_; }; } // namespace extensions #endif // EXTENSIONS_COMMON_MANIFEST_H_