Home | History | Annotate | Download | only in extensions
      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_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_CACHE_H_
      6 #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_CACHE_H_
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/callback_forward.h"
     12 #include "base/files/file_path.h"
     13 #include "base/gtest_prod_util.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "base/memory/weak_ptr.h"
     17 #include "base/sequenced_task_runner.h"
     18 #include "chrome/browser/extensions/updater/extension_downloader_delegate.h"
     19 #include "content/public/browser/notification_observer.h"
     20 #include "content/public/browser/notification_registrar.h"
     21 
     22 namespace base {
     23 class DictionaryValue;
     24 }
     25 
     26 namespace extensions {
     27 class ExtensionDownloader;
     28 }
     29 
     30 namespace net {
     31 class URLRequestContextGetter;
     32 }
     33 
     34 namespace chromeos {
     35 
     36 // The ExternalCache manages a cache for external extensions.
     37 class ExternalCache : public content::NotificationObserver,
     38                       public extensions::ExtensionDownloaderDelegate {
     39  public:
     40   class Delegate {
     41    public:
     42     virtual ~Delegate() {}
     43     // Caller owns |prefs|.
     44     virtual void OnExtensionListsUpdated(
     45         const base::DictionaryValue* prefs) = 0;
     46 
     47     // Cache needs to provide already installed extensions otherwise they
     48     // will be removed. Cache calls this function to get version of installed
     49     // extension or empty string if not installed.
     50     virtual std::string GetInstalledExtensionVersion(const std::string& id);
     51   };
     52 
     53   // The |request_context| is used for update checks. All file I/O is done via
     54   // the |backend_task_runner|. If |always_check_updates| is |false|, update
     55   // checks are performed for extensions that have an |external_update_url|
     56   // only. If |wait_for_cache_initialization| is |true|, the cache contents will
     57   // not be read until a flag file appears in the cache directory, signaling
     58   // that the cache is ready.
     59   ExternalCache(const base::FilePath& cache_dir,
     60                 net::URLRequestContextGetter* request_context,
     61                 const scoped_refptr<base::SequencedTaskRunner>&
     62                     backend_task_runner,
     63                 Delegate* delegate,
     64                 bool always_check_updates,
     65                 bool wait_for_cache_initialization);
     66   virtual ~ExternalCache();
     67 
     68   // Name of flag file that indicates that cache is ready (import finished).
     69   static const char kCacheReadyFlagFileName[];
     70 
     71   // Returns already cached extensions.
     72   const base::DictionaryValue* cached_extensions() {
     73     return cached_extensions_.get();
     74   }
     75 
     76   // Implementation of content::NotificationObserver:
     77   virtual void Observe(int type,
     78                        const content::NotificationSource& source,
     79                        const content::NotificationDetails& details) OVERRIDE;
     80 
     81   // Implementation of ExtensionDownloaderDelegate:
     82   virtual void OnExtensionDownloadFailed(
     83       const std::string& id,
     84       Error error,
     85       const PingResult& ping_result,
     86       const std::set<int>& request_ids) OVERRIDE;
     87 
     88   virtual void OnExtensionDownloadFinished(
     89       const std::string& id,
     90       const base::FilePath& path,
     91       const GURL& download_url,
     92       const std::string& version,
     93       const PingResult& ping_result,
     94       const std::set<int>& request_ids) OVERRIDE;
     95 
     96   virtual bool IsExtensionPending(const std::string& id) OVERRIDE;
     97 
     98   virtual bool GetExtensionExistingVersion(const std::string& id,
     99                                            std::string* version) OVERRIDE;
    100 
    101   // Shut down the cache. The |callback| will be invoked when the cache has shut
    102   // down completely and there are no more pending file I/O operations.
    103   void Shutdown(const base::Closure& callback);
    104 
    105   // Replace the list of extensions to cache with |prefs| and perform update
    106   // checks for these.
    107   void UpdateExtensionsList(scoped_ptr<base::DictionaryValue> prefs);
    108 
    109   // If a user of one of the ExternalCache's extensions detects that
    110   // the extension is damaged then this method can be used to remove it from
    111   // the cache and retry to download it after a restart.
    112   void OnDamagedFileDetected(const base::FilePath& path);
    113 
    114  private:
    115   // Notifies the that the cache has been updated, providing
    116   // extensions loader with an updated list of extensions.
    117   void UpdateExtensionLoader();
    118 
    119   // Checks the cache contents and deletes any entries no longer referenced by
    120   // |extensions_|. If |wait_for_cache_initialization_| is |true|, waits for the
    121   // cache to become ready first, as indicated by the presence of a flag file.
    122   void CheckCache();
    123 
    124   // Checks whether a flag file exists in the |cache_dir|, indicating that the
    125   // cache is ready. This method is invoked via the |backend_task_runner_| and
    126   // posts its result back to the |external_cache| on the UI thread.
    127   static void BackendCheckCacheStatus(
    128       base::WeakPtr<ExternalCache> external_cache,
    129       const base::FilePath& cache_dir);
    130 
    131   // Invoked on the UI thread after checking whether the cache is ready. If the
    132   // cache is not ready yet, posts a delayed task that will repeat the check,
    133   // thus polling for cache readiness.
    134   void OnCacheStatusChecked(bool ready);
    135 
    136   // Checks the cache contents. This is a helper that invokes the actual check
    137   // by posting to the |backend_task_runner_|.
    138   void CheckCacheContents();
    139 
    140   // Checks the cache contents, deleting any entries no longer referenced by
    141   // |prefs|. This method is invoked via the |backend_task_runner_| and posts
    142   // back a list of cache entries to the |external_cache| on the UI thread.
    143   static void BackendCheckCacheContents(
    144       base::WeakPtr<ExternalCache> external_cache,
    145       const base::FilePath& cache_dir,
    146       scoped_ptr<base::DictionaryValue> prefs);
    147 
    148   // Helper for BackendCheckCacheContents() that updates |prefs|.
    149   static void BackendCheckCacheContentsInternal(
    150       const base::FilePath& cache_dir,
    151       base::DictionaryValue* prefs);
    152 
    153   // Invoked when the cache has been updated. |prefs| contains all the currently
    154   // valid crx files in the cache, ownerships is transfered to this function.
    155   void OnCacheUpdated(scoped_ptr<base::DictionaryValue> prefs);
    156 
    157   // Installs the downloaded crx file at |path| in the |cache_dir|. This method
    158   // is invoked via the |backend_task_runner_|.
    159   static void BackendInstallCacheEntry(
    160       base::WeakPtr<ExternalCache> external_cache,
    161       const base::FilePath& cache_dir,
    162       const std::string& id,
    163       const base::FilePath& path,
    164       const std::string& version);
    165 
    166   // Invoked on the UI thread when a new entry has been installed in the cache.
    167   void OnCacheEntryInstalled(const std::string& id,
    168                              const base::FilePath& path,
    169                              const std::string& version);
    170 
    171   // Posted to the |backend_task_runner_| during cache shutdown so that it runs
    172   // after all file I/O has been completed. Invokes |callback| on the UI thread
    173   // to indicate that the cache has been shut down completely.
    174   static void BackendShudown(const base::Closure& callback);
    175 
    176   // Path to the directory where the extension cache is stored.
    177   base::FilePath cache_dir_;
    178 
    179   // Request context used by the |downloader_|.
    180   net::URLRequestContextGetter* request_context_;
    181 
    182   // Delegate that would like to get notifications about cache updates.
    183   Delegate* delegate_;
    184 
    185   // Whether the cache shutdown has been initiated.
    186   bool shutdown_;
    187 
    188   // Updates needs to be check for the extensions with external_crx too.
    189   bool always_check_updates_;
    190 
    191   // Set to true if cache should wait for initialization flag file.
    192   bool wait_for_cache_initialization_;
    193 
    194   // This is the list of extensions currently configured.
    195   scoped_ptr<base::DictionaryValue> extensions_;
    196 
    197   // This contains extensions that are both currently configured
    198   // and that have a valid crx in the cache.
    199   scoped_ptr<base::DictionaryValue> cached_extensions_;
    200 
    201   // Used to download the extensions and to check for updates.
    202   scoped_ptr<extensions::ExtensionDownloader> downloader_;
    203 
    204   // Task runner for executing file I/O tasks.
    205   scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
    206 
    207   // Observes failures to install CRX files.
    208   content::NotificationRegistrar notification_registrar_;
    209 
    210   // Weak factory for callbacks from the backend and delayed tasks.
    211   base::WeakPtrFactory<ExternalCache> weak_ptr_factory_;
    212 
    213   DISALLOW_COPY_AND_ASSIGN(ExternalCache);
    214 };
    215 
    216 }  // namespace chromeos
    217 
    218 #endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_CACHE_H_
    219