10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/appcache/mock_appcache_storage.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_entry.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_group.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_response.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_service_impl.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a quick and easy 'mock' implementation of the storage interface
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that doesn't put anything to disk.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We simply add an extra reference to objects when they're put in storage,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and remove the extra reference when they are removed from storage.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Responses are never really removed from the in-memory disk cache.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delegate callbacks are made asyncly to appropiately mimic what will
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// happen with a real disk-backed storage impl that involves IO on a
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// background thread.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace content {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)MockAppCacheStorage::MockAppCacheStorage(AppCacheServiceImpl* service)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : AppCacheStorage(service),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      simulate_make_group_obsolete_failure_(false),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      simulate_store_group_and_newest_cache_failure_(false),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      simulate_find_main_resource_(false),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      simulate_find_sub_resource_(false),
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      simulated_found_cache_id_(kAppCacheNoCacheId),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      simulated_found_group_id_(0),
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      simulated_found_network_namespace_(false),
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_factory_(this) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_cache_id_ = 0;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_group_id_ = 0;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_response_id_ = 0;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MockAppCacheStorage::~MockAppCacheStorage() {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::GetAllInfo(Delegate* delegate) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleTask(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MockAppCacheStorage::ProcessGetAllInfo,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_factory_.GetWeakPtr(),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::LoadCache(int64 id, Delegate* delegate) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCache* cache = working_set_.GetCache(id);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldCacheLoadAppearAsync(cache)) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleTask(
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&MockAppCacheStorage::ProcessLoadCache,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr(), id,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessLoadCache(id, GetOrCreateDelegateReference(delegate));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::LoadOrCreateGroup(
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, Delegate* delegate) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheGroup* group = working_set_.GetGroup(manifest_url);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldGroupLoadAppearAsync(group)) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleTask(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&MockAppCacheStorage::ProcessLoadOrCreateGroup,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr(), manifest_url,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessLoadOrCreateGroup(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manifest_url, GetOrCreateDelegateReference(delegate));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::StoreGroupAndNewestCache(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(group && delegate && newest_cache);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always make this operation look async.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleTask(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MockAppCacheStorage::ProcessStoreGroupAndNewestCache,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_factory_.GetWeakPtr(), make_scoped_refptr(group),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 make_scoped_refptr(newest_cache),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::FindResponseForMainRequest(
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url, const GURL& preferred_manifest_url, Delegate* delegate) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: MockAppCacheStorage does not respect the preferred_manifest_url.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always make this operation look async.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleTask(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MockAppCacheStorage::ProcessFindResponseForMainRequest,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_factory_.GetWeakPtr(), url,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::FindResponseForSubRequest(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCache* cache, const GURL& url,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* found_network_namespace) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(cache && cache->is_complete());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This layer of indirection is here to facilitate testing.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (simulate_find_sub_resource_) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *found_entry = simulated_found_entry_;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *found_fallback_entry = simulated_found_fallback_entry_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *found_network_namespace = simulated_found_network_namespace_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    simulate_find_sub_resource_ = false;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL fallback_namespace_not_used;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL intercept_namespace_not_used;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache->FindResponseForRequest(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url, found_entry, &intercept_namespace_not_used,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_fallback_entry,  &fallback_namespace_not_used,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_network_namespace);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::MarkEntryAsForeign(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& entry_url, int64 cache_id) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCache* cache = working_set_.GetCache(cache_id);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheEntry* entry = cache->GetEntry(entry_url);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(entry);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry->add_types(AppCacheEntry::FOREIGN);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid MockAppCacheStorage::MakeGroupObsolete(AppCacheGroup* group,
143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                            Delegate* delegate,
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                            int response_code) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(group && delegate);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always make this method look async.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleTask(
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MockAppCacheStorage::ProcessMakeGroupObsolete,
150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                 weak_factory_.GetWeakPtr(),
151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                 make_scoped_refptr(group),
152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                 make_scoped_refptr(GetOrCreateDelegateReference(delegate)),
153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                 response_code));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, int64 group_id, int64 response_id) {
158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (simulated_reader_)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return simulated_reader_.release();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new AppCacheResponseReader(response_id, group_id, disk_cache());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheResponseWriter* MockAppCacheStorage::CreateResponseWriter(
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, int64 group_id) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new AppCacheResponseWriter(NewResponseId(),  group_id, disk_cache());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::DoomResponses(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, const std::vector<int64>& response_ids) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteResponses(manifest_url, response_ids);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::DeleteResponses(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, const std::vector<int64>& response_ids) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't bother with actually removing responses from the disk-cache,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just keep track of which ids have been doomed or deleted
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int64>::const_iterator it = response_ids.begin();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (it != response_ids.end()) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    doomed_response_ids_.insert(*it);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::ProcessGetAllInfo(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<DelegateReference> delegate_ref) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ref->delegate)
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    delegate_ref->delegate->OnAllInfo(simulated_appcache_info_.get());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::ProcessLoadCache(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 id, scoped_refptr<DelegateReference> delegate_ref) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCache* cache = working_set_.GetCache(id);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ref->delegate)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ref->delegate->OnCacheLoaded(cache, id);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::ProcessLoadOrCreateGroup(
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, scoped_refptr<DelegateReference> delegate_ref) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheGroup> group(working_set_.GetGroup(manifest_url));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Newly created groups are not put in the stored_groups collection
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until StoreGroupAndNewestCache is called.
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!group.get())
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    group = new AppCacheGroup(service_->storage(), manifest_url, NewGroupId());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ref->delegate)
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    delegate_ref->delegate->OnGroupLoaded(group.get(), manifest_url);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::ProcessStoreGroupAndNewestCache(
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<AppCacheGroup> group,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<AppCache> newest_cache,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<DelegateReference> delegate_ref) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Delegate* delegate = delegate_ref->delegate;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (simulate_store_group_and_newest_cache_failure_) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate)
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      delegate->OnGroupAndNewestCacheStored(
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          group.get(), newest_cache.get(), false, false);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddStoredGroup(group.get());
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (newest_cache.get() != group->newest_complete_cache()) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    newest_cache->set_complete(true);
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    group->AddCache(newest_cache.get());
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    AddStoredCache(newest_cache.get());
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Copy the collection prior to removal, on final release
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of a cache the group's collection will change.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheGroup::Caches copy = group->old_caches();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveStoredCaches(copy);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate)
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    delegate->OnGroupAndNewestCacheStored(
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        group.get(), newest_cache.get(), true, false);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FoundCandidate {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL namespace_entry_url;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheEntry entry;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 cache_id;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 group_id;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_cache_in_use;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FoundCandidate()
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : cache_id(kAppCacheNoCacheId), group_id(0), is_cache_in_use(false) {}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MaybeTakeNewNamespaceEntry(
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    AppCacheNamespaceType namespace_type,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheEntry &entry,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& namespace_url,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cache_is_in_use,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FoundCandidate* best_candidate,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL* best_candidate_namespace,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCache* cache,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheGroup* group) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry.has_response_id());
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool take_new_entry = true;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does the new candidate entry trump our current best candidate?
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (best_candidate->entry.has_response_id()) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Longer namespace prefix matches win.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t candidate_length =
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        namespace_url.spec().length();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t best_length =
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        best_candidate_namespace->spec().length();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (candidate_length > best_length) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      take_new_entry = true;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (candidate_length == best_length &&
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               cache_is_in_use && !best_candidate->is_cache_in_use) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      take_new_entry = true;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      take_new_entry = false;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (take_new_entry) {
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (namespace_type == APPCACHE_FALLBACK_NAMESPACE) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_candidate->namespace_entry_url =
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cache->GetFallbackEntryUrl(namespace_url);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_candidate->namespace_entry_url =
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cache->GetInterceptEntryUrl(namespace_url);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    best_candidate->entry = entry;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    best_candidate->cache_id = cache->cache_id();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    best_candidate->group_id = group->group_id();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    best_candidate->manifest_url = group->manifest_url();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    best_candidate->is_cache_in_use = cache_is_in_use;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *best_candidate_namespace = namespace_url;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::ProcessFindResponseForMainRequest(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url, scoped_refptr<DelegateReference> delegate_ref) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (simulate_find_main_resource_) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    simulate_find_main_resource_ = false;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_ref->delegate) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_ref->delegate->OnMainResponseFound(
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          url, simulated_found_entry_,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          simulated_found_fallback_url_, simulated_found_fallback_entry_,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          simulated_found_cache_id_, simulated_found_group_id_,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          simulated_found_manifest_url_);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This call has no persistent side effects, if the delegate has gone
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // away, we can just bail out early.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delegate_ref->delegate)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(michaeln): The heuristics around choosing amoungst
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // multiple candidates is under specified, and just plain
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not fully understood. Refine these over time. In particular,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // * prefer candidates from newer caches
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // * take into account the cache associated with the document
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   that initiated the navigation
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // * take into account the cache associated with the document
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   currently residing in the frame being navigated
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FoundCandidate found_candidate;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL found_intercept_candidate_namespace;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FoundCandidate found_fallback_candidate;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL found_fallback_candidate_namespace;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (StoredGroupMap::const_iterator it = stored_groups_.begin();
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != stored_groups_.end(); ++it) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheGroup* group = it->second.get();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCache* cache = group->newest_complete_cache();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (group->is_obsolete() || !cache ||
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (url.GetOrigin() != group->manifest_url().GetOrigin())) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheEntry found_entry;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheEntry found_fallback_entry;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL found_intercept_namespace;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL found_fallback_namespace;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ignore_found_network_namespace = false;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found = cache->FindResponseForRequest(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            url, &found_entry, &found_intercept_namespace,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &found_fallback_entry, &found_fallback_namespace,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &ignore_found_network_namespace);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 6.11.1 Navigating across documents, Step 10.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Network namespacing doesn't apply to main resource loads,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and foreign entries are excluded.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found || ignore_found_network_namespace ||
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (found_entry.has_response_id() && found_entry.IsForeign()) ||
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (found_fallback_entry.has_response_id() &&
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         found_fallback_entry.IsForeign())) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have a bias for hits from caches that are in use.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_in_use = IsCacheStored(cache) && !cache->HasOneRef();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found_entry.has_response_id() &&
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_intercept_namespace.is_empty()) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_candidate.namespace_entry_url = GURL();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_candidate.entry = found_entry;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_candidate.cache_id = cache->cache_id();
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_candidate.group_id = group->group_id();
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_candidate.manifest_url = group->manifest_url();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_candidate.is_cache_in_use = is_in_use;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (is_in_use)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;  // We break out of the loop with this direct hit.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (found_entry.has_response_id() &&
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               !found_intercept_namespace.is_empty()) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MaybeTakeNewNamespaceEntry(
379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          APPCACHE_INTERCEPT_NAMESPACE,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          found_entry, found_intercept_namespace, is_in_use,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &found_candidate, &found_intercept_candidate_namespace,
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cache, group);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(found_fallback_entry.has_response_id());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MaybeTakeNewNamespaceEntry(
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          APPCACHE_FALLBACK_NAMESPACE,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          found_fallback_entry, found_fallback_namespace, is_in_use,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &found_fallback_candidate, &found_fallback_candidate_namespace,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cache, group);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Found a direct hit or an intercept namespace hit.
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_candidate.entry.has_response_id()) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ref->delegate->OnMainResponseFound(
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url, found_candidate.entry, found_candidate.namespace_entry_url,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AppCacheEntry(),  found_candidate.cache_id, found_candidate.group_id,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_candidate.manifest_url);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Found a fallback namespace.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_fallback_candidate.entry.has_response_id()) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ref->delegate->OnMainResponseFound(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url, AppCacheEntry(),
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_fallback_candidate.namespace_entry_url,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_fallback_candidate.entry,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_fallback_candidate.cache_id,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_fallback_candidate.group_id,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_fallback_candidate.manifest_url);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Didn't find anything.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ref->delegate->OnMainResponseFound(
416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      url, AppCacheEntry(), GURL(), AppCacheEntry(), kAppCacheNoCacheId, 0,
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GURL());
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::ProcessMakeGroupObsolete(
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<AppCacheGroup> group,
422e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    scoped_refptr<DelegateReference> delegate_ref,
423e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    int response_code) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (simulate_make_group_obsolete_failure_) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_ref->delegate)
426e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      delegate_ref->delegate->OnGroupMadeObsolete(
427e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          group.get(), false, response_code);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveStoredGroup(group.get());
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (group->newest_complete_cache())
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveStoredCache(group->newest_complete_cache());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy the collection prior to removal, on final release
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of a cache the group's collection will change.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheGroup::Caches copy = group->old_caches();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveStoredCaches(copy);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  group->set_obsolete(true);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Also remove from the working set, caches for an 'obsolete' group
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // may linger in use, but the group itself cannot be looked up by
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'manifest_url' in the working set any longer.
445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  working_set()->RemoveGroup(group.get());
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ref->delegate)
448e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    delegate_ref->delegate->OnGroupMadeObsolete(
449e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        group.get(), true, response_code);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::ScheduleTask(const base::Closure& task) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tasks_.push_back(task);
454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MockAppCacheStorage::RunOnePendingTask,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_factory_.GetWeakPtr()));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::RunOnePendingTask() {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pending_tasks_.empty());
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure task = pending_tasks_.front();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tasks_.pop_front();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.Run();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::AddStoredCache(AppCache* cache) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 cache_id = cache->cache_id();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stored_caches_.find(cache_id) == stored_caches_.end()) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stored_caches_.insert(
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        StoredCacheMap::value_type(cache_id, make_scoped_refptr(cache)));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::RemoveStoredCache(AppCache* cache) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not remove from the working set, active caches are still usable
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and may be looked up by id until they fall out of use.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stored_caches_.erase(cache->cache_id());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::RemoveStoredCaches(
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheGroup::Caches& caches) {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheGroup::Caches::const_iterator it = caches.begin();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (it != caches.end()) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveStoredCache(*it);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::AddStoredGroup(AppCacheGroup* group) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& url = group->manifest_url();
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stored_groups_.find(url) == stored_groups_.end()) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stored_groups_.insert(
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        StoredGroupMap::value_type(url, make_scoped_refptr(group)));
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockAppCacheStorage::RemoveStoredGroup(AppCacheGroup* group) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stored_groups_.erase(group->manifest_url());
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MockAppCacheStorage::ShouldGroupLoadAppearAsync(
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheGroup* group) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll have to query the database to see if a group for the
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manifest_url exists on disk. So return true for async.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!group)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Groups without a newest cache can't have been put to disk yet, so
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we can synchronously return a reference we have in the working set.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!group->newest_complete_cache())
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The LoadGroup interface implies also loading the newest cache, so
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if loading the newest cache should appear async, so too must the
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // loading of this group.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldCacheLoadAppearAsync(group->newest_complete_cache()))
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If any of the old caches are "in use", then the group must also
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be memory resident and not require async loading.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AppCacheGroup::Caches& old_caches = group->old_caches();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheGroup::Caches::const_iterator it = old_caches.begin();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (it != old_caches.end()) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "in use" caches don't require async loading
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ShouldCacheLoadAppearAsync(*it))
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MockAppCacheStorage::ShouldCacheLoadAppearAsync(const AppCache* cache) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cache)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the 'stored' ref is the only ref, real storage will have to load from
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the database.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsCacheStored(cache) && cache->HasOneRef();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}  // namespace content
545