blob: 316370f3eb36711bfe2c013f7080f6e046fe8cc9 [file] [log] [blame]
// Copyright 2015 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 "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include <stddef.h>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/cache_storage/cache_storage_trace_utils.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/referrer_type_converters.h"
#include "mojo/public/cpp/bindings/message.h"
#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
namespace {
using blink::mojom::CacheStorageError;
using blink::mojom::CacheStorageVerboseError;
// TODO(lucmult): Check this before binding.
bool OriginCanAccessCacheStorage(const url::Origin& origin) {
return !origin.opaque() && IsOriginSecure(origin.GetURL());
}
// Verifies that the BatchOperation list conforms to the constraints imposed
// by the web exposed Cache API. Don't permit compromised renderers to use
// unexpected operation combinations.
bool ValidBatchOperations(
const std::vector<blink::mojom::BatchOperationPtr>& batch_operations) {
// At least one operation is required.
if (batch_operations.empty())
return false;
blink::mojom::OperationType type = batch_operations[0]->operation_type;
// We must have a defined operation type. All other enum values allowed
// by the mojo validator are permitted here.
if (type == blink::mojom::OperationType::kUndefined)
return false;
// Delete operations should only be sent one at a time.
if (type == blink::mojom::OperationType::kDelete &&
batch_operations.size() > 1) {
return false;
}
// All operations in the list must be the same.
for (const auto& op : batch_operations) {
if (op->operation_type != type)
return false;
}
return true;
}
} // namespace
// Implements the mojom interface CacheStorageCache. It's owned by
// CacheStorageDispatcherHost and it's destroyed when client drops the mojo ptr
// which in turn removes from StrongBindingSet in CacheStorageDispatcherHost.
class CacheStorageDispatcherHost::CacheImpl
: public blink::mojom::CacheStorageCache {
public:
explicit CacheImpl(CacheStorageCacheHandle cache_handle)
: cache_handle_(std::move(cache_handle)) {}
~CacheImpl() override = default;
// blink::mojom::CacheStorageCache implementation:
void Match(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
int64_t trace_id,
MatchCallback callback) override {
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Match",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"request", CacheStorageTracedValue(request),
"options", CacheStorageTracedValue(match_options));
auto cb = base::BindOnce(
[](base::TimeTicks start_time, bool ignore_search, int64_t trace_id,
blink::mojom::CacheStorageCache::MatchCallback callback,
blink::mojom::CacheStorageError error,
blink::mojom::FetchAPIResponsePtr response) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
UMA_HISTOGRAM_LONG_TIMES("ServiceWorkerCache.Cache.Browser.Match",
elapsed);
if (ignore_search) {
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.Cache.Browser.Match.IgnoreSearch", elapsed);
}
if (error == CacheStorageError::kErrorNotFound) {
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.Cache.Browser.Match.Miss", elapsed);
}
if (error != CacheStorageError::kSuccess) {
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Match::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
CacheStorageTracedValue(error));
std::move(callback).Run(
blink::mojom::MatchResult::NewStatus(error));
return;
}
UMA_HISTOGRAM_LONG_TIMES("ServiceWorkerCache.Cache.Browser.Match.Hit",
elapsed);
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Match::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "response",
CacheStorageTracedValue(response));
std::move(callback).Run(
blink::mojom::MatchResult::NewResponse(std::move(response)));
},
base::TimeTicks::Now(), match_options->ignore_search, trace_id,
std::move(callback));
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
std::move(cb).Run(CacheStorageError::kErrorNotFound, nullptr);
return;
}
cache->Match(std::move(request), std::move(match_options), trace_id,
std::move(cb));
}
void MatchAll(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
int64_t trace_id,
MatchAllCallback callback) override {
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheImpl::MatchAll",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"request", CacheStorageTracedValue(request),
"options", CacheStorageTracedValue(match_options));
auto cb = base::BindOnce(
[](base::TimeTicks start_time, int64_t trace_id,
blink::mojom::CacheStorageCache::MatchAllCallback callback,
blink::mojom::CacheStorageError error,
std::vector<blink::mojom::FetchAPIResponsePtr> responses) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
UMA_HISTOGRAM_LONG_TIMES("ServiceWorkerCache.Cache.Browser.MatchAll",
elapsed);
if (error != CacheStorageError::kSuccess &&
error != CacheStorageError::kErrorNotFound) {
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheImpl::MatchAll::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
CacheStorageTracedValue(error));
std::move(callback).Run(
blink::mojom::MatchAllResult::NewStatus(error));
return;
}
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheImpl::MatchAll::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"response_list", CacheStorageTracedValue(responses));
std::move(callback).Run(
blink::mojom::MatchAllResult::NewResponses(std::move(responses)));
},
base::TimeTicks::Now(), trace_id, std::move(callback));
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
std::move(cb).Run(CacheStorageError::kErrorNotFound,
std::vector<blink::mojom::FetchAPIResponsePtr>());
return;
}
cache->MatchAll(std::move(request), std::move(match_options), trace_id,
std::move(cb));
}
void Keys(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
int64_t trace_id,
KeysCallback callback) override {
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Keys",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"request", CacheStorageTracedValue(request),
"options", CacheStorageTracedValue(match_options));
auto cb = base::BindOnce(
[](base::TimeTicks start_time, int64_t trace_id,
blink::mojom::CacheStorageCache::KeysCallback callback,
blink::mojom::CacheStorageError error,
std::unique_ptr<content::CacheStorageCache::Requests> requests) {
UMA_HISTOGRAM_LONG_TIMES("ServiceWorkerCache.Cache.Browser.Keys",
base::TimeTicks::Now() - start_time);
if (error != CacheStorageError::kSuccess) {
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Keys::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
CacheStorageTracedValue(error));
std::move(callback).Run(
blink::mojom::CacheKeysResult::NewStatus(error));
return;
}
std::vector<blink::mojom::FetchAPIRequestPtr> requests_;
for (const auto& request : *requests) {
requests_.push_back(
BackgroundFetchSettledFetch::CloneRequest(request));
}
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Keys::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"request_list", CacheStorageTracedValue(requests_));
std::move(callback).Run(
blink::mojom::CacheKeysResult::NewKeys(std::move(requests_)));
},
base::TimeTicks::Now(), trace_id, std::move(callback));
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
std::move(cb).Run(CacheStorageError::kErrorNotFound, nullptr);
return;
}
cache->Keys(std::move(request), std::move(match_options), trace_id,
std::move(cb));
}
void Batch(std::vector<blink::mojom::BatchOperationPtr> batch_operations,
int64_t trace_id,
BatchCallback callback) override {
TRACE_EVENT_WITH_FLOW1(
"CacheStorage", "CacheStorageDispatchHost::CacheImpl::Batch",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "operation_list",
CacheStorageTracedValue(batch_operations));
if (!ValidBatchOperations(batch_operations)) {
mojo::ReportBadMessage("CSDH_UNEXPECTED_OPERATION");
return;
}
// Validated batch operations always have at least one entry.
blink::mojom::OperationType operation_type =
batch_operations[0]->operation_type;
int operation_count = batch_operations.size();
auto cb = base::BindOnce(
[](base::TimeTicks start_time,
blink::mojom::OperationType operation_type, int operation_count,
int64_t trace_id,
blink::mojom::CacheStorageCache::BatchCallback callback,
blink::mojom::CacheStorageVerboseErrorPtr error) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheImpl::Batch::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
CacheStorageTracedValue(error->value));
if (operation_type == blink::mojom::OperationType::kDelete) {
DCHECK_EQ(operation_count, 1);
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.Cache.Browser.DeleteOne", elapsed);
} else if (operation_count > 1) {
DCHECK_EQ(operation_type, blink::mojom::OperationType::kPut);
UMA_HISTOGRAM_LONG_TIMES("ServiceWorkerCache.Cache.Browser.PutMany",
elapsed);
} else {
DCHECK_EQ(operation_type, blink::mojom::OperationType::kPut);
UMA_HISTOGRAM_LONG_TIMES("ServiceWorkerCache.Cache.Browser.PutOne",
elapsed);
}
std::move(callback).Run(std::move(error));
},
base::TimeTicks::Now(), operation_type, operation_count, trace_id,
std::move(callback));
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
std::move(cb).Run(CacheStorageVerboseError::New(
CacheStorageError::kErrorNotFound, base::nullopt));
return;
}
cache->BatchOperation(
std::move(batch_operations), trace_id, std::move(cb),
base::BindOnce(
[](mojo::ReportBadMessageCallback bad_message_callback) {
std::move(bad_message_callback).Run("CSDH_UNEXPECTED_OPERATION");
},
mojo::GetBadMessageCallback()));
}
void SetSideData(const GURL& url,
base::Time response_time,
const std::vector<uint8_t>& side_data,
int64_t trace_id,
SetSideDataCallback callback) override {
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatcherHost::CacheImpl::SetSideData",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"url", url.spec());
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
std::move(callback).Run(blink::mojom::CacheStorageError::kErrorNotFound);
return;
}
scoped_refptr<net::IOBuffer> buffer =
base::MakeRefCounted<net::IOBuffer>(side_data.size());
if (!side_data.empty())
memcpy(buffer->data(), &side_data.front(), side_data.size());
cache->WriteSideData(std::move(callback), url, response_time, trace_id,
std::move(buffer), side_data.size());
}
CacheStorageCacheHandle cache_handle_;
DISALLOW_COPY_AND_ASSIGN(CacheImpl);
};
// Implements the mojom interface CacheStorage. It's owned by the
// CacheStorageDispatcherHost. The CacheStorageImpl is destroyed when the
// client drops its mojo ptr which in turn removes from StrongBindingSet in
// CacheStorageDispatcherHost.
class CacheStorageDispatcherHost::CacheStorageImpl final
: public blink::mojom::CacheStorage {
public:
CacheStorageImpl(CacheStorageDispatcherHost* owner, const url::Origin& origin)
: owner_(owner), origin_(origin), weak_factory_(this) {
// The CacheStorageHandle is empty to start and lazy initialized on first
// use via GetOrCreateCacheStorage(). In the future we could eagerly create
// the backend when the mojo connection is created.
}
~CacheStorageImpl() override = default;
// Mojo CacheStorage Interface implementation:
void Keys(int64_t trace_id,
blink::mojom::CacheStorage::KeysCallback callback) override {
TRACE_EVENT_WITH_FLOW0(
"CacheStorage", "CacheStorageDispatchHost::CacheStorageImpl::Keys",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
auto cb = base::BindOnce(
[](base::TimeTicks start_time, int64_t trace_id,
blink::mojom::CacheStorage::KeysCallback callback,
std::vector<std::string> cache_names) {
std::vector<base::string16> string16s;
for (const auto& name : cache_names) {
string16s.push_back(base::UTF8ToUTF16(name));
}
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.CacheStorage.Browser.Keys",
base::TimeTicks::Now() - start_time);
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Keys::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "key_list",
CacheStorageTracedValue(string16s));
std::move(callback).Run(string16s);
},
base::TimeTicks::Now(), trace_id, std::move(callback));
content::CacheStorage* cache_storage = GetOrCreateCacheStorage();
if (!cache_storage) {
std::move(cb).Run(std::vector<std::string>());
return;
}
cache_storage->EnumerateCaches(trace_id, std::move(cb));
}
void Delete(const base::string16& cache_name,
int64_t trace_id,
blink::mojom::CacheStorage::DeleteCallback callback) override {
std::string utf8_cache_name = base::UTF16ToUTF8(cache_name);
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Delete",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"cache_name", utf8_cache_name);
auto cb = base::BindOnce(
[](base::TimeTicks start_time, int64_t trace_id,
blink::mojom::CacheStorage::DeleteCallback callback,
CacheStorageError error) {
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.CacheStorage.Browser.Delete",
base::TimeTicks::Now() - start_time);
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Delete::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
CacheStorageTracedValue(error));
std::move(callback).Run(error);
},
base::TimeTicks::Now(), trace_id, std::move(callback));
content::CacheStorage* cache_storage = GetOrCreateCacheStorage();
if (!cache_storage) {
std::move(cb).Run(MakeErrorStorage(ErrorStorageType::kStorageHandleNull));
return;
}
cache_storage->DoomCache(utf8_cache_name, trace_id, std::move(cb));
}
void Has(const base::string16& cache_name,
int64_t trace_id,
blink::mojom::CacheStorage::HasCallback callback) override {
std::string utf8_cache_name = base::UTF16ToUTF8(cache_name);
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Has",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"cache_name", utf8_cache_name);
auto cb = base::BindOnce(
[](base::TimeTicks start_time, int64_t trace_id,
blink::mojom::CacheStorage::HasCallback callback, bool has_cache,
CacheStorageError error) {
if (!has_cache)
error = CacheStorageError::kErrorNotFound;
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Has::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
CacheStorageTracedValue(error));
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.CacheStorage.Browser.Has",
base::TimeTicks::Now() - start_time);
std::move(callback).Run(error);
},
base::TimeTicks::Now(), trace_id, std::move(callback));
content::CacheStorage* cache_storage = GetOrCreateCacheStorage();
if (!cache_storage) {
std::move(cb).Run(/* has_cache = */ false,
MakeErrorStorage(ErrorStorageType::kStorageHandleNull));
return;
}
cache_storage->HasCache(utf8_cache_name, trace_id, std::move(cb));
}
void Match(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::MultiCacheQueryOptionsPtr match_options,
int64_t trace_id,
blink::mojom::CacheStorage::MatchCallback callback) override {
TRACE_EVENT_WITH_FLOW2("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Match",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"request", CacheStorageTracedValue(request),
"options", CacheStorageTracedValue(match_options));
auto cb = BindOnce(
[](base::TimeTicks start_time, bool match_all_caches, int64_t trace_id,
blink::mojom::CacheStorage::MatchCallback callback,
CacheStorageError error,
blink::mojom::FetchAPIResponsePtr response) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
if (match_all_caches) {
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.CacheStorage.Browser.MatchAllCaches",
elapsed);
} else {
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.CacheStorage.Browser.MatchOneCache",
elapsed);
}
if (error != CacheStorageError::kSuccess) {
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Match::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
CacheStorageTracedValue(error));
std::move(callback).Run(
blink::mojom::MatchResult::NewStatus(error));
return;
}
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Match::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "response",
CacheStorageTracedValue(response));
std::move(callback).Run(
blink::mojom::MatchResult::NewResponse(std::move(response)));
},
base::TimeTicks::Now(), !match_options->cache_name, trace_id,
std::move(callback));
content::CacheStorage* cache_storage = GetOrCreateCacheStorage();
if (!cache_storage) {
std::move(cb).Run(CacheStorageError::kErrorNotFound, nullptr);
return;
}
if (!match_options->cache_name) {
cache_storage->MatchAllCaches(std::move(request),
std::move(match_options->query_options),
trace_id, std::move(cb));
return;
}
std::string cache_name = base::UTF16ToUTF8(*match_options->cache_name);
cache_storage->MatchCache(std::move(cache_name), std::move(request),
std::move(match_options->query_options), trace_id,
std::move(cb));
}
void Open(const base::string16& cache_name,
int64_t trace_id,
blink::mojom::CacheStorage::OpenCallback callback) override {
std::string utf8_cache_name = base::UTF16ToUTF8(cache_name);
TRACE_EVENT_WITH_FLOW1("CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Open",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"cache_name", utf8_cache_name);
content::CacheStorage* cache_storage = GetOrCreateCacheStorage();
auto cb =
base::BindOnce(
[](base::WeakPtr<CacheStorageImpl> self, base::TimeTicks start_time,
int64_t trace_id,
blink::mojom::CacheStorage::OpenCallback callback,
CacheStorageCacheHandle cache_handle, CacheStorageError error) {
if (!self)
return;
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.CacheStorage.Browser.Open",
base::TimeTicks::Now() - start_time);
TRACE_EVENT_WITH_FLOW1(
"CacheStorage",
"CacheStorageDispatchHost::CacheStorageImpl::Open::Callback",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"status", CacheStorageTracedValue(error));
if (error != CacheStorageError::kSuccess) {
std::move(callback).Run(
blink::mojom::OpenResult::NewStatus(error));
return;
}
blink::mojom::CacheStorageCacheAssociatedPtrInfo ptr_info;
auto request = mojo::MakeRequest(&ptr_info);
auto cache_impl =
std::make_unique<CacheImpl>(std::move(cache_handle));
self->owner_->AddCacheBinding(std::move(cache_impl),
std::move(request));
std::move(callback).Run(
blink::mojom::OpenResult::NewCache(std::move(ptr_info)));
},
weak_factory_.GetWeakPtr(), base::TimeTicks::Now(), trace_id,
std::move(callback));
if (!cache_storage) {
std::move(cb).Run(CacheStorageCacheHandle(),
MakeErrorStorage(ErrorStorageType::kStorageHandleNull));
return;
}
cache_storage->OpenCache(utf8_cache_name, trace_id, std::move(cb));
}
private:
// Helper method that returns the current CacheStorageHandle value. If the
// handle is closed, then it attempts to open a new CacheStorageHandle
// automatically. This automatic open is necessary to re-attach to the
// backend after the browser storage has been wiped.
content::CacheStorage* GetOrCreateCacheStorage() {
DCHECK(owner_);
if (!cache_storage_handle_.value())
cache_storage_handle_ = owner_->OpenCacheStorage(origin_);
return cache_storage_handle_.value();
}
// Owns this.
CacheStorageDispatcherHost* const owner_;
const url::Origin origin_;
CacheStorageHandle cache_storage_handle_;
base::WeakPtrFactory<CacheStorageImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CacheStorageImpl);
};
CacheStorageDispatcherHost::CacheStorageDispatcherHost() = default;
CacheStorageDispatcherHost::~CacheStorageDispatcherHost() = default;
void CacheStorageDispatcherHost::Init(CacheStorageContextImpl* context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageDispatcherHost::CreateCacheListener,
base::RetainedRef(this), base::RetainedRef(context)));
}
void CacheStorageDispatcherHost::CreateCacheListener(
CacheStorageContextImpl* context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
context_ = context;
}
void CacheStorageDispatcherHost::AddBinding(
blink::mojom::CacheStorageRequest request,
const url::Origin& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto impl = std::make_unique<CacheStorageImpl>(this, origin);
bindings_.AddBinding(std::move(impl), std::move(request));
}
void CacheStorageDispatcherHost::AddCacheBinding(
std::unique_ptr<CacheImpl> cache_impl,
blink::mojom::CacheStorageCacheAssociatedRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
cache_bindings_.AddBinding(std::move(cache_impl), std::move(request));
}
CacheStorageHandle CacheStorageDispatcherHost::OpenCacheStorage(
const url::Origin& origin) {
if (!context_ || !context_->cache_manager() ||
!OriginCanAccessCacheStorage(origin))
return CacheStorageHandle();
return context_->cache_manager()->OpenCacheStorage(
origin, CacheStorageOwner::kCacheAPI);
}
} // namespace content