Home | History | Annotate | Download | only in common
      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