blob: d9709f4a4d2b180cea34a22c0d6f6e44bc1c3d10 [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 "base/containers/span.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/values.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/hashed_extension_id.h"
namespace extensions {
struct InstallWarning;
// Wraps the DictionaryValue form of extension's manifest. Enforces access to
// properties of the manifest using ManifestFeatureProvider.
class Manifest {
public:
// Historically, where an extension was loaded from, and whether an
// extension's files were inside or outside of the profile's directory. In
// modern usage, a Location can be thought of as the installation source:
// whether an extension was explicitly installed by the user (through the
// UI), or implicitly installed by other means. For example, enterprise
// policy, being part of Chrome per se (but implemented as an extension), or
// installed as a side effect of installing third party software.
//
// NOTE: These values are stored as integers in the preferences and used
// in histograms so don't remove or reorder existing items. Just append
// to the end.
enum Location {
INVALID_LOCATION,
INTERNAL, // A crx file from the internal Extensions directory. This
// includes extensions explicitly installed by the user. It also
// includes installed-by-default extensions that are not part of
// Chrome itself (and thus not a COMPONENT), but are part of a
// larger system (such as Chrome OS).
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).
UNPACKED, // From loading an unpacked extension from the
// extensions settings page.
COMPONENT, // An integral component of Chrome itself, which
// happens to be implemented as an extension. We don't
// show these in the management UI.
EXTERNAL_PREF_DOWNLOAD, // A crx file from an external directory (via
// prefs), installed from an update URL.
EXTERNAL_POLICY_DOWNLOAD, // A crx file from an external directory (via
// admin policies), installed from an update URL.
COMMAND_LINE, // --load-extension.
EXTERNAL_POLICY, // A crx file from an external directory (via admin
// policies), cached locally and installed from the
// cache.
EXTERNAL_COMPONENT, // Similar to COMPONENT in that it's considered an
// internal implementation detail of chrome, but
// installed from an update URL like the *DOWNLOAD ones.
// New enum values must go above here.
NUM_LOCATIONS
};
// 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,
// 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 Location GetHigherPriorityLocation(Location loc1, Location loc2);
// Whether the |location| is external or not.
static inline bool IsExternalLocation(Location location) {
return location == EXTERNAL_PREF ||
location == EXTERNAL_REGISTRY ||
location == EXTERNAL_PREF_DOWNLOAD ||
location == EXTERNAL_POLICY ||
location == EXTERNAL_POLICY_DOWNLOAD ||
location == EXTERNAL_COMPONENT;
}
// Whether the |location| is unpacked (no CRX) or not.
static inline bool IsUnpackedLocation(Location location) {
return location == UNPACKED || location == COMMAND_LINE;
}
// Whether extensions with |location| are auto-updatable or not.
static inline bool IsAutoUpdateableLocation(Location location) {
// Only internal and external extensions can be autoupdated.
return location == INTERNAL ||
IsExternalLocation(location);
}
// Whether the |location| is a source of extensions force-installed through
// policy.
static inline bool IsPolicyLocation(Location location) {
return location == EXTERNAL_POLICY ||
location == EXTERNAL_POLICY_DOWNLOAD;
}
// Whether the |location| is an extension intended to be an internal part of
// Chrome.
static inline bool IsComponentLocation(Location location) {
return location == COMPONENT || location == EXTERNAL_COMPONENT;
}
static inline bool IsValidLocation(Location location) {
return location > INVALID_LOCATION && location < NUM_LOCATIONS;
}
// Unpacked extensions start off with file access since they are a developer
// feature.
static inline bool ShouldAlwaysAllowFileAccess(Location location) {
return IsUnpackedLocation(location);
}
// Returns the Manifest::Type for the given |value|.
static Type GetTypeFromManifestValue(const base::DictionaryValue& value);
// Returns true if an item with the given |location| should always be loaded,
// even if extensions are otherwise disabled.
static bool ShouldAlwaysLoadExtension(Manifest::Location location,
bool is_theme);
Manifest(Location location, std::unique_ptr<base::DictionaryValue> value);
virtual ~Manifest();
void SetExtensionId(const ExtensionId& id);
const ExtensionId& extension_id() const { return extension_id_; }
const HashedExtensionId& hashed_id() const { return hashed_id_; }
Location 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 GetManifestVersion() const;
// 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_shared_module() const { return type_ == TYPE_SHARED_MODULE; }
// These access the wrapped manifest value, returning false when the property
// does not exist or if the manifest type can't access it.
// TODO(karandeepb): These methods should be changed to use base::StringPiece.
// Better, we should pass a list of path components instead of a unified
// |path| to do away with our usage of deprecated base::Value methods.
bool HasKey(const std::string& key) const;
bool HasPath(const std::string& path) const;
bool Get(const std::string& path, const base::Value** out_value) const;
bool GetBoolean(const std::string& path, bool* out_value) const;
bool GetInteger(const std::string& path, int* out_value) const;
bool GetString(const std::string& path, std::string* out_value) const;
bool GetString(const std::string& path, base::string16* out_value) 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;
// Deprecated: Use the GetList() overload that accepts a base::Value output
// parameter instead.
bool GetList(const std::string& path,
const base::ListValue** out_value) const;
bool GetList(const std::string& path, const base::Value** out_value) const;
bool GetPathOfType(const std::string& path,
base::Value::Type type,
const base::Value** out_value) const;
// Returns a new Manifest equal to this one.
std::unique_ptr<Manifest> CreateDeepCopy() const;
// Returns true if this equals the |other| manifest.
bool Equals(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(); }
private:
// Returns true if the extension can specify the given |path|.
bool CanAccessPath(const std::string& path) const;
bool CanAccessPath(const base::span<const base::StringPiece> path) const;
bool CanAccessKey(const std::string& key) const;
// 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.
std::string extension_id_;
// The hex-encoding of the SHA1 of the extension id; used to determine feature
// availability.
HashedExtensionId hashed_id_;
// The location the extension was loaded from.
Location location_;
// The underlying dictionary representation of the manifest.
std::unique_ptr<base::DictionaryValue> value_;
Type type_;
DISALLOW_COPY_AND_ASSIGN(Manifest);
};
} // namespace extensions
#endif // EXTENSIONS_COMMON_MANIFEST_H_