Home | History | Annotate | Download | only in appcache
      1 // Copyright (c) 2009 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 #include "webkit/browser/appcache/appcache_storage.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/stl_util.h"
     10 #include "webkit/browser/appcache/appcache_response.h"
     11 #include "webkit/browser/appcache/appcache_service.h"
     12 #include "webkit/browser/quota/quota_client.h"
     13 #include "webkit/browser/quota/quota_manager.h"
     14 
     15 namespace appcache {
     16 
     17 // static
     18 const int64 AppCacheStorage::kUnitializedId = -1;
     19 
     20 AppCacheStorage::AppCacheStorage(AppCacheService* service)
     21     : last_cache_id_(kUnitializedId), last_group_id_(kUnitializedId),
     22       last_response_id_(kUnitializedId), service_(service)  {
     23 }
     24 
     25 AppCacheStorage::~AppCacheStorage() {
     26   STLDeleteValues(&pending_info_loads_);
     27   DCHECK(delegate_references_.empty());
     28 }
     29 
     30 AppCacheStorage::DelegateReference::DelegateReference(
     31     Delegate* delegate, AppCacheStorage* storage)
     32     : delegate(delegate), storage(storage) {
     33   storage->delegate_references_.insert(
     34       DelegateReferenceMap::value_type(delegate, this));
     35 }
     36 
     37 AppCacheStorage::DelegateReference::~DelegateReference() {
     38   if (delegate)
     39     storage->delegate_references_.erase(delegate);
     40 }
     41 
     42 AppCacheStorage::ResponseInfoLoadTask::ResponseInfoLoadTask(
     43     const GURL& manifest_url,
     44     int64 group_id,
     45     int64 response_id,
     46     AppCacheStorage* storage)
     47     : storage_(storage),
     48       manifest_url_(manifest_url),
     49       group_id_(group_id),
     50       response_id_(response_id),
     51       info_buffer_(new HttpResponseInfoIOBuffer) {
     52   storage_->pending_info_loads_.insert(
     53       PendingResponseInfoLoads::value_type(response_id, this));
     54 }
     55 
     56 AppCacheStorage::ResponseInfoLoadTask::~ResponseInfoLoadTask() {
     57 }
     58 
     59 void AppCacheStorage::ResponseInfoLoadTask::StartIfNeeded() {
     60   if (reader_)
     61     return;
     62   reader_.reset(
     63       storage_->CreateResponseReader(manifest_url_, group_id_, response_id_));
     64   reader_->ReadInfo(info_buffer_.get(),
     65                     base::Bind(&ResponseInfoLoadTask::OnReadComplete,
     66                                base::Unretained(this)));
     67 }
     68 
     69 void AppCacheStorage::ResponseInfoLoadTask::OnReadComplete(int result) {
     70   storage_->pending_info_loads_.erase(response_id_);
     71   scoped_refptr<AppCacheResponseInfo> info;
     72   if (result >= 0) {
     73     info = new AppCacheResponseInfo(storage_, manifest_url_,
     74                                     response_id_,
     75                                     info_buffer_->http_info.release(),
     76                                     info_buffer_->response_data_size);
     77   }
     78   FOR_EACH_DELEGATE(delegates_, OnResponseInfoLoaded(info.get(), response_id_));
     79   delete this;
     80 }
     81 
     82 void AppCacheStorage::LoadResponseInfo(
     83     const GURL& manifest_url, int64 group_id, int64 id, Delegate* delegate) {
     84   AppCacheResponseInfo* info = working_set_.GetResponseInfo(id);
     85   if (info) {
     86     delegate->OnResponseInfoLoaded(info, id);
     87     return;
     88   }
     89   ResponseInfoLoadTask* info_load =
     90       GetOrCreateResponseInfoLoadTask(manifest_url, group_id, id);
     91   DCHECK(manifest_url == info_load->manifest_url());
     92   DCHECK(group_id == info_load->group_id());
     93   DCHECK(id == info_load->response_id());
     94   info_load->AddDelegate(GetOrCreateDelegateReference(delegate));
     95   info_load->StartIfNeeded();
     96 }
     97 
     98 void AppCacheStorage::UpdateUsageMapAndNotify(
     99     const GURL& origin, int64 new_usage) {
    100   DCHECK_GE(new_usage, 0);
    101   int64 old_usage = usage_map_[origin];
    102   if (new_usage > 0)
    103     usage_map_[origin] = new_usage;
    104   else
    105     usage_map_.erase(origin);
    106   if (new_usage != old_usage && service()->quota_manager_proxy()) {
    107     service()->quota_manager_proxy()->NotifyStorageModified(
    108         quota::QuotaClient::kAppcache,
    109         origin, quota::kStorageTypeTemporary,
    110         new_usage - old_usage);
    111   }
    112 }
    113 
    114 void AppCacheStorage::ClearUsageMapAndNotify() {
    115   if (service()->quota_manager_proxy()) {
    116     for (UsageMap::const_iterator iter = usage_map_.begin();
    117          iter != usage_map_.end(); ++iter) {
    118       service()->quota_manager_proxy()->NotifyStorageModified(
    119           quota::QuotaClient::kAppcache,
    120           iter->first, quota::kStorageTypeTemporary,
    121           -(iter->second));
    122     }
    123   }
    124   usage_map_.clear();
    125 }
    126 
    127 void AppCacheStorage::NotifyStorageAccessed(const GURL& origin) {
    128   if (service()->quota_manager_proxy() &&
    129       usage_map_.find(origin) != usage_map_.end())
    130     service()->quota_manager_proxy()->NotifyStorageAccessed(
    131         quota::QuotaClient::kAppcache,
    132         origin, quota::kStorageTypeTemporary);
    133 }
    134 
    135 }  // namespace appcache
    136 
    137