blob: b46ee60849c9b758e022d7e576de61b080fd59f5 [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/receiver_set.h"
#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_url_loader_factory.h"
#include "storage/browser/blob/blob_url_registry.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<BlobUrlRegistry> registry,
const GURL& url,
mojo::PendingRemote<blink::mojom::Blob> blob,
mojo::PendingReceiver<blink::mojom::BlobURLToken> receiver)
: registry_(std::move(registry)),
url_(url),
token_(base::UnguessableToken::Create()) {
receivers_.Add(this, std::move(receiver));
receivers_.set_disconnect_handler(base::BindRepeating(
&BlobURLTokenImpl::OnConnectionError, base::Unretained(this)));
if (registry_) {
registry_->AddTokenMapping(token_, url_, std::move(blob));
}
}
~BlobURLTokenImpl() override {
if (registry_)
registry_->RemoveTokenMapping(token_);
}
void GetToken(GetTokenCallback callback) override {
std::move(callback).Run(token_);
}
void Clone(
mojo::PendingReceiver<blink::mojom::BlobURLToken> receiver) override {
receivers_.Add(this, std::move(receiver));
}
private:
void OnConnectionError() {
if (!receivers_.empty())
return;
delete this;
}
base::WeakPtr<BlobUrlRegistry> registry_;
mojo::ReceiverSet<blink::mojom::BlobURLToken> receivers_;
const GURL url_;
const base::UnguessableToken token_;
};
BlobURLStoreImpl::BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
BlobRegistryImpl::Delegate* delegate)
: registry_(std::move(registry)), delegate_(delegate) {}
BlobURLStoreImpl::~BlobURLStoreImpl() {
if (registry_) {
for (const auto& url : urls_)
registry_->RemoveUrlMapping(url);
}
}
void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob,
const GURL& url,
RegisterCallback callback) {
if (!url.SchemeIsBlob()) {
mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Register");
std::move(callback).Run();
return;
}
if (!delegate_->CanCommitURL(url)) {
mojo::ReportBadMessage(
"Non committable URL passed to BlobURLStore::Register");
std::move(callback).Run();
return;
}
if (BlobUrlUtils::UrlHasFragment(url)) {
mojo::ReportBadMessage(
"URL with fragment passed to BlobURLStore::Register");
std::move(callback).Run();
return;
}
if (registry_)
registry_->AddUrlMapping(url, std::move(blob));
urls_.insert(url);
std::move(callback).Run();
}
void BlobURLStoreImpl::Revoke(const GURL& url) {
if (!url.SchemeIsBlob()) {
mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Revoke");
return;
}
if (!delegate_->CanCommitURL(url)) {
mojo::ReportBadMessage(
"Non committable URL passed to BlobURLStore::Revoke");
return;
}
if (BlobUrlUtils::UrlHasFragment(url)) {
mojo::ReportBadMessage("URL with fragment passed to BlobURLStore::Revoke");
return;
}
if (registry_)
registry_->RemoveUrlMapping(url);
urls_.erase(url);
}
void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) {
if (!registry_) {
std::move(callback).Run(mojo::NullRemote());
return;
}
mojo::PendingRemote<blink::mojom::Blob> blob = registry_->GetBlobFromUrl(url);
std::move(callback).Run(std::move(blob));
}
void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
const GURL& url,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
BlobURLLoaderFactory::Create(
registry_ ? registry_->GetBlobFromUrl(url) : mojo::NullRemote(), url,
std::move(receiver));
}
void BlobURLStoreImpl::ResolveForNavigation(
const GURL& url,
mojo::PendingReceiver<blink::mojom::BlobURLToken> token) {
if (!registry_)
return;
mojo::PendingRemote<blink::mojom::Blob> blob = registry_->GetBlobFromUrl(url);
if (!blob)
return;
new BlobURLTokenImpl(registry_, url, std::move(blob), std::move(token));
}
} // namespace storage