blob: 70f0c5fbf7e38efb1a63ff8e6fea734b83097352 [file] [log] [blame]
// 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 <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#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<Manifest> CreateManifestForLoginScreen(
mojom::ManifestLocation location,
std::unique_ptr<base::DictionaryValue> value,
ExtensionId extension_id);
Manifest(mojom::ManifestLocation location,
std::unique_ptr<base::DictionaryValue> 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<InstallWarning>* 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<bool> FindBoolPath(base::StringPiece path) const;
absl::optional<int> 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<base::DictionaryValue> 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<const base::DictionaryValue> value_;
// Same as |value_| but comprises only of keys available to this manifest.
std::unique_ptr<const base::DictionaryValue> available_values_;
const Type type_;
const int manifest_version_;
};
} // namespace extensions
#endif // EXTENSIONS_COMMON_MANIFEST_H_