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 <set>
10#include <string>
11
12#include "base/memory/scoped_ptr.h"
13#include "base/strings/string16.h"
14#include "base/values.h"
15
16namespace extensions {
17struct InstallWarning;
18
19// Wraps the DictionaryValue form of extension's manifest. Enforces access to
20// properties of the manifest using ManifestFeatureProvider.
21class Manifest {
22 public:
23  // What an extension was loaded from.
24  // NOTE: These values are stored as integers in the preferences and used
25  // in histograms so don't remove or reorder existing items.  Just append
26  // to the end.
27  enum Location {
28    INVALID_LOCATION,
29    INTERNAL,           // A crx file from the internal Extensions directory.
30    EXTERNAL_PREF,      // A crx file from an external directory (via prefs).
31    EXTERNAL_REGISTRY,  // A crx file from an external directory (via eg the
32                        // registry on Windows).
33    UNPACKED,           // From loading an unpacked extension from the
34                        // extensions settings page.
35    COMPONENT,          // An integral component of Chrome itself, which
36                        // happens to be implemented as an extension. We don't
37                        // show these in the management UI.
38    EXTERNAL_PREF_DOWNLOAD,    // A crx file from an external directory (via
39                               // prefs), installed from an update URL.
40    EXTERNAL_POLICY_DOWNLOAD,  // A crx file from an external directory (via
41                               // admin policies), installed from an update URL.
42    COMMAND_LINE,              // --load-extension.
43    EXTERNAL_POLICY,     // A crx file from an external directory (via admin
44                         // policies), cached locally and installed from the
45                         // cache.
46    EXTERNAL_COMPONENT,  // Similar to COMPONENT in that it's considered an
47                         // internal implementation detail of chrome, but
48    // installed from an update URL like the *DOWNLOAD ones.
49
50    // New enum values must go above here.
51    NUM_LOCATIONS
52  };
53
54  // Do not change the order of entries or remove entries in this list
55  // as this is used in UMA_HISTOGRAM_ENUMERATIONs about extensions.
56  enum Type {
57    TYPE_UNKNOWN = 0,
58    TYPE_EXTENSION,
59    TYPE_THEME,
60    TYPE_USER_SCRIPT,
61    TYPE_HOSTED_APP,
62    // This is marked legacy because platform apps are preferred. For
63    // backwards compatibility, we can't remove support for packaged apps
64    TYPE_LEGACY_PACKAGED_APP,
65    TYPE_PLATFORM_APP,
66    TYPE_SHARED_MODULE,
67
68    // New enum values must go above here.
69    NUM_LOAD_TYPES
70  };
71
72  // Given two install sources, return the one which should take priority
73  // over the other. If an extension is installed from two sources A and B,
74  // its install source should be set to GetHigherPriorityLocation(A, B).
75  static Location GetHigherPriorityLocation(Location loc1, Location loc2);
76
77  // Whether the |location| is external or not.
78  static inline bool IsExternalLocation(Location location) {
79    return location == EXTERNAL_PREF ||
80           location == EXTERNAL_REGISTRY ||
81           location == EXTERNAL_PREF_DOWNLOAD ||
82           location == EXTERNAL_POLICY ||
83           location == EXTERNAL_POLICY_DOWNLOAD ||
84           location == EXTERNAL_COMPONENT;
85  }
86
87  // Whether the |location| is unpacked (no CRX) or not.
88  static inline bool IsUnpackedLocation(Location location) {
89    return location == UNPACKED || location == COMMAND_LINE;
90  }
91
92  // Whether extensions with |location| are auto-updatable or not.
93  static inline bool IsAutoUpdateableLocation(Location location) {
94    // Only internal and external extensions can be autoupdated.
95    return location == INTERNAL ||
96           IsExternalLocation(location);
97  }
98
99  // Whether the |location| is a source of extensions force-installed through
100  // policy.
101  static inline bool IsPolicyLocation(Location location) {
102    return location == EXTERNAL_POLICY ||
103           location == EXTERNAL_POLICY_DOWNLOAD;
104  }
105
106  // Whether the |location| is an extension intended to be an internal part of
107  // Chrome.
108  static inline bool IsComponentLocation(Location location) {
109    return location == COMPONENT || location == EXTERNAL_COMPONENT;
110  }
111
112  // Unpacked extensions start off with file access since they are a developer
113  // feature.
114  static inline bool ShouldAlwaysAllowFileAccess(Location location) {
115    return IsUnpackedLocation(location);
116  }
117
118  Manifest(Location location, scoped_ptr<base::DictionaryValue> value);
119  virtual ~Manifest();
120
121  const std::string& extension_id() const { return extension_id_; }
122  void set_extension_id(const std::string& id) { extension_id_ = id; }
123
124  Location location() const { return location_; }
125
126  // Returns false and |error| will be non-empty if the manifest is malformed.
127  // |warnings| will be populated if there are keys in the manifest that cannot
128  // be specified by the extension type.
129  bool ValidateManifest(std::string* error,
130                        std::vector<InstallWarning>* warnings) const;
131
132  // The version of this extension's manifest. We increase the manifest
133  // version when making breaking changes to the extension system. If the
134  // manifest contains no explicit manifest version, this returns the current
135  // system default.
136  int GetManifestVersion() const;
137
138  // Returns the manifest type.
139  Type type() const { return type_; }
140
141  bool is_theme() const { return type_ == TYPE_THEME; }
142  bool is_app() const {
143    return is_legacy_packaged_app() || is_hosted_app() || is_platform_app();
144  }
145  bool is_platform_app() const { return type_ == TYPE_PLATFORM_APP; }
146  bool is_hosted_app() const { return type_ == TYPE_HOSTED_APP; }
147  bool is_legacy_packaged_app() const {
148    return type_ == TYPE_LEGACY_PACKAGED_APP;
149  }
150  bool is_extension() const { return type_ == TYPE_EXTENSION; }
151  bool is_shared_module() const { return type_ == TYPE_SHARED_MODULE; }
152
153  // These access the wrapped manifest value, returning false when the property
154  // does not exist or if the manifest type can't access it.
155  bool HasKey(const std::string& key) const;
156  bool HasPath(const std::string& path) const;
157  bool Get(const std::string& path, const base::Value** out_value) const;
158  bool GetBoolean(const std::string& path, bool* out_value) const;
159  bool GetInteger(const std::string& path, int* out_value) const;
160  bool GetString(const std::string& path, std::string* out_value) const;
161  bool GetString(const std::string& path, base::string16* out_value) const;
162  bool GetDictionary(const std::string& path,
163                     const base::DictionaryValue** out_value) const;
164  bool GetList(const std::string& path,
165               const base::ListValue** out_value) const;
166
167  // Returns a new Manifest equal to this one, passing ownership to
168  // the caller.
169  Manifest* DeepCopy() const;
170
171  // Returns true if this equals the |other| manifest.
172  bool Equals(const Manifest* other) const;
173
174  // Gets the underlying DictionaryValue representing the manifest.
175  // Note: only use this when you KNOW you don't need the validation.
176  const base::DictionaryValue* value() const { return value_.get(); }
177
178 private:
179  // Returns true if the extension can specify the given |path|.
180  bool CanAccessPath(const std::string& path) const;
181  bool CanAccessKey(const std::string& key) const;
182
183  // A persistent, globally unique ID. An extension's ID is used in things
184  // like directory structures and URLs, and is expected to not change across
185  // versions. It is generated as a SHA-256 hash of the extension's public
186  // key, or as a hash of the path in the case of unpacked extensions.
187  std::string extension_id_;
188
189  // The location the extension was loaded from.
190  Location location_;
191
192  // The underlying dictionary representation of the manifest.
193  scoped_ptr<base::DictionaryValue> value_;
194
195  Type type_;
196
197  DISALLOW_COPY_AND_ASSIGN(Manifest);
198};
199
200}  // namespace extensions
201
202#endif  // EXTENSIONS_COMMON_MANIFEST_H_
203