146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 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)
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_service_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <functional>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/single_thread_task_runner.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_backend_impl.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_entry.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_executable_handler.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_histograms.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_policy.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_quota_client.h"
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_response.h"
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_service_impl.h"
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_storage_impl.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/quota/special_storage_policy.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace content {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeferredCallback(const net::CompletionCallback& callback, int rv) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(rv);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheInfoCollection::AppCacheInfoCollection() {}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheInfoCollection::~AppCacheInfoCollection() {}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AsyncHelper -------
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AppCacheServiceImpl::AsyncHelper
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public AppCacheStorage::Delegate {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AsyncHelper(AppCacheServiceImpl* service,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              const net::CompletionCallback& callback)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : service_(service), callback_(callback) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->pending_helpers_.insert(this);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AsyncHelper() {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (service_)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->pending_helpers_.erase(this);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Start() = 0;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Cancel();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CallCallback(int rv) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback_.is_null()) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Defer to guarantee async completion.
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE, base::Bind(&DeferredCallback, callback_, rv));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Reset();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AppCacheServiceImpl* service_;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CompletionCallback callback_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::AsyncHelper::Cancel() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback_.is_null()) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Run(net::ERR_ABORTED);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Reset();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_->storage()->CancelDelegateCallbacks(this);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_ = NULL;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CanHandleOfflineHelper -------
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AppCacheServiceImpl::CanHandleOfflineHelper : AsyncHelper {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CanHandleOfflineHelper(
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service, const GURL& url,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& first_party, const net::CompletionCallback& callback)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : AsyncHelper(service, callback),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url_(url),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        first_party_(first_party) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCachePolicy* policy = service_->appcache_policy();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (policy && !policy->CanLoadAppCache(url_, first_party_)) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CallCallback(net::ERR_FAILED);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete this;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->storage()->FindResponseForMainRequest(url_, GURL(), this);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AppCacheStorage::Delegate implementation.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMainResponseFound(
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url, const AppCacheEntry& entry,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& fallback_url, const AppCacheEntry& fallback_entry,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 cache_id, int64 group_id, const GURL& mainfest_url) OVERRIDE;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL first_party_;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CanHandleOfflineHelper);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::CanHandleOfflineHelper::OnMainResponseFound(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url, const AppCacheEntry& entry,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& fallback_url, const AppCacheEntry& fallback_entry,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 cache_id, int64 group_id, const GURL& manifest_url) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool can = (entry.has_response_id() || fallback_entry.has_response_id());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallCallback(can ? net::OK : net::ERR_FAILED);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DeleteHelper -------
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AppCacheServiceImpl::DeleteHelper : public AsyncHelper {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteHelper(
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service, const GURL& manifest_url,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::CompletionCallback& callback)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : AsyncHelper(service, callback), manifest_url_(manifest_url) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->storage()->LoadOrCreateGroup(manifest_url_, this);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AppCacheStorage::Delegate implementation.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGroupLoaded(
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      AppCacheGroup* group, const GURL& manifest_url) OVERRIDE;
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void OnGroupMadeObsolete(AppCacheGroup* group,
149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   bool success,
150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   int response_code) OVERRIDE;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DeleteHelper);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteHelper::OnGroupLoaded(
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      AppCacheGroup* group, const GURL& manifest_url) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (group) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group->set_being_deleted(true);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group->CancelUpdate();
161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    service_->storage()->MakeGroupObsolete(group, this, 0);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallCallback(net::ERR_FAILED);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteHelper::OnGroupMadeObsolete(
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    AppCacheGroup* group,
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    bool success,
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    int response_code) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallCallback(success ? net::OK : net::ERR_FAILED);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DeleteOriginHelper -------
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AppCacheServiceImpl::DeleteOriginHelper : public AsyncHelper {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteOriginHelper(
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service, const GURL& origin,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::CompletionCallback& callback)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : AsyncHelper(service, callback), origin_(origin),
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_caches_to_delete_(0), successes_(0), failures_(0) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We start by listing all caches, continues in OnAllInfo().
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->storage()->GetAllInfo(this);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AppCacheStorage::Delegate implementation.
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAllInfo(AppCacheInfoCollection* collection) OVERRIDE;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGroupLoaded(
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      AppCacheGroup* group, const GURL& manifest_url) OVERRIDE;
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void OnGroupMadeObsolete(AppCacheGroup* group,
198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   bool success,
199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   int response_code) OVERRIDE;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CacheCompleted(bool success);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL origin_;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_caches_to_delete_;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int successes_;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int failures_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DeleteOriginHelper);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteOriginHelper::OnAllInfo(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheInfoCollection* collection) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!collection) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Failed to get a listing.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallCallback(net::ERR_FAILED);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<GURL, AppCacheInfoVector>::iterator found =
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      collection->infos_by_origin.find(origin_);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == collection->infos_by_origin.end() || found->second.empty()) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No caches for this origin.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallCallback(net::OK);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have some caches to delete.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AppCacheInfoVector& caches_to_delete = found->second;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  successes_ = 0;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  failures_ = 0;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_caches_to_delete_ = static_cast<int>(caches_to_delete.size());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AppCacheInfoVector::const_iterator iter = caches_to_delete.begin();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != caches_to_delete.end(); ++iter) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->storage()->LoadOrCreateGroup(iter->manifest_url, this);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteOriginHelper::OnGroupLoaded(
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      AppCacheGroup* group, const GURL& manifest_url) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (group) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group->set_being_deleted(true);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group->CancelUpdate();
245e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    service_->storage()->MakeGroupObsolete(group, this, 0);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CacheCompleted(false);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteOriginHelper::OnGroupMadeObsolete(
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    AppCacheGroup* group,
253e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    bool success,
254e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    int response_code) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheCompleted(success);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteOriginHelper::CacheCompleted(bool success) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++successes_;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++failures_;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((successes_ + failures_) < num_caches_to_delete_)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallCallback(!failures_ ? net::OK : net::ERR_FAILED);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetInfoHelper -------
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AppCacheServiceImpl::GetInfoHelper : AsyncHelper {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetInfoHelper(
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service, AppCacheInfoCollection* collection,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::CompletionCallback& callback)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : AsyncHelper(service, callback), collection_(collection) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->storage()->GetAllInfo(this);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AppCacheStorage::Delegate implementation.
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAllInfo(AppCacheInfoCollection* collection) OVERRIDE;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheInfoCollection> collection_;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GetInfoHelper);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::GetInfoHelper::OnAllInfo(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheInfoCollection* collection) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (collection)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    collection->infos_by_origin.swap(collection_->infos_by_origin);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallCallback(collection ? net::OK : net::ERR_FAILED);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CheckResponseHelper -------
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AppCacheServiceImpl::CheckResponseHelper : AsyncHelper {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckResponseHelper(
30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service, const GURL& manifest_url, int64 cache_id,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 response_id)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : AsyncHelper(service, net::CompletionCallback()),
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_(manifest_url),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cache_id_(cache_id),
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_id_(response_id),
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kIOBufferSize(32 * 1024),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_total_size_(0),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        amount_headers_read_(0),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        amount_data_read_(0) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->storage()->LoadOrCreateGroup(manifest_url_, this);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Cancel() OVERRIDE {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheHistograms::CountCheckResponseResult(
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AppCacheHistograms::CHECK_CANCELED);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_reader_.reset();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AsyncHelper::Cancel();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnGroupLoaded(AppCacheGroup* group,
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const GURL& manifest_url) OVERRIDE;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReadInfoComplete(int result);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReadDataComplete(int result);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inputs describing what to check.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 cache_id_;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 response_id_;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Internals used to perform the checks.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kIOBufferSize;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCache> cache_;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AppCacheResponseReader> response_reader_;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBuffer> data_buffer_;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 expected_total_size_;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amount_headers_read_;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amount_data_read_;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CheckResponseHelper);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::CheckResponseHelper::OnGroupLoaded(
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheGroup* group, const GURL& manifest_url) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(manifest_url_, manifest_url);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!group || !group->newest_complete_cache() || group->is_being_deleted() ||
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group->is_obsolete()) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheHistograms::CountCheckResponseResult(
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AppCacheHistograms::MANIFEST_OUT_OF_DATE);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_ = group->newest_complete_cache();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AppCacheEntry* entry = cache_->GetEntryWithResponseId(response_id_);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cache_->cache_id() == cache_id_) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheHistograms::CountCheckResponseResult(
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AppCacheHistograms::ENTRY_NOT_FOUND);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheHistograms::CountCheckResponseResult(
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AppCacheHistograms::RESPONSE_OUT_OF_DATE);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we can read the response info and data.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_total_size_ = entry->response_size();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_reader_.reset(service_->storage()->CreateResponseReader(
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manifest_url_, group->group_id(), response_id_));
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info_buffer_ = new HttpResponseInfoIOBuffer();
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_reader_->ReadInfo(
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      info_buffer_.get(),
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&CheckResponseHelper::OnReadInfoComplete,
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 base::Unretained(this)));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::CheckResponseHelper::OnReadInfoComplete(int result) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheHistograms::CountCheckResponseResult(
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AppCacheHistograms::READ_HEADERS_ERROR);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  amount_headers_read_ = result;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start reading the data.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_buffer_ = new net::IOBuffer(kIOBufferSize);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_reader_->ReadData(
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      data_buffer_.get(),
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      kIOBufferSize,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CheckResponseHelper::OnReadDataComplete,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::CheckResponseHelper::OnReadDataComplete(int result) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result > 0) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Keep reading until we've read thru everything or failed to read.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    amount_data_read_ += result;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_reader_->ReadData(
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        data_buffer_.get(),
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        kIOBufferSize,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&CheckResponseHelper::OnReadDataComplete,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheHistograms::CheckResponseResultType check_result;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    check_result = AppCacheHistograms::READ_DATA_ERROR;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (info_buffer_->response_data_size != amount_data_read_ ||
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           expected_total_size_ != amount_data_read_ + amount_headers_read_)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    check_result = AppCacheHistograms::UNEXPECTED_DATA_SIZE;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    check_result = AppCacheHistograms::RESPONSE_OK;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheHistograms::CountCheckResponseResult(check_result);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (check_result != AppCacheHistograms::RESPONSE_OK)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// AppCacheStorageReference ------
4371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)AppCacheStorageReference::AppCacheStorageReference(
4391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<AppCacheStorage> storage)
4401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : storage_(storage.Pass()) {}
4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)AppCacheStorageReference::~AppCacheStorageReference() {}
4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
44346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// AppCacheServiceImpl -------
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)AppCacheServiceImpl::AppCacheServiceImpl(
44603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::QuotaManagerProxy* quota_manager_proxy)
44703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : appcache_policy_(NULL),
44803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      quota_client_(NULL),
44903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      handler_factory_(NULL),
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      quota_manager_proxy_(quota_manager_proxy),
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_context_(NULL),
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      force_keep_session_state_(false) {
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (quota_manager_proxy_.get()) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quota_client_ = new AppCacheQuotaClient(this);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quota_manager_proxy_->RegisterClient(quota_client_);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AppCacheServiceImpl::~AppCacheServiceImpl() {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(backends_.empty());
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::for_each(pending_helpers_.begin(),
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                pending_helpers_.end(),
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::mem_fun(&AsyncHelper::Cancel));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&pending_helpers_);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (quota_client_)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quota_client_->NotifyAppCacheDestroyed();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroy storage_ first; ~AppCacheStorageImpl accesses other data members
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (special_storage_policy_).
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage_.reset();
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void AppCacheServiceImpl::Initialize(
47403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const base::FilePath& cache_directory,
47503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
47603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!storage_.get());
4781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  cache_directory_ = cache_directory;
4791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  db_thread_ = db_thread;
4801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  cache_thread_ = cache_thread;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheStorageImpl* storage = new AppCacheStorageImpl(this);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage->Initialize(cache_directory, db_thread, cache_thread);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage_.reset(storage);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::ScheduleReinitialize() {
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (reinit_timer_.IsRunning())
4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Reinitialization only happens when corruption has been noticed.
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We don't want to thrash the disk but we also don't want to
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // leave the appcache disabled for an indefinite period of time. Some
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // users never shutdown the browser.
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::TimeDelta kZeroDelta;
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::TimeDelta kOneHour(base::TimeDelta::FromHours(1));
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::TimeDelta k30Seconds(base::TimeDelta::FromSeconds(30));
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the system managed to stay up for long enough, reset the
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // delay so a new failure won't incur a long wait to get going again.
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::TimeDelta up_time = base::Time::Now() - last_reinit_time_;
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (next_reinit_delay_ != kZeroDelta && up_time > kOneHour)
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    next_reinit_delay_ = kZeroDelta;
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  reinit_timer_.Start(FROM_HERE, next_reinit_delay_,
50646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                      this, &AppCacheServiceImpl::Reinitialize);
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Adjust the delay for next time.
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::TimeDelta increment = std::max(k30Seconds, next_reinit_delay_);
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  next_reinit_delay_ = std::min(next_reinit_delay_ + increment,  kOneHour);
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
51346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::Reinitialize() {
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppCacheHistograms::CountReinitAttempt(!last_reinit_time_.is_null());
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  last_reinit_time_ = base::Time::Now();
5161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Inform observers of about this and give them a chance to
5181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // defer deletion of the old storage object.
5191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<AppCacheStorageReference>
5201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      old_storage_ref(new AppCacheStorageReference(storage_.Pass()));
5211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_,
5221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    OnServiceReinitialized(old_storage_ref.get()));
5231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Initialize(cache_directory_, db_thread_, cache_thread_);
5251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
52746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::CanHandleMainResourceOffline(
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& first_party,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CanHandleOfflineHelper* helper =
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CanHandleOfflineHelper(this, url, first_party, callback);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper->Start();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::GetAllAppCacheInfo(
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheInfoCollection* collection,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(collection);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetInfoHelper* helper = new GetInfoHelper(this, collection, callback);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper->Start();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteAppCacheGroup(
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteHelper* helper = new DeleteHelper(this, manifest_url, callback);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper->Start();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::DeleteAppCachesForOrigin(
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin,  const net::CompletionCallback& callback) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteOriginHelper* helper = new DeleteOriginHelper(this, origin, callback);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper->Start();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::CheckAppCacheResponse(const GURL& manifest_url,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int64 cache_id,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int64 response_id) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckResponseHelper* helper = new CheckResponseHelper(
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, manifest_url, cache_id, response_id);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper->Start();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::set_special_storage_policy(
56603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::SpecialStoragePolicy* policy) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  special_storage_policy_ = policy;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::RegisterBackend(
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheBackendImpl* backend_impl) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(backends_.find(backend_impl->process_id()) == backends_.end());
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backends_.insert(
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BackendMap::value_type(backend_impl->process_id(), backend_impl));
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppCacheServiceImpl::UnregisterBackend(
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheBackendImpl* backend_impl) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backends_.erase(backend_impl->process_id());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace content
583