1// Copyright (c) 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 CHROME_COMMON_EXTENSIONS_EXTENSION_H_
6#define CHROME_COMMON_EXTENSIONS_EXTENSION_H_
7
8#include <algorithm>
9#include <iosfwd>
10#include <map>
11#include <set>
12#include <string>
13#include <utility>
14#include <vector>
15
16#include "base/containers/hash_tables.h"
17#include "base/files/file_path.h"
18#include "base/memory/linked_ptr.h"
19#include "base/memory/ref_counted.h"
20#include "base/memory/scoped_ptr.h"
21#include "base/synchronization/lock.h"
22#include "base/threading/thread_checker.h"
23#include "chrome/common/extensions/extension_constants.h"
24#include "chrome/common/extensions/manifest.h"
25#include "chrome/common/extensions/permissions/api_permission.h"
26#include "extensions/common/extension_resource.h"
27#include "extensions/common/install_warning.h"
28#include "extensions/common/url_pattern.h"
29#include "extensions/common/url_pattern_set.h"
30#include "ui/base/accelerators/accelerator.h"
31#include "ui/gfx/size.h"
32#include "url/gurl.h"
33
34class ExtensionAction;
35class SkBitmap;
36
37namespace base {
38class DictionaryValue;
39class Version;
40}
41
42namespace gfx {
43class ImageSkia;
44}
45
46namespace extensions {
47class PermissionsData;
48class APIPermissionSet;
49class PermissionSet;
50
51// Represents a Chrome extension.
52// Once created, an Extension object is immutable, with the exception of its
53// RuntimeData. This makes it safe to use on any thread, since access to the
54// RuntimeData is protected by a lock.
55class Extension : public base::RefCountedThreadSafe<Extension> {
56 public:
57  struct ManifestData;
58
59  typedef std::vector<std::string> ScriptingWhitelist;
60  typedef std::map<const std::string, linked_ptr<ManifestData> >
61      ManifestDataMap;
62
63  enum State {
64    DISABLED = 0,
65    ENABLED,
66    // An external extension that the user uninstalled. We should not reinstall
67    // such extensions on startup.
68    EXTERNAL_EXTENSION_UNINSTALLED,
69    // Special state for component extensions, since they are always loaded by
70    // the component loader, and should never be auto-installed on startup.
71    ENABLED_COMPONENT,
72    NUM_STATES
73  };
74
75  // Used to record the reason an extension was disabled.
76  enum DeprecatedDisableReason {
77    DEPRECATED_DISABLE_UNKNOWN,
78    DEPRECATED_DISABLE_USER_ACTION,
79    DEPRECATED_DISABLE_PERMISSIONS_INCREASE,
80    DEPRECATED_DISABLE_RELOAD,
81    DEPRECATED_DISABLE_LAST,  // Not used.
82  };
83
84  enum DisableReason {
85    DISABLE_NONE = 0,
86    DISABLE_USER_ACTION = 1 << 0,
87    DISABLE_PERMISSIONS_INCREASE = 1 << 1,
88    DISABLE_RELOAD = 1 << 2,
89    DISABLE_UNSUPPORTED_REQUIREMENT = 1 << 3,
90    DISABLE_SIDELOAD_WIPEOUT = 1 << 4,
91    DISABLE_UNKNOWN_FROM_SYNC = 1 << 5,
92  };
93
94  enum InstallType {
95    INSTALL_ERROR,
96    DOWNGRADE,
97    REINSTALL,
98    UPGRADE,
99    NEW_INSTALL
100  };
101
102  // A base class for parsed manifest data that APIs want to store on
103  // the extension. Related to base::SupportsUserData, but with an immutable
104  // thread-safe interface to match Extension.
105  struct ManifestData {
106    virtual ~ManifestData() {}
107  };
108
109  enum InitFromValueFlags {
110    NO_FLAGS = 0,
111
112    // Usually, the id of an extension is generated by the "key" property of
113    // its manifest, but if |REQUIRE_KEY| is not set, a temporary ID will be
114    // generated based on the path.
115    REQUIRE_KEY = 1 << 0,
116
117    // Requires the extension to have an up-to-date manifest version.
118    // Typically, we'll support multiple manifest versions during a version
119    // transition. This flag signals that we want to require the most modern
120    // manifest version that Chrome understands.
121    REQUIRE_MODERN_MANIFEST_VERSION = 1 << 1,
122
123    // |ALLOW_FILE_ACCESS| indicates that the user is allowing this extension
124    // to have file access. If it's not present, then permissions and content
125    // scripts that match file:/// URLs will be filtered out.
126    ALLOW_FILE_ACCESS = 1 << 2,
127
128    // |FROM_WEBSTORE| indicates that the extension was installed from the
129    // Chrome Web Store.
130    FROM_WEBSTORE = 1 << 3,
131
132    // |FROM_BOOKMARK| indicates the extension was created using a mock App
133    // created from a bookmark.
134    FROM_BOOKMARK = 1 << 4,
135
136    // |FOLLOW_SYMLINKS_ANYWHERE| means that resources can be symlinks to
137    // anywhere in the filesystem, rather than being restricted to the
138    // extension directory.
139    FOLLOW_SYMLINKS_ANYWHERE = 1 << 5,
140
141    // |ERROR_ON_PRIVATE_KEY| means that private keys inside an
142    // extension should be errors rather than warnings.
143    ERROR_ON_PRIVATE_KEY = 1 << 6,
144
145    // |WAS_INSTALLED_BY_DEFAULT| installed by default when the profile was
146    // created.
147    WAS_INSTALLED_BY_DEFAULT = 1 << 7,
148  };
149
150  static scoped_refptr<Extension> Create(const base::FilePath& path,
151                                         Manifest::Location location,
152                                         const base::DictionaryValue& value,
153                                         int flags,
154                                         std::string* error);
155
156  // In a few special circumstances, we want to create an Extension and give it
157  // an explicit id. Most consumers should just use the other Create() method.
158  static scoped_refptr<Extension> Create(const base::FilePath& path,
159                                         Manifest::Location location,
160                                         const base::DictionaryValue& value,
161                                         int flags,
162                                         const std::string& explicit_id,
163                                         std::string* error);
164
165  // Valid schemes for web extent URLPatterns.
166  static const int kValidWebExtentSchemes;
167
168  // Valid schemes for host permission URLPatterns.
169  static const int kValidHostPermissionSchemes;
170
171#if defined(OS_WIN)
172  static const char kExtensionRegistryPath[];
173#endif
174
175  // The mimetype used for extensions.
176  static const char kMimeType[];
177
178  // Checks to see if the extension has a valid ID.
179  static bool IdIsValid(const std::string& id);
180
181  // See Type definition in Manifest.
182  Manifest::Type GetType() const;
183
184  // Returns an absolute url to a resource inside of an extension. The
185  // |extension_url| argument should be the url() from an Extension object. The
186  // |relative_path| can be untrusted user input. The returned URL will either
187  // be invalid() or a child of |extension_url|.
188  // NOTE: Static so that it can be used from multiple threads.
189  static GURL GetResourceURL(const GURL& extension_url,
190                             const std::string& relative_path);
191  GURL GetResourceURL(const std::string& relative_path) const {
192    return GetResourceURL(url(), relative_path);
193  }
194
195  // Returns true if the resource matches a pattern in the pattern_set.
196  bool ResourceMatches(const URLPatternSet& pattern_set,
197                       const std::string& resource) const;
198
199  // Returns an extension resource object. |relative_path| should be UTF8
200  // encoded.
201  ExtensionResource GetResource(const std::string& relative_path) const;
202
203  // As above, but with |relative_path| following the file system's encoding.
204  ExtensionResource GetResource(const base::FilePath& relative_path) const;
205
206  // |input| is expected to be the text of an rsa public or private key. It
207  // tolerates the presence or absence of bracking header/footer like this:
208  //     -----(BEGIN|END) [RSA PUBLIC/PRIVATE] KEY-----
209  // and may contain newlines.
210  static bool ParsePEMKeyBytes(const std::string& input, std::string* output);
211
212  // Does a simple base64 encoding of |input| into |output|.
213  static bool ProducePEM(const std::string& input, std::string* output);
214
215  // Expects base64 encoded |input| and formats into |output| including
216  // the appropriate header & footer.
217  static bool FormatPEMForFileOutput(const std::string& input,
218                                     std::string* output,
219                                     bool is_public);
220
221  // Returns the base extension url for a given |extension_id|.
222  static GURL GetBaseURLFromExtensionId(const std::string& extension_id);
223
224  // Adds an extension to the scripting whitelist. Used for testing only.
225  static void SetScriptingWhitelist(const ScriptingWhitelist& whitelist);
226  static const ScriptingWhitelist* GetScriptingWhitelist();
227
228  // DEPRECATED: These methods have been moved to PermissionsData.
229  // TODO(rdevlin.cronin): remove these once all calls have been updated.
230  bool HasAPIPermission(APIPermission::ID permission) const;
231  bool HasAPIPermission(const std::string& permission_name) const;
232  scoped_refptr<const PermissionSet> GetActivePermissions() const;
233
234  // Whether context menu should be shown for page and browser actions.
235  bool ShowConfigureContextMenus() const;
236
237  // Returns true if this extension or app includes areas within |origin|.
238  bool OverlapsWithOrigin(const GURL& origin) const;
239
240  // Returns true if the extension requires a valid ordinal for sorting, e.g.,
241  // for displaying in a launcher or new tab page.
242  bool RequiresSortOrdinal() const;
243
244  // Returns true if the extension should be displayed in the app launcher.
245  bool ShouldDisplayInAppLauncher() const;
246
247  // Returns true if the extension should be displayed in the browser NTP.
248  bool ShouldDisplayInNewTabPage() const;
249
250  // Returns true if the extension should be displayed in the extension
251  // settings page (i.e. chrome://extensions).
252  bool ShouldDisplayInExtensionSettings() const;
253
254  // Returns true if the extension should not be shown anywhere. This is
255  // mostly the same as the extension being a component extension, but also
256  // includes non-component apps that are hidden from the app launcher and ntp.
257  bool ShouldNotBeVisible() const;
258
259  // Get the manifest data associated with the key, or NULL if there is none.
260  // Can only be called after InitValue is finished.
261  ManifestData* GetManifestData(const std::string& key) const;
262
263  // Sets |data| to be associated with the key. Takes ownership of |data|.
264  // Can only be called before InitValue is finished. Not thread-safe;
265  // all SetManifestData calls should be on only one thread.
266  void SetManifestData(const std::string& key, ManifestData* data);
267
268  // Accessors:
269
270  const base::FilePath& path() const { return path_; }
271  const GURL& url() const { return extension_url_; }
272  Manifest::Location location() const;
273  const std::string& id() const;
274  const base::Version* version() const { return version_.get(); }
275  const std::string VersionString() const;
276  const std::string& name() const { return name_; }
277  const std::string& non_localized_name() const { return non_localized_name_; }
278  // Base64-encoded version of the key used to sign this extension.
279  // In pseudocode, returns
280  // base::Base64Encode(RSAPrivateKey(pem_file).ExportPublicKey()).
281  const std::string& public_key() const { return public_key_; }
282  const std::string& description() const { return description_; }
283  int manifest_version() const { return manifest_version_; }
284  bool converted_from_user_script() const {
285    return converted_from_user_script_;
286  }
287  PermissionsData* permissions_data() { return permissions_data_.get(); }
288  const PermissionsData* permissions_data() const {
289    return permissions_data_.get();
290  }
291
292  // Appends |new_warning[s]| to install_warnings_.
293  void AddInstallWarning(const InstallWarning& new_warning);
294  void AddInstallWarnings(const std::vector<InstallWarning>& new_warnings);
295  const std::vector<InstallWarning>& install_warnings() const {
296    return install_warnings_;
297  }
298  const extensions::Manifest* manifest() const {
299    return manifest_.get();
300  }
301  bool wants_file_access() const { return wants_file_access_; }
302  // TODO(rdevlin.cronin): This is needed for ContentScriptsHandler, and should
303  // be moved out as part of crbug.com/159265. This should not be used anywhere
304  // else.
305  void set_wants_file_access(bool wants_file_access) {
306    wants_file_access_ = wants_file_access;
307  }
308  int creation_flags() const { return creation_flags_; }
309  bool from_webstore() const { return (creation_flags_ & FROM_WEBSTORE) != 0; }
310  bool from_bookmark() const { return (creation_flags_ & FROM_BOOKMARK) != 0; }
311  bool was_installed_by_default() const {
312    return (creation_flags_ & WAS_INSTALLED_BY_DEFAULT) != 0;
313  }
314
315  // App-related.
316  bool is_app() const;
317  bool is_platform_app() const;
318  bool is_hosted_app() const;
319  bool is_legacy_packaged_app() const;
320  bool is_extension() const;
321  bool can_be_incognito_enabled() const;
322  bool force_incognito_enabled() const;
323
324  void AddWebExtentPattern(const URLPattern& pattern);
325  const URLPatternSet& web_extent() const { return extent_; }
326
327  // Theme-related.
328  bool is_theme() const;
329
330 private:
331  friend class base::RefCountedThreadSafe<Extension>;
332
333  // Chooses the extension ID for an extension based on a variety of criteria.
334  // The chosen ID will be set in |manifest|.
335  static bool InitExtensionID(extensions::Manifest* manifest,
336                              const base::FilePath& path,
337                              const std::string& explicit_id,
338                              int creation_flags,
339                              string16* error);
340
341  Extension(const base::FilePath& path,
342            scoped_ptr<extensions::Manifest> manifest);
343  virtual ~Extension();
344
345  // Initialize the extension from a parsed manifest.
346  // TODO(aa): Rename to just Init()? There's no Value here anymore.
347  // TODO(aa): It is really weird the way this class essentially contains a copy
348  // of the underlying DictionaryValue in its members. We should decide to
349  // either wrap the DictionaryValue and go with that only, or we should parse
350  // into strong types and discard the value. But doing both is bad.
351  bool InitFromValue(int flags, string16* error);
352
353  // The following are helpers for InitFromValue to load various features of the
354  // extension from the manifest.
355
356  bool LoadRequiredFeatures(string16* error);
357  bool LoadName(string16* error);
358  bool LoadVersion(string16* error);
359
360  bool LoadAppFeatures(string16* error);
361  bool LoadExtent(const char* key,
362                  URLPatternSet* extent,
363                  const char* list_error,
364                  const char* value_error,
365                  string16* error);
366
367  bool LoadSharedFeatures(string16* error);
368  bool LoadDescription(string16* error);
369  bool LoadManifestVersion(string16* error);
370
371  bool CheckMinimumChromeVersion(string16* error) const;
372
373  // The extension's human-readable name. Name is used for display purpose. It
374  // might be wrapped with unicode bidi control characters so that it is
375  // displayed correctly in RTL context.
376  // NOTE: Name is UTF-8 and may contain non-ascii characters.
377  std::string name_;
378
379  // A non-localized version of the extension's name. This is useful for
380  // debug output.
381  std::string non_localized_name_;
382
383  // The version of this extension's manifest. We increase the manifest
384  // version when making breaking changes to the extension system.
385  // Version 1 was the first manifest version (implied by a lack of a
386  // manifest_version attribute in the extension's manifest). We initialize
387  // this member variable to 0 to distinguish the "uninitialized" case from
388  // the case when we know the manifest version actually is 1.
389  int manifest_version_;
390
391  // The absolute path to the directory the extension is stored in.
392  base::FilePath path_;
393
394  // Defines the set of URLs in the extension's web content.
395  URLPatternSet extent_;
396
397  scoped_ptr<PermissionsData> permissions_data_;
398
399  // Any warnings that occurred when trying to create/parse the extension.
400  std::vector<InstallWarning> install_warnings_;
401
402  // The base extension url for the extension.
403  GURL extension_url_;
404
405  // The extension's version.
406  scoped_ptr<base::Version> version_;
407
408  // An optional longer description of the extension.
409  std::string description_;
410
411  // True if the extension was generated from a user script. (We show slightly
412  // different UI if so).
413  bool converted_from_user_script_;
414
415  // The public key used to sign the contents of the crx package.
416  std::string public_key_;
417
418  // The manifest from which this extension was created.
419  scoped_ptr<Manifest> manifest_;
420
421  // Stored parsed manifest data.
422  ManifestDataMap manifest_data_;
423
424  // Set to true at the end of InitValue when initialization is finished.
425  bool finished_parsing_manifest_;
426
427  // Ensures that any call to GetManifestData() prior to finishing
428  // initialization happens from the same thread (this can happen when certain
429  // parts of the initialization process need information from previous parts).
430  base::ThreadChecker thread_checker_;
431
432  // Should this app be shown in the app launcher.
433  bool display_in_launcher_;
434
435  // Should this app be shown in the browser New Tab Page.
436  bool display_in_new_tab_page_;
437
438  // Whether the extension has host permissions or user script patterns that
439  // imply access to file:/// scheme URLs (the user may not have actually
440  // granted it that access).
441  bool wants_file_access_;
442
443  // The flags that were passed to InitFromValue.
444  int creation_flags_;
445
446  DISALLOW_COPY_AND_ASSIGN(Extension);
447};
448
449typedef std::vector<scoped_refptr<const Extension> > ExtensionList;
450typedef std::set<std::string> ExtensionIdSet;
451typedef std::vector<std::string> ExtensionIdList;
452
453// Handy struct to pass core extension info around.
454struct ExtensionInfo {
455  ExtensionInfo(const base::DictionaryValue* manifest,
456                const std::string& id,
457                const base::FilePath& path,
458                Manifest::Location location);
459  ~ExtensionInfo();
460
461  scoped_ptr<base::DictionaryValue> extension_manifest;
462  std::string extension_id;
463  base::FilePath extension_path;
464  Manifest::Location extension_location;
465
466 private:
467  DISALLOW_COPY_AND_ASSIGN(ExtensionInfo);
468};
469
470struct InstalledExtensionInfo {
471  // The extension being installed - this should always be non-NULL.
472  const Extension* extension;
473
474  // True if the extension is being updated; false if it is being installed.
475  bool is_update;
476
477  // The name of the extension prior to this update. Will be empty if
478  // |is_update| is false.
479  std::string old_name;
480
481  InstalledExtensionInfo(const Extension* extension,
482                         bool is_update,
483                         const std::string& old_name);
484};
485
486struct UnloadedExtensionInfo {
487  extension_misc::UnloadedExtensionReason reason;
488
489  // The extension being unloaded - this should always be non-NULL.
490  const Extension* extension;
491
492  UnloadedExtensionInfo(
493      const Extension* extension,
494      extension_misc::UnloadedExtensionReason reason);
495};
496
497// The details sent for EXTENSION_PERMISSIONS_UPDATED notifications.
498struct UpdatedExtensionPermissionsInfo {
499  enum Reason {
500    ADDED,    // The permissions were added to the extension.
501    REMOVED,  // The permissions were removed from the extension.
502  };
503
504  Reason reason;
505
506  // The extension who's permissions have changed.
507  const Extension* extension;
508
509  // The permissions that have changed. For Reason::ADDED, this would contain
510  // only the permissions that have added, and for Reason::REMOVED, this would
511  // only contain the removed permissions.
512  const PermissionSet* permissions;
513
514  UpdatedExtensionPermissionsInfo(
515      const Extension* extension,
516      const PermissionSet* permissions,
517      Reason reason);
518};
519
520}  // namespace extensions
521
522#endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_H_
523