| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/network/http_cache_data_counter.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/location.h" |
| #include "base/threading/sequenced_task_runner_handle.h" |
| #include "net/disk_cache/disk_cache.h" |
| #include "net/http/http_cache.h" |
| #include "net/url_request/url_request_context.h" |
| |
| namespace network { |
| |
| std::unique_ptr<HttpCacheDataCounter> HttpCacheDataCounter::CreateAndStart( |
| net::URLRequestContext* url_request_context, |
| base::Time start_time, |
| base::Time end_time, |
| HttpCacheDataCounterCallback callback) { |
| HttpCacheDataCounter* instance = |
| new HttpCacheDataCounter(start_time, end_time, std::move(callback)); |
| net::HttpCache* http_cache = |
| url_request_context->http_transaction_factory()->GetCache(); |
| if (!http_cache) { |
| // No cache, no space used. Posts a task, so it will run after the return. |
| instance->PostResult(false, 0); |
| } else { |
| // Tricky here: if |this| gets deleted before |http_cache| gets deleted, |
| // GetBackend may still write things out (even though the callback will |
| // abort due to weak pointer), so the destination for the pointer can't be |
| // owned by |this|. |
| // |
| // While it can be transferred to the callback to GetBackend, that callback |
| // also needs to be kept alive for the duration of this method in order to |
| // get at the backend pointer in the synchronous result case. |
| auto backend = std::make_unique<disk_cache::Backend*>(); |
| disk_cache::Backend** backend_ptr = backend.get(); |
| |
| auto get_backend_callback = |
| base::BindRepeating(&HttpCacheDataCounter::GotBackend, |
| instance->GetWeakPtr(), base::Passed(&backend)); |
| int rv = http_cache->GetBackend(backend_ptr, get_backend_callback); |
| if (rv != net::ERR_IO_PENDING) { |
| instance->GotBackend(std::make_unique<disk_cache::Backend*>(*backend_ptr), |
| rv); |
| } |
| } |
| |
| return base::WrapUnique(instance); |
| } |
| |
| HttpCacheDataCounter::HttpCacheDataCounter( |
| base::Time start_time, |
| base::Time end_time, |
| HttpCacheDataCounterCallback callback) |
| : start_time_(start_time), |
| end_time_(end_time), |
| callback_(std::move(callback)), |
| weak_factory_(this) {} |
| |
| HttpCacheDataCounter::~HttpCacheDataCounter() {} |
| |
| void HttpCacheDataCounter::GotBackend( |
| std::unique_ptr<disk_cache::Backend*> backend, |
| int error_code) { |
| DCHECK_LE(error_code, 0); |
| bool is_upper_limit = false; |
| if (error_code != net::OK) { |
| PostResult(is_upper_limit, error_code); |
| return; |
| } |
| |
| if (!*backend) { |
| PostResult(is_upper_limit, 0); |
| return; |
| } |
| |
| int64_t rv; |
| disk_cache::Backend* cache = *backend; |
| |
| // Handle this here since some backends would DCHECK on this. |
| if (start_time_ > end_time_) { |
| PostResult(is_upper_limit, 0); |
| return; |
| } |
| |
| if (start_time_.is_null() && end_time_.is_max()) { |
| rv = cache->CalculateSizeOfAllEntries(base::BindOnce( |
| &HttpCacheDataCounter::PostResult, GetWeakPtr(), is_upper_limit)); |
| } else { |
| rv = cache->CalculateSizeOfEntriesBetween( |
| start_time_, end_time_, |
| base::BindOnce(&HttpCacheDataCounter::PostResult, GetWeakPtr(), |
| is_upper_limit)); |
| if (rv == net::ERR_NOT_IMPLEMENTED) { |
| is_upper_limit = true; |
| rv = cache->CalculateSizeOfAllEntries(base::BindOnce( |
| &HttpCacheDataCounter::PostResult, GetWeakPtr(), is_upper_limit)); |
| } |
| } |
| if (rv != net::ERR_IO_PENDING) |
| PostResult(is_upper_limit, rv); |
| } |
| |
| void HttpCacheDataCounter::PostResult(bool is_upper_limit, |
| int64_t result_or_error) { |
| base::SequencedTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback_), this, is_upper_limit, |
| result_or_error)); |
| } |
| |
| } // namespace network |