1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef EXTENSIONS_COMMON_MANIFEST_H_
6#define EXTENSIONS_COMMON_MANIFEST_H_
7
8#include <map>
9#include <memory>
10#include <set>
11#include <string>
12#include <vector>
13
14#include "base/containers/span.h"
15#include "base/macros.h"
16#include "base/strings/string16.h"
17#include "base/values.h"
18#include "extensions/common/extension_id.h"
19#include "extensions/common/hashed_extension_id.h"
20
21namespace extensions {
22struct InstallWarning;
23
24// Wraps the DictionaryValue form of extension's manifest. Enforces access to
25// properties of the manifest using ManifestFeatureProvider.
26class Manifest {
27 public:
28 // Historically, where an extension was loaded from, and whether an
29 // extension's files were inside or outside of the profile's directory. In
30 // modern usage, a Location can be thought of as the installation source:
31 // whether an extension was explicitly installed by the user (through the
32 // UI), or implicitly installed by other means. For example, enterprise
33 // policy, being part of Chrome per se (but implemented as an extension), or
34 // installed as a side effect of installing third party software.
35 //
36 // NOTE: These values are stored as integers in the preferences and used
37 // in histograms so don't remove or reorder existing items. Just append
38 // to the end.
39 enum Location {
40 INVALID_LOCATION,
41 INTERNAL, // A crx file from the internal Extensions directory. This
42 // includes extensions explicitly installed by the user. It also
43 // includes installed-by-default extensions that are not part of
44 // Chrome itself (and thus not a COMPONENT), but are part of a
45 // larger system (such as Chrome OS).
46 EXTERNAL_PREF, // A crx file from an external directory (via prefs).
47 EXTERNAL_REGISTRY, // A crx file from an external directory (via eg the
48 // registry on Windows).
49 UNPACKED, // From loading an unpacked extension from the
50 // extensions settings page.
51 COMPONENT, // An integral component of Chrome itself, which
52 // happens to be implemented as an extension. We don't
53 // show these in the management UI.
54 EXTERNAL_PREF_DOWNLOAD, // A crx file from an external directory (via
55 // prefs), installed from an update URL.
56 EXTERNAL_POLICY_DOWNLOAD, // A crx file from an external directory (via
57 // admin policies), installed from an update URL.
58 COMMAND_LINE, // --load-extension.
59 EXTERNAL_POLICY, // A crx file from an external directory (via admin
60 // policies), cached locally and installed from the
61 // cache.
62 EXTERNAL_COMPONENT, // Similar to COMPONENT in that it's considered an
63 // internal implementation detail of chrome, but
64 // installed from an update URL like the *DOWNLOAD ones.
65
66 // New enum values must go above here.
67 NUM_LOCATIONS
68 };
69
70 // Do not change the order of entries or remove entries in this list as this
71 // is used in ExtensionType enum in tools/metrics/histograms/enums.xml.
72 enum Type {
73 TYPE_UNKNOWN = 0,
74 TYPE_EXTENSION = 1,
75 TYPE_THEME = 2,
76 TYPE_USER_SCRIPT = 3,
77 TYPE_HOSTED_APP = 4,
78 // This is marked legacy because platform apps are preferred. For
79 // backwards compatibility, we can't remove support for packaged apps
80 TYPE_LEGACY_PACKAGED_APP = 5,
81 TYPE_PLATFORM_APP = 6,
82 TYPE_SHARED_MODULE = 7,
83
84 // New enum values must go above here.
85 NUM_LOAD_TYPES
86 };
87
88 // Given two install sources, return the one which should take priority
89 // over the other. If an extension is installed from two sources A and B,
90 // its install source should be set to GetHigherPriorityLocation(A, B).
91 static Location GetHigherPriorityLocation(Location loc1, Location loc2);
92
93 // Whether the |location| is external or not.
94 static inline bool IsExternalLocation(Location location) {
95 return location == EXTERNAL_PREF ||
96 location == EXTERNAL_REGISTRY ||
97 location == EXTERNAL_PREF_DOWNLOAD ||
98 location == EXTERNAL_POLICY ||
99 location == EXTERNAL_POLICY_DOWNLOAD ||
100 location == EXTERNAL_COMPONENT;
101 }
102
103 // Whether the |location| is unpacked (no CRX) or not.
104 static inline bool IsUnpackedLocation(Location location) {
105 return location == UNPACKED || location == COMMAND_LINE;
106 }
107
108 // Whether extensions with |location| are auto-updatable or not.
109 static inline bool IsAutoUpdateableLocation(Location location) {
110 // Only internal and external extensions can be autoupdated.
111 return location == INTERNAL ||
112 IsExternalLocation(location);
113 }
114
115 // Whether the |location| is a source of extensions force-installed through
116 // policy.
117 static inline bool IsPolicyLocation(Location location) {
118 return location == EXTERNAL_POLICY ||
119 location == EXTERNAL_POLICY_DOWNLOAD;
120 }
121
122 // Whether the |location| is an extension intended to be an internal part of
123 // Chrome.
124 static inline bool IsComponentLocation(Location location) {
125 return location == COMPONENT || location == EXTERNAL_COMPONENT;
126 }
127
128 static inline bool IsValidLocation(Location location) {
129 return location > INVALID_LOCATION && location < NUM_LOCATIONS;
130 }
131
132 // Unpacked extensions start off with file access since they are a developer
133 // feature.
134 static inline bool ShouldAlwaysAllowFileAccess(Location location) {
135 return IsUnpackedLocation(location);
136 }
137
138 // Returns the Manifest::Type for the given |value|.
139 static Type GetTypeFromManifestValue(const base::DictionaryValue& value);
140
141 // Returns true if an item with the given |location| should always be loaded,
142 // even if extensions are otherwise disabled.
143 static bool ShouldAlwaysLoadExtension(Manifest::Location location,
144 bool is_theme);
145
146 Manifest(Location location, std::unique_ptr<base::DictionaryValue> value);
147 virtual ~Manifest();
148
149 void SetExtensionId(const ExtensionId& id);
150
151 const ExtensionId& extension_id() const { return extension_id_; }
152 const HashedExtensionId& hashed_id() const { return hashed_id_; }
153
154 Location location() const { return location_; }
155
156 // Returns false and |error| will be non-empty if the manifest is malformed.
157 // |warnings| will be populated if there are keys in the manifest that cannot
158 // be specified by the extension type.
159 bool ValidateManifest(std::string* error,
160 std::vector<InstallWarning>* warnings) const;
161
162 // The version of this extension's manifest. We increase the manifest
163 // version when making breaking changes to the extension system. If the
164 // manifest contains no explicit manifest version, this returns the current
165 // system default.
166 int GetManifestVersion() const;
167
168 // Returns the manifest type.
169 Type type() const { return type_; }
170
171 bool is_theme() const { return type_ == TYPE_THEME; }
172 bool is_app() const {
173 return is_legacy_packaged_app() || is_hosted_app() || is_platform_app();
174 }
175 bool is_platform_app() const { return type_ == TYPE_PLATFORM_APP; }
176 bool is_hosted_app() const { return type_ == TYPE_HOSTED_APP; }
177 bool is_legacy_packaged_app() const {
178 return type_ == TYPE_LEGACY_PACKAGED_APP;
179 }
180 bool is_extension() const { return type_ == TYPE_EXTENSION; }
181 bool is_shared_module() const { return type_ == TYPE_SHARED_MODULE; }
182
183 // These access the wrapped manifest value, returning false when the property
184 // does not exist or if the manifest type can't access it.
185 // TODO(karandeepb): These methods should be changed to use base::StringPiece.
186 // Better, we should pass a list of path components instead of a unified
187 // |path| to do away with our usage of deprecated base::Value methods.
188 bool HasKey(const std::string& key) const;
189 bool HasPath(const std::string& path) const;
190 bool Get(const std::string& path, const base::Value** out_value) const;
191 bool GetBoolean(const std::string& path, bool* out_value) const;
192 bool GetInteger(const std::string& path, int* out_value) const;
193 bool GetString(const std::string& path, std::string* out_value) const;
194 bool GetString(const std::string& path, base::string16* out_value) const;
195 // Deprecated: Use the GetDictionary() overload that accepts a base::Value
196 // output parameter instead.
197 bool GetDictionary(const std::string& path,
198 const base::DictionaryValue** out_value) const;
199 bool GetDictionary(const std::string& path,
200 const base::Value** out_value) const;
201 // Deprecated: Use the GetList() overload that accepts a base::Value output
202 // parameter instead.
203 bool GetList(const std::string& path,
204 const base::ListValue** out_value) const;
205 bool GetList(const std::string& path, const base::Value** out_value) const;
206
207 bool GetPathOfType(const std::string& path,
208 base::Value::Type type,
209 const base::Value** out_value) const;
210
211 // Returns a new Manifest equal to this one.
212 std::unique_ptr<Manifest> CreateDeepCopy() const;
213
214 // Returns true if this equals the |other| manifest.
215 bool Equals(const Manifest* other) const;
216
217 // Gets the underlying DictionaryValue representing the manifest.
218 // Note: only use this when you KNOW you don't need the validation.
219 const base::DictionaryValue* value() const { return value_.get(); }
220
221 private:
222 // Returns true if the extension can specify the given |path|.
223 bool CanAccessPath(const std::string& path) const;
224 bool CanAccessPath(const base::span<const base::StringPiece> path) const;
225 bool CanAccessKey(const std::string& key) const;
226
227 // A persistent, globally unique ID. An extension's ID is used in things
228 // like directory structures and URLs, and is expected to not change across
229 // versions. It is generated as a SHA-256 hash of the extension's public
230 // key, or as a hash of the path in the case of unpacked extensions.
231 std::string extension_id_;
232
233 // The hex-encoding of the SHA1 of the extension id; used to determine feature
234 // availability.
235 HashedExtensionId hashed_id_;
236
237 // The location the extension was loaded from.
238 Location location_;
239
240 // The underlying dictionary representation of the manifest.
241 std::unique_ptr<base::DictionaryValue> value_;
242
243 Type type_;
244
245 DISALLOW_COPY_AND_ASSIGN(Manifest);
246};
247
248} // namespace extensions
249
250#endif // EXTENSIONS_COMMON_MANIFEST_H_
251