blob: 01b76c2d2b057ce435a7c4371e083c61f9202940 [file] [log] [blame]
// Copyright 2017 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 "storage/browser/blob/blob_url_store_impl.h"
#include "base/bind.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_loader_factory.h"
#include "storage/browser/blob/blob_url_utils.h"
namespace storage {
// Self deletes when the last binding to it is closed.
class BlobURLTokenImpl : public blink::mojom::BlobURLToken {
public:
BlobURLTokenImpl(base::WeakPtr<BlobStorageContext> context,
const GURL& url,
std::unique_ptr<BlobDataHandle> blob,
blink::mojom::BlobURLTokenRequest request)
: context_(std::move(context)),
url_(url),
blob_(std::move(blob)),
token_(base::UnguessableToken::Create()) {
bindings_.AddBinding(this, std::move(request));
bindings_.set_connection_error_handler(base::BindRepeating(
&BlobURLTokenImpl::OnConnectionError, base::Unretained(this)));
if (context_) {
context_->mutable_registry()->AddTokenMapping(token_, url_,
blob_->uuid());
}
}
~BlobURLTokenImpl() override {
if (context_)
context_->mutable_registry()->RemoveTokenMapping(token_);
}
void GetToken(GetTokenCallback callback) override {
std::move(callback).Run(token_);
}
void Clone(blink::mojom::BlobURLTokenRequest request) override {
bindings_.AddBinding(this, std::move(request));
}
private:
void OnConnectionError() {
if (!bindings_.empty())
return;
delete this;
}
base::WeakPtr<BlobStorageContext> context_;
mojo::BindingSet<blink::mojom::BlobURLToken> bindings_;
const GURL url_;
const std::unique_ptr<BlobDataHandle> blob_;
const base::UnguessableToken token_;
};
BlobURLStoreImpl::BlobURLStoreImpl(base::WeakPtr<BlobStorageContext> context,
BlobRegistryImpl::Delegate* delegate)
: context_(std::move(context)),
delegate_(delegate),
weak_ptr_factory_(this) {}
BlobURLStoreImpl::~BlobURLStoreImpl() {
if (context_) {
for (const auto& url : urls_)
context_->RevokePublicBlobURL(url);
}
}
void BlobURLStoreImpl::Register(blink::mojom::BlobPtr blob,
const GURL& url,
RegisterCallback callback) {
if (!url.SchemeIsBlob() || !delegate_->CanCommitURL(url) ||
BlobUrlUtils::UrlHasFragment(url)) {
mojo::ReportBadMessage("Invalid Blob URL passed to BlobURLStore::Register");
std::move(callback).Run();
return;
}
blink::mojom::Blob* blob_ptr = blob.get();
blob_ptr->GetInternalUUID(base::BindOnce(
&BlobURLStoreImpl::RegisterWithUUID, weak_ptr_factory_.GetWeakPtr(),
std::move(blob), url, std::move(callback)));
}
void BlobURLStoreImpl::Revoke(const GURL& url) {
if (!url.SchemeIsBlob() || !delegate_->CanCommitURL(url) ||
BlobUrlUtils::UrlHasFragment(url)) {
mojo::ReportBadMessage("Invalid Blob URL passed to BlobURLStore::Revoke");
return;
}
if (context_)
context_->RevokePublicBlobURL(url);
urls_.erase(url);
}
void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) {
if (!context_) {
std::move(callback).Run(nullptr);
return;
}
blink::mojom::BlobPtr blob;
std::unique_ptr<BlobDataHandle> blob_handle =
context_->GetBlobDataFromPublicURL(url);
if (blob_handle)
BlobImpl::Create(std::move(blob_handle), MakeRequest(&blob));
std::move(callback).Run(std::move(blob));
}
void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
const GURL& url,
network::mojom::URLLoaderFactoryRequest request) {
BlobURLLoaderFactory::Create(
context_ ? context_->GetBlobDataFromPublicURL(url) : nullptr, url,
std::move(request));
}
void BlobURLStoreImpl::ResolveForNavigation(
const GURL& url,
blink::mojom::BlobURLTokenRequest token) {
if (!context_)
return;
std::unique_ptr<BlobDataHandle> blob_handle =
context_->GetBlobDataFromPublicURL(url);
if (!blob_handle)
return;
new BlobURLTokenImpl(context_, url, std::move(blob_handle), std::move(token));
}
void BlobURLStoreImpl::RegisterWithUUID(blink::mojom::BlobPtr blob,
const GURL& url,
RegisterCallback callback,
const std::string& uuid) {
// |blob| is unused, but is passed here to be kept alive until
// RegisterPublicBlobURL increments the refcount of it via the uuid.
if (context_)
context_->RegisterPublicBlobURL(url, uuid);
urls_.insert(url);
std::move(callback).Run();
}
} // namespace storage