Home | History | Annotate | Download | only in appcache
      1 // Copyright (c) 2011 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 WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_
      6 #define WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_
      7 
      8 #include "base/callback.h"
      9 #include "base/gtest_prod_util.h"
     10 #include "base/memory/ref_counted.h"
     11 #include "base/observer_list.h"
     12 #include "url/gurl.h"
     13 #include "webkit/browser/appcache/appcache_group.h"
     14 #include "webkit/browser/appcache/appcache_service.h"
     15 #include "webkit/browser/appcache/appcache_storage.h"
     16 #include "webkit/browser/webkit_storage_browser_export.h"
     17 #include "webkit/common/appcache/appcache_interfaces.h"
     18 #include "webkit/common/resource_type.h"
     19 
     20 namespace net {
     21 class URLRequest;
     22 }  // namespace net
     23 
     24 namespace appcache {
     25 
     26 class AppCache;
     27 class AppCacheFrontend;
     28 class AppCacheRequestHandler;
     29 
     30 typedef base::Callback<void(Status, void*)> GetStatusCallback;
     31 typedef base::Callback<void(bool, void*)> StartUpdateCallback;
     32 typedef base::Callback<void(bool, void*)> SwapCacheCallback;
     33 
     34 // Server-side representation of an application cache host.
     35 class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheHost
     36     : public AppCacheStorage::Delegate,
     37       public AppCacheGroup::UpdateObserver {
     38  public:
     39 
     40   class WEBKIT_STORAGE_BROWSER_EXPORT Observer {
     41    public:
     42     // Called just after the cache selection algorithm completes.
     43     virtual void OnCacheSelectionComplete(AppCacheHost* host) = 0;
     44 
     45     // Called just prior to the instance being deleted.
     46     virtual void OnDestructionImminent(AppCacheHost* host) = 0;
     47 
     48     virtual ~Observer() {}
     49   };
     50 
     51   AppCacheHost(int host_id, AppCacheFrontend* frontend,
     52                AppCacheService* service);
     53   virtual ~AppCacheHost();
     54 
     55   // Adds/removes an observer, the AppCacheHost does not take
     56   // ownership of the observer.
     57   void AddObserver(Observer* observer);
     58   void RemoveObserver(Observer* observer);
     59 
     60   // Support for cache selection and scriptable method calls.
     61   void SelectCache(const GURL& document_url,
     62                    const int64 cache_document_was_loaded_from,
     63                    const GURL& manifest_url);
     64   void SelectCacheForWorker(int parent_process_id,
     65                             int parent_host_id);
     66   void SelectCacheForSharedWorker(int64 appcache_id);
     67   void MarkAsForeignEntry(const GURL& document_url,
     68                           int64 cache_document_was_loaded_from);
     69   void GetStatusWithCallback(const GetStatusCallback& callback,
     70                              void* callback_param);
     71   void StartUpdateWithCallback(const StartUpdateCallback& callback,
     72                                void* callback_param);
     73   void SwapCacheWithCallback(const SwapCacheCallback& callback,
     74                              void* callback_param);
     75 
     76   // Called prior to the main resource load. When the system contains multiple
     77   // candidates for a main resource load, the appcache preferred by the host
     78   // that created this host is used to break ties.
     79   void SetSpawningHostId(int spawning_process_id, int spawning_host_id);
     80 
     81   // May return NULL if the spawning host context has been closed, or if a
     82   // spawning host context was never identified.
     83   const AppCacheHost* GetSpawningHost() const;
     84 
     85   const GURL& preferred_manifest_url() const {
     86     return preferred_manifest_url_;
     87   }
     88   void set_preferred_manifest_url(const GURL& url) {
     89     preferred_manifest_url_ = url;
     90   }
     91 
     92   // Support for loading resources out of the appcache.
     93   // May return NULL if the request isn't subject to retrieval from an appache.
     94   AppCacheRequestHandler* CreateRequestHandler(
     95       net::URLRequest* request, ResourceType::Type resource_type);
     96 
     97   // Support for devtools inspecting appcache resources.
     98   void GetResourceList(std::vector<AppCacheResourceInfo>* resource_infos);
     99 
    100   // Breaks any existing association between this host and a cache.
    101   // 'manifest_url' is sent to DevTools as the manifest url that could have
    102   // been associated before or could be associated later with this host.
    103   // Associations are broken either thru the cache selection algorithm
    104   // implemented in this class, or by the update algorithm (see
    105   // AppCacheUpdateJob).
    106   void AssociateNoCache(const GURL& manifest_url);
    107 
    108   // Establishes an association between this host and an incomplete cache.
    109   // 'manifest_url' is manifest url of the cache group being updated.
    110   // Associations with incomplete caches are established by the update algorithm
    111   // (see AppCacheUpdateJob).
    112   void AssociateIncompleteCache(AppCache* cache, const GURL& manifest_url);
    113 
    114   // Establishes an association between this host and a complete cache.
    115   // Associations with complete caches are established either thru the cache
    116   // selection algorithm implemented (in this class), or by the update algorithm
    117   // (see AppCacheUpdateJob).
    118   void AssociateCompleteCache(AppCache* cache);
    119 
    120   // Adds a reference to the newest complete cache in a group, unless it's the
    121   // same as the cache that is currently associated with the host.
    122   void SetSwappableCache(AppCacheGroup* group);
    123 
    124   // Used to ensure that a loaded appcache survives a frame navigation.
    125   void LoadMainResourceCache(int64 cache_id);
    126 
    127   // Used to notify the host that a namespace resource is being delivered as
    128   // the main resource of the page and to provide its url.
    129   void NotifyMainResourceIsNamespaceEntry(const GURL& namespace_entry_url);
    130 
    131   // Used to notify the host that the main resource was blocked by a policy. To
    132   // work properly, this method needs to by invoked prior to cache selection.
    133   void NotifyMainResourceBlocked(const GURL& manifest_url);
    134 
    135   // Used by the update job to keep track of which hosts are associated
    136   // with which pending master entries.
    137   const GURL& pending_master_entry_url() const {
    138     return new_master_entry_url_;
    139   }
    140 
    141   int host_id() const { return host_id_; }
    142   AppCacheService* service() const { return service_; }
    143   AppCacheFrontend* frontend() const { return frontend_; }
    144   AppCache* associated_cache() const { return associated_cache_.get(); }
    145 
    146   bool is_selection_pending() const {
    147     return pending_selected_cache_id_ != kNoCacheId ||
    148            !pending_selected_manifest_url_.is_empty();
    149   }
    150 
    151   const GURL& first_party_url() const { return first_party_url_; }
    152 
    153  private:
    154   Status GetStatus();
    155   void LoadSelectedCache(int64 cache_id);
    156   void LoadOrCreateGroup(const GURL& manifest_url);
    157 
    158   // See public Associate*Host() methods above.
    159   void AssociateCacheHelper(AppCache* cache, const GURL& manifest_url);
    160 
    161   // AppCacheStorage::Delegate impl
    162   virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE;
    163   virtual void OnGroupLoaded(AppCacheGroup* group,
    164                              const GURL& manifest_url) OVERRIDE;
    165 
    166   void FinishCacheSelection(AppCache* cache, AppCacheGroup* group);
    167   void DoPendingGetStatus();
    168   void DoPendingStartUpdate();
    169   void DoPendingSwapCache();
    170 
    171   void ObserveGroupBeingUpdated(AppCacheGroup* group);
    172 
    173   // AppCacheGroup::UpdateObserver methods.
    174   virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE;
    175 
    176   // Returns true if this host is for a dedicated worker context.
    177   bool is_for_dedicated_worker() const {
    178     return parent_host_id_ != kNoHostId;
    179   }
    180 
    181   // Returns the parent context's host instance. This is only valid
    182   // to call when this instance is_for_dedicated_worker.
    183   AppCacheHost* GetParentAppCacheHost() const;
    184 
    185   // Identifies the corresponding appcache host in the child process.
    186   int host_id_;
    187 
    188   // Information about the host that created this one; the manifest
    189   // preferred by our creator influences which cache our main resource
    190   // should be loaded from.
    191   int spawning_host_id_;
    192   int spawning_process_id_;
    193   GURL preferred_manifest_url_;
    194 
    195   // Hosts for dedicated workers are special cased to shunt
    196   // request handling off to the dedicated worker's parent.
    197   // The scriptable api is not accessible in dedicated workers
    198   // so the other aspects of this class are not relevant for
    199   // these special case instances.
    200   int parent_host_id_;
    201   int parent_process_id_;
    202 
    203   // The cache associated with this host, if any.
    204   scoped_refptr<AppCache> associated_cache_;
    205 
    206   // Hold a reference to the newest complete cache (if associated cache is
    207   // not the newest) to keep the newest cache in existence while the app cache
    208   // group is in use. The newest complete cache may have no associated hosts
    209   // holding any references to it and would otherwise be deleted prematurely.
    210   scoped_refptr<AppCache> swappable_cache_;
    211 
    212   // Keep a reference to the group being updated until the update completes.
    213   scoped_refptr<AppCacheGroup> group_being_updated_;
    214 
    215   // Similarly, keep a reference to the newest cache of the group until the
    216   // update completes. When adding a new master entry to a cache that is not
    217   // in use in any other host, this reference keeps the cache in  memory.
    218   scoped_refptr<AppCache> newest_cache_of_group_being_updated_;
    219 
    220   // Keep a reference to the cache of the main resource so it survives frame
    221   // navigations.
    222   scoped_refptr<AppCache> main_resource_cache_;
    223   int64 pending_main_resource_cache_id_;
    224 
    225   // Cache loading is async, if we're loading a specific cache or group
    226   // for the purposes of cache selection, one or the other of these will
    227   // indicate which cache or group is being loaded.
    228   int64 pending_selected_cache_id_;
    229   GURL pending_selected_manifest_url_;
    230 
    231   // A new master entry to be added to the cache, may be empty.
    232   GURL new_master_entry_url_;
    233 
    234   // The frontend proxy to deliver notifications to the child process.
    235   AppCacheFrontend* frontend_;
    236 
    237   // Our central service object.
    238   AppCacheService* service_;
    239 
    240   // Since these are synchronous scriptable API calls in the client, there can
    241   // only be one type of callback pending. Also, we have to wait until we have a
    242   // cache selection prior to responding to these calls, as cache selection
    243   // involves async loading of a cache or a group from storage.
    244   GetStatusCallback pending_get_status_callback_;
    245   StartUpdateCallback pending_start_update_callback_;
    246   SwapCacheCallback pending_swap_cache_callback_;
    247   void* pending_callback_param_;
    248 
    249   // True if an intercept or fallback namespace resource was
    250   // delivered as the main resource.
    251   bool main_resource_was_namespace_entry_;
    252   GURL namespace_entry_url_;
    253 
    254   // True if requests for this host were blocked by a policy.
    255   bool main_resource_blocked_;
    256   GURL blocked_manifest_url_;
    257 
    258   // Tells if info about associated cache is pending. Info is pending
    259   // when update job has not returned success yet.
    260   bool associated_cache_info_pending_;
    261 
    262   // List of objects observing us.
    263   ObserverList<Observer> observers_;
    264 
    265   // Used to inform the QuotaManager of what origins are currently in use.
    266   GURL origin_in_use_;
    267 
    268   // First party url to be used in policy checks.
    269   GURL first_party_url_;
    270 
    271   friend class AppCacheRequestHandlerTest;
    272   friend class AppCacheUpdateJobTest;
    273   FRIEND_TEST_ALL_PREFIXES(AppCacheTest, CleanupUnusedCache);
    274   FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, CleanupUnusedGroup);
    275   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, Basic);
    276   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectNoCache);
    277   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForeignEntry);
    278   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedCacheLoad);
    279   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedGroupLoad);
    280   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SetSwappableCache);
    281   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForDedicatedWorker);
    282   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectCacheAllowed);
    283   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectCacheBlocked);
    284   FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, QueueUpdate);
    285 
    286   DISALLOW_COPY_AND_ASSIGN(AppCacheHost);
    287 };
    288 
    289 }  // namespace appcache
    290 
    291 #endif  // WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_
    292