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 16 namespace extensions { 17 struct InstallWarning; 18 19 // Wraps the DictionaryValue form of extension's manifest. Enforces access to 20 // properties of the manifest using ManifestFeatureProvider. 21 class 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