blob: f79e7e0baabac1300d8eee81b8502304cb6e7a25 [file] [log] [blame]
// Copyright 2020 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_registry.h"
#include "base/check.h"
#include "storage/browser/blob/blob_url_utils.h"
#include "url/gurl.h"
namespace storage {
BlobUrlRegistry::BlobUrlRegistry(base::WeakPtr<BlobUrlRegistry> fallback)
: fallback_(std::move(fallback)) {}
BlobUrlRegistry::~BlobUrlRegistry() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
bool BlobUrlRegistry::AddUrlMapping(
const GURL& blob_url,
mojo::PendingRemote<blink::mojom::Blob> blob,
// TODO(https://crbug.com/1224926): Remove these once experiment is over.
const base::UnguessableToken& unsafe_agent_cluster_id,
const absl::optional<net::SchemefulSite>& unsafe_top_level_site) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!BlobUrlUtils::UrlHasFragment(blob_url));
if (IsUrlMapped(blob_url))
return false;
url_to_unsafe_agent_cluster_id_[blob_url] = unsafe_agent_cluster_id;
if (unsafe_top_level_site)
url_to_unsafe_top_level_site_[blob_url] = *unsafe_top_level_site;
url_to_blob_[blob_url] = std::move(blob);
return true;
}
bool BlobUrlRegistry::RemoveUrlMapping(const GURL& blob_url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!BlobUrlUtils::UrlHasFragment(blob_url));
auto blob_it = url_to_blob_.find(blob_url);
if (blob_it == url_to_blob_.end()) {
return false;
}
url_to_blob_.erase(blob_it);
url_to_unsafe_agent_cluster_id_.erase(blob_url);
url_to_unsafe_top_level_site_.erase(blob_url);
return true;
}
bool BlobUrlRegistry::IsUrlMapped(const GURL& blob_url) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (url_to_blob_.find(blob_url) != url_to_blob_.end())
return true;
if (fallback_)
return fallback_->IsUrlMapped(blob_url);
return false;
}
// TODO(https://crbug.com/1224926): Remove this once experiment is over.
absl::optional<base::UnguessableToken> BlobUrlRegistry::GetUnsafeAgentClusterID(
const GURL& blob_url) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = url_to_unsafe_agent_cluster_id_.find(blob_url);
if (it != url_to_unsafe_agent_cluster_id_.end())
return it->second;
if (fallback_)
return fallback_->GetUnsafeAgentClusterID(blob_url);
return absl::nullopt;
}
absl::optional<net::SchemefulSite> BlobUrlRegistry::GetUnsafeTopLevelSite(
const GURL& blob_url) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = url_to_unsafe_top_level_site_.find(blob_url);
if (it != url_to_unsafe_top_level_site_.end())
return it->second;
if (fallback_)
return fallback_->GetUnsafeTopLevelSite(blob_url);
return absl::nullopt;
}
mojo::PendingRemote<blink::mojom::Blob> BlobUrlRegistry::GetBlobFromUrl(
const GURL& url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = url_to_blob_.find(BlobUrlUtils::ClearUrlFragment(url));
if (it == url_to_blob_.end())
return fallback_ ? fallback_->GetBlobFromUrl(url) : mojo::NullRemote();
mojo::Remote<blink::mojom::Blob> blob(std::move(it->second));
mojo::PendingRemote<blink::mojom::Blob> result;
blob->Clone(result.InitWithNewPipeAndPassReceiver());
it->second = blob.Unbind();
return result;
}
void BlobUrlRegistry::AddTokenMapping(
const base::UnguessableToken& token,
const GURL& url,
mojo::PendingRemote<blink::mojom::Blob> blob) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(token_to_url_and_blob_.find(token) == token_to_url_and_blob_.end());
token_to_url_and_blob_.emplace(token, std::make_pair(url, std::move(blob)));
}
void BlobUrlRegistry::RemoveTokenMapping(const base::UnguessableToken& token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(token_to_url_and_blob_.find(token) != token_to_url_and_blob_.end());
token_to_url_and_blob_.erase(token);
}
bool BlobUrlRegistry::GetTokenMapping(
const base::UnguessableToken& token,
GURL* url,
mojo::PendingRemote<blink::mojom::Blob>* blob) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = token_to_url_and_blob_.find(token);
if (it == token_to_url_and_blob_.end())
return false;
*url = it->second.first;
mojo::Remote<blink::mojom::Blob> source_blob(std::move(it->second.second));
source_blob->Clone(blob->InitWithNewPipeAndPassReceiver());
it->second.second = source_blob.Unbind();
return true;
}
} // namespace storage