This source file includes following definitions.
- weak_factory_
 
- GetAllInfo
 
- LoadCache
 
- LoadOrCreateGroup
 
- StoreGroupAndNewestCache
 
- FindResponseForMainRequest
 
- FindResponseForSubRequest
 
- MarkEntryAsForeign
 
- MakeGroupObsolete
 
- CreateResponseReader
 
- CreateResponseWriter
 
- DoomResponses
 
- DeleteResponses
 
- ProcessGetAllInfo
 
- ProcessLoadCache
 
- ProcessLoadOrCreateGroup
 
- ProcessStoreGroupAndNewestCache
 
- MaybeTakeNewNamespaceEntry
 
- ProcessFindResponseForMainRequest
 
- ProcessMakeGroupObsolete
 
- ScheduleTask
 
- RunOnePendingTask
 
- AddStoredCache
 
- RemoveStoredCache
 
- RemoveStoredCaches
 
- AddStoredGroup
 
- RemoveStoredGroup
 
- ShouldGroupLoadAppearAsync
 
- ShouldCacheLoadAppearAsync
 
#include "webkit/browser/appcache/mock_appcache_storage.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "webkit/browser/appcache/appcache.h"
#include "webkit/browser/appcache/appcache_entry.h"
#include "webkit/browser/appcache/appcache_group.h"
#include "webkit/browser/appcache/appcache_response.h"
#include "webkit/browser/appcache/appcache_service.h"
namespace appcache {
MockAppCacheStorage::MockAppCacheStorage(AppCacheService* service)
    : AppCacheStorage(service),
      simulate_make_group_obsolete_failure_(false),
      simulate_store_group_and_newest_cache_failure_(false),
      simulate_find_main_resource_(false),
      simulate_find_sub_resource_(false),
      simulated_found_cache_id_(kNoCacheId),
      simulated_found_group_id_(0),
      simulated_found_network_namespace_(false),
      weak_factory_(this) {
  last_cache_id_ = 0;
  last_group_id_ = 0;
  last_response_id_ = 0;
}
MockAppCacheStorage::~MockAppCacheStorage() {
}
void MockAppCacheStorage::GetAllInfo(Delegate* delegate) {
  ScheduleTask(
      base::Bind(&MockAppCacheStorage::ProcessGetAllInfo,
                 weak_factory_.GetWeakPtr(),
                 make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
}
void MockAppCacheStorage::LoadCache(int64 id, Delegate* delegate) {
  DCHECK(delegate);
  AppCache* cache = working_set_.GetCache(id);
  if (ShouldCacheLoadAppearAsync(cache)) {
    ScheduleTask(
        base::Bind(&MockAppCacheStorage::ProcessLoadCache,
                   weak_factory_.GetWeakPtr(), id,
                   make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
    return;
  }
  ProcessLoadCache(id, GetOrCreateDelegateReference(delegate));
}
void MockAppCacheStorage::LoadOrCreateGroup(
    const GURL& manifest_url, Delegate* delegate) {
  DCHECK(delegate);
  AppCacheGroup* group = working_set_.GetGroup(manifest_url);
  if (ShouldGroupLoadAppearAsync(group)) {
    ScheduleTask(
        base::Bind(&MockAppCacheStorage::ProcessLoadOrCreateGroup,
                   weak_factory_.GetWeakPtr(), manifest_url,
                   make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
    return;
  }
  ProcessLoadOrCreateGroup(
      manifest_url, GetOrCreateDelegateReference(delegate));
}
void MockAppCacheStorage::StoreGroupAndNewestCache(
    AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) {
  DCHECK(group && delegate && newest_cache);
  
  ScheduleTask(
      base::Bind(&MockAppCacheStorage::ProcessStoreGroupAndNewestCache,
                 weak_factory_.GetWeakPtr(), make_scoped_refptr(group),
                 make_scoped_refptr(newest_cache),
                 make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
}
void MockAppCacheStorage::FindResponseForMainRequest(
    const GURL& url, const GURL& preferred_manifest_url, Delegate* delegate) {
  DCHECK(delegate);
  
  
  ScheduleTask(
      base::Bind(&MockAppCacheStorage::ProcessFindResponseForMainRequest,
                 weak_factory_.GetWeakPtr(), url,
                 make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
}
void MockAppCacheStorage::FindResponseForSubRequest(
    AppCache* cache, const GURL& url,
    AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
    bool* found_network_namespace) {
  DCHECK(cache && cache->is_complete());
  
  if (simulate_find_sub_resource_) {
    *found_entry = simulated_found_entry_;
    *found_fallback_entry = simulated_found_fallback_entry_;
    *found_network_namespace = simulated_found_network_namespace_;
    simulate_find_sub_resource_ = false;
    return;
  }
  GURL fallback_namespace_not_used;
  GURL intercept_namespace_not_used;
  cache->FindResponseForRequest(
      url, found_entry, &intercept_namespace_not_used,
      found_fallback_entry,  &fallback_namespace_not_used,
      found_network_namespace);
}
void MockAppCacheStorage::MarkEntryAsForeign(
    const GURL& entry_url, int64 cache_id) {
  AppCache* cache = working_set_.GetCache(cache_id);
  if (cache) {
    AppCacheEntry* entry = cache->GetEntry(entry_url);
    DCHECK(entry);
    if (entry)
      entry->add_types(AppCacheEntry::FOREIGN);
  }
}
void MockAppCacheStorage::MakeGroupObsolete(AppCacheGroup* group,
                                            Delegate* delegate,
                                            int response_code) {
  DCHECK(group && delegate);
  
  ScheduleTask(
      base::Bind(&MockAppCacheStorage::ProcessMakeGroupObsolete,
                 weak_factory_.GetWeakPtr(),
                 make_scoped_refptr(group),
                 make_scoped_refptr(GetOrCreateDelegateReference(delegate)),
                 response_code));
}
AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader(
    const GURL& manifest_url, int64 group_id, int64 response_id) {
  if (simulated_reader_)
    return simulated_reader_.release();
  return new AppCacheResponseReader(response_id, group_id, disk_cache());
}
AppCacheResponseWriter* MockAppCacheStorage::CreateResponseWriter(
    const GURL& manifest_url, int64 group_id) {
  return new AppCacheResponseWriter(NewResponseId(),  group_id, disk_cache());
}
void MockAppCacheStorage::DoomResponses(
    const GURL& manifest_url, const std::vector<int64>& response_ids) {
  DeleteResponses(manifest_url, response_ids);
}
void MockAppCacheStorage::DeleteResponses(
    const GURL& manifest_url, const std::vector<int64>& response_ids) {
  
  
  std::vector<int64>::const_iterator it = response_ids.begin();
  while (it != response_ids.end()) {
    doomed_response_ids_.insert(*it);
    ++it;
  }
}
void MockAppCacheStorage::ProcessGetAllInfo(
    scoped_refptr<DelegateReference> delegate_ref) {
  if (delegate_ref->delegate)
    delegate_ref->delegate->OnAllInfo(simulated_appcache_info_.get());
}
void MockAppCacheStorage::ProcessLoadCache(
    int64 id, scoped_refptr<DelegateReference> delegate_ref) {
  AppCache* cache = working_set_.GetCache(id);
  if (delegate_ref->delegate)
    delegate_ref->delegate->OnCacheLoaded(cache, id);
}
void MockAppCacheStorage::ProcessLoadOrCreateGroup(
    const GURL& manifest_url, scoped_refptr<DelegateReference> delegate_ref) {
  scoped_refptr<AppCacheGroup> group(working_set_.GetGroup(manifest_url));
  
  
  if (!group.get())
    group = new AppCacheGroup(service_->storage(), manifest_url, NewGroupId());
  if (delegate_ref->delegate)
    delegate_ref->delegate->OnGroupLoaded(group.get(), manifest_url);
}
void MockAppCacheStorage::ProcessStoreGroupAndNewestCache(
    scoped_refptr<AppCacheGroup> group,
    scoped_refptr<AppCache> newest_cache,
    scoped_refptr<DelegateReference> delegate_ref) {
  Delegate* delegate = delegate_ref->delegate;
  if (simulate_store_group_and_newest_cache_failure_) {
    if (delegate)
      delegate->OnGroupAndNewestCacheStored(
          group.get(), newest_cache.get(), false, false);
    return;
  }
  AddStoredGroup(group.get());
  if (newest_cache.get() != group->newest_complete_cache()) {
    newest_cache->set_complete(true);
    group->AddCache(newest_cache.get());
    AddStoredCache(newest_cache.get());
    
    
    AppCacheGroup::Caches copy = group->old_caches();
    RemoveStoredCaches(copy);
  }
  if (delegate)
    delegate->OnGroupAndNewestCacheStored(
        group.get(), newest_cache.get(), true, false);
}
namespace {
struct FoundCandidate {
  GURL namespace_entry_url;
  AppCacheEntry entry;
  int64 cache_id;
  int64 group_id;
  GURL manifest_url;
  bool is_cache_in_use;
  FoundCandidate()
      : cache_id(kNoCacheId), group_id(0), is_cache_in_use(false) {}
};
void MaybeTakeNewNamespaceEntry(
    NamespaceType namespace_type,
    const AppCacheEntry &entry,
    const GURL& namespace_url,
    bool cache_is_in_use,
    FoundCandidate* best_candidate,
    GURL* best_candidate_namespace,
    AppCache* cache,
    AppCacheGroup* group) {
  DCHECK(entry.has_response_id());
  bool take_new_entry = true;
  
  if (best_candidate->entry.has_response_id()) {
    
    size_t candidate_length =
        namespace_url.spec().length();
    size_t best_length =
        best_candidate_namespace->spec().length();
    if (candidate_length > best_length) {
      take_new_entry = true;
    } else if (candidate_length == best_length &&
               cache_is_in_use && !best_candidate->is_cache_in_use) {
      take_new_entry = true;
    } else {
      take_new_entry = false;
    }
  }
  if (take_new_entry) {
    if (namespace_type == FALLBACK_NAMESPACE) {
      best_candidate->namespace_entry_url =
          cache->GetFallbackEntryUrl(namespace_url);
    } else {
      best_candidate->namespace_entry_url =
          cache->GetInterceptEntryUrl(namespace_url);
    }
    best_candidate->entry = entry;
    best_candidate->cache_id = cache->cache_id();
    best_candidate->group_id = group->group_id();
    best_candidate->manifest_url = group->manifest_url();
    best_candidate->is_cache_in_use = cache_is_in_use;
    *best_candidate_namespace = namespace_url;
  }
}
}  
void MockAppCacheStorage::ProcessFindResponseForMainRequest(
    const GURL& url, scoped_refptr<DelegateReference> delegate_ref) {
  if (simulate_find_main_resource_) {
    simulate_find_main_resource_ = false;
    if (delegate_ref->delegate) {
      delegate_ref->delegate->OnMainResponseFound(
          url, simulated_found_entry_,
          simulated_found_fallback_url_, simulated_found_fallback_entry_,
          simulated_found_cache_id_, simulated_found_group_id_,
          simulated_found_manifest_url_);
    }
    return;
  }
  
  
  if (!delegate_ref->delegate)
    return;
  
  
  
  
  
  
  
  
  FoundCandidate found_candidate;
  GURL found_intercept_candidate_namespace;
  FoundCandidate found_fallback_candidate;
  GURL found_fallback_candidate_namespace;
  for (StoredGroupMap::const_iterator it = stored_groups_.begin();
       it != stored_groups_.end(); ++it) {
    AppCacheGroup* group = it->second.get();
    AppCache* cache = group->newest_complete_cache();
    if (group->is_obsolete() || !cache ||
        (url.GetOrigin() != group->manifest_url().GetOrigin())) {
      continue;
    }
    AppCacheEntry found_entry;
    AppCacheEntry found_fallback_entry;
    GURL found_intercept_namespace;
    GURL found_fallback_namespace;
    bool ignore_found_network_namespace = false;
    bool found = cache->FindResponseForRequest(
                            url, &found_entry, &found_intercept_namespace,
                            &found_fallback_entry, &found_fallback_namespace,
                            &ignore_found_network_namespace);
    
    
    
    if (!found || ignore_found_network_namespace ||
        (found_entry.has_response_id() && found_entry.IsForeign()) ||
        (found_fallback_entry.has_response_id() &&
         found_fallback_entry.IsForeign())) {
      continue;
    }
    
    bool is_in_use = IsCacheStored(cache) && !cache->HasOneRef();
    if (found_entry.has_response_id() &&
        found_intercept_namespace.is_empty()) {
      found_candidate.namespace_entry_url = GURL();
      found_candidate.entry = found_entry;
      found_candidate.cache_id = cache->cache_id();
      found_candidate.group_id = group->group_id();
      found_candidate.manifest_url = group->manifest_url();
      found_candidate.is_cache_in_use = is_in_use;
      if (is_in_use)
        break;  
    } else if (found_entry.has_response_id() &&
               !found_intercept_namespace.is_empty()) {
      MaybeTakeNewNamespaceEntry(
          INTERCEPT_NAMESPACE,
          found_entry, found_intercept_namespace, is_in_use,
          &found_candidate, &found_intercept_candidate_namespace,
          cache, group);
    } else {
      DCHECK(found_fallback_entry.has_response_id());
      MaybeTakeNewNamespaceEntry(
          FALLBACK_NAMESPACE,
          found_fallback_entry, found_fallback_namespace, is_in_use,
          &found_fallback_candidate, &found_fallback_candidate_namespace,
          cache, group);
    }
  }
  
  if (found_candidate.entry.has_response_id()) {
    delegate_ref->delegate->OnMainResponseFound(
        url, found_candidate.entry, found_candidate.namespace_entry_url,
        AppCacheEntry(),  found_candidate.cache_id, found_candidate.group_id,
        found_candidate.manifest_url);
    return;
  }
  
  if (found_fallback_candidate.entry.has_response_id()) {
    delegate_ref->delegate->OnMainResponseFound(
        url, AppCacheEntry(),
        found_fallback_candidate.namespace_entry_url,
        found_fallback_candidate.entry,
        found_fallback_candidate.cache_id,
        found_fallback_candidate.group_id,
        found_fallback_candidate.manifest_url);
    return;
  }
  
  delegate_ref->delegate->OnMainResponseFound(
      url, AppCacheEntry(), GURL(), AppCacheEntry(), kNoCacheId, 0, GURL());
}
void MockAppCacheStorage::ProcessMakeGroupObsolete(
    scoped_refptr<AppCacheGroup> group,
    scoped_refptr<DelegateReference> delegate_ref,
    int response_code) {
  if (simulate_make_group_obsolete_failure_) {
    if (delegate_ref->delegate)
      delegate_ref->delegate->OnGroupMadeObsolete(
          group.get(), false, response_code);
    return;
  }
  RemoveStoredGroup(group.get());
  if (group->newest_complete_cache())
    RemoveStoredCache(group->newest_complete_cache());
  
  
  AppCacheGroup::Caches copy = group->old_caches();
  RemoveStoredCaches(copy);
  group->set_obsolete(true);
  
  
  
  working_set()->RemoveGroup(group.get());
  if (delegate_ref->delegate)
    delegate_ref->delegate->OnGroupMadeObsolete(
        group.get(), true, response_code);
}
void MockAppCacheStorage::ScheduleTask(const base::Closure& task) {
  pending_tasks_.push_back(task);
  base::MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(&MockAppCacheStorage::RunOnePendingTask,
                 weak_factory_.GetWeakPtr()));
}
void MockAppCacheStorage::RunOnePendingTask() {
  DCHECK(!pending_tasks_.empty());
  base::Closure task = pending_tasks_.front();
  pending_tasks_.pop_front();
  task.Run();
}
void MockAppCacheStorage::AddStoredCache(AppCache* cache) {
  int64 cache_id = cache->cache_id();
  if (stored_caches_.find(cache_id) == stored_caches_.end()) {
    stored_caches_.insert(
        StoredCacheMap::value_type(cache_id, make_scoped_refptr(cache)));
  }
}
void MockAppCacheStorage::RemoveStoredCache(AppCache* cache) {
  
  
  stored_caches_.erase(cache->cache_id());
}
void MockAppCacheStorage::RemoveStoredCaches(
    const AppCacheGroup::Caches& caches) {
  AppCacheGroup::Caches::const_iterator it = caches.begin();
  while (it != caches.end()) {
    RemoveStoredCache(*it);
    ++it;
  }
}
void MockAppCacheStorage::AddStoredGroup(AppCacheGroup* group) {
  const GURL& url = group->manifest_url();
  if (stored_groups_.find(url) == stored_groups_.end()) {
    stored_groups_.insert(
        StoredGroupMap::value_type(url, make_scoped_refptr(group)));
  }
}
void MockAppCacheStorage::RemoveStoredGroup(AppCacheGroup* group) {
  stored_groups_.erase(group->manifest_url());
}
bool MockAppCacheStorage::ShouldGroupLoadAppearAsync(
    const AppCacheGroup* group) {
  
  
  if (!group)
    return true;
  
  
  if (!group->newest_complete_cache())
    return false;
  
  
  
  if (!ShouldCacheLoadAppearAsync(group->newest_complete_cache()))
    return false;
  
  
  const AppCacheGroup::Caches& old_caches = group->old_caches();
  AppCacheGroup::Caches::const_iterator it = old_caches.begin();
  while (it != old_caches.end()) {
    
    if (!ShouldCacheLoadAppearAsync(*it))
      return false;
    ++it;
  }
  return true;
}
bool MockAppCacheStorage::ShouldCacheLoadAppearAsync(const AppCache* cache) {
  if (!cache)
    return true;
  
  
  return IsCacheStored(cache) && cache->HasOneRef();
}
}