| // 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 |