|  | // Copyright 2018 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_loader_factory.h" | 
|  |  | 
|  | #include "mojo/public/cpp/bindings/callback_helpers.h" | 
|  | #include "storage/browser/blob/blob_data_handle.h" | 
|  | #include "storage/browser/blob/blob_storage_context.h" | 
|  | #include "storage/browser/blob/blob_url_loader.h" | 
|  |  | 
|  | namespace storage { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // The BlobURLTokenPtr parameter is passed in to make sure the connection stays | 
|  | // alive until this method is called, it is not otherwise used by this method. | 
|  | void CreateFactoryForToken(blink::mojom::BlobURLTokenPtr, | 
|  | const base::WeakPtr<BlobStorageContext>& context, | 
|  | network::mojom::URLLoaderFactoryRequest request, | 
|  | const base::UnguessableToken& token) { | 
|  | std::unique_ptr<BlobDataHandle> handle; | 
|  | GURL blob_url; | 
|  | if (context) { | 
|  | std::string uuid; | 
|  | if (context->registry().GetTokenMapping(token, &blob_url, &uuid)) | 
|  | handle = context->GetBlobDataFromUUID(uuid); | 
|  | } | 
|  | BlobURLLoaderFactory::Create(std::move(handle), blob_url, std::move(request)); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | // static | 
|  | void BlobURLLoaderFactory::Create( | 
|  | std::unique_ptr<BlobDataHandle> handle, | 
|  | const GURL& blob_url, | 
|  | network::mojom::URLLoaderFactoryRequest request) { | 
|  | new BlobURLLoaderFactory(std::move(handle), blob_url, std::move(request)); | 
|  | } | 
|  |  | 
|  | // static | 
|  | void BlobURLLoaderFactory::Create( | 
|  | blink::mojom::BlobURLTokenPtr token, | 
|  | base::WeakPtr<BlobStorageContext> context, | 
|  | network::mojom::URLLoaderFactoryRequest request) { | 
|  | // Not every URLLoaderFactory user deals with the URLLoaderFactory simply | 
|  | // disconnecting very well, so make sure we always at least bind the request | 
|  | // to some factory that can then fail with a network error. Hence the callback | 
|  | // is wrapped in WrapCallbackWithDefaultInvokeIfNotRun. | 
|  | auto* raw_token = token.get(); | 
|  | raw_token->GetToken(mojo::WrapCallbackWithDefaultInvokeIfNotRun( | 
|  | base::BindOnce(&CreateFactoryForToken, std::move(token), | 
|  | std::move(context), std::move(request)), | 
|  | base::UnguessableToken())); | 
|  | } | 
|  |  | 
|  | void BlobURLLoaderFactory::CreateLoaderAndStart( | 
|  | network::mojom::URLLoaderRequest loader, | 
|  | int32_t routing_id, | 
|  | int32_t request_id, | 
|  | uint32_t options, | 
|  | const network::ResourceRequest& request, | 
|  | network::mojom::URLLoaderClientPtr client, | 
|  | const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { | 
|  | if (url_.is_valid() && request.url != url_) { | 
|  | bindings_.ReportBadMessage("Invalid URL when attempting to fetch Blob"); | 
|  | client->OnComplete( | 
|  | network::URLLoaderCompletionStatus(net::ERR_INVALID_URL)); | 
|  | return; | 
|  | } | 
|  | BlobURLLoader::CreateAndStart( | 
|  | std::move(loader), request, std::move(client), | 
|  | handle_ ? std::make_unique<BlobDataHandle>(*handle_) : nullptr); | 
|  | } | 
|  |  | 
|  | void BlobURLLoaderFactory::Clone( | 
|  | network::mojom::URLLoaderFactoryRequest request) { | 
|  | bindings_.AddBinding(this, std::move(request)); | 
|  | } | 
|  |  | 
|  | BlobURLLoaderFactory::BlobURLLoaderFactory( | 
|  | std::unique_ptr<BlobDataHandle> handle, | 
|  | const GURL& blob_url, | 
|  | network::mojom::URLLoaderFactoryRequest request) | 
|  | : handle_(std::move(handle)), url_(blob_url) { | 
|  | bindings_.AddBinding(this, std::move(request)); | 
|  | bindings_.set_connection_error_handler(base::BindRepeating( | 
|  | &BlobURLLoaderFactory::OnConnectionError, base::Unretained(this))); | 
|  | } | 
|  |  | 
|  | BlobURLLoaderFactory::~BlobURLLoaderFactory() = default; | 
|  |  | 
|  | void BlobURLLoaderFactory::OnConnectionError() { | 
|  | if (!bindings_.empty()) | 
|  | return; | 
|  | delete this; | 
|  | } | 
|  |  | 
|  | }  // namespace storage |