blob: bef6ce2d31358537516f918d316dc1890f2d456c [file] [log] [blame]
// Copyright (c) 2011 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_request_job_factory.h"
#include <memory>
#include <utility>
#include "base/strings/string_util.h"
#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request_context.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job.h"
namespace storage {
namespace {
int kUserDataKey; // The value is not important, the addr is a key.
} // namespace
// static
std::unique_ptr<net::URLRequest> BlobProtocolHandler::CreateBlobRequest(
std::unique_ptr<BlobDataHandle> blob_data_handle,
const net::URLRequestContext* request_context,
net::URLRequest::Delegate* request_delegate) {
const GURL kBlobUrl("blob://see_user_data/");
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("blob_read", R"(
semantics {
sender: "BlobProtocolHandler"
description:
"Blobs are used for a variety of use cases, and are basically "
"immutable blocks of data. See https://chromium.googlesource.com/"
"chromium/src/+/master/storage/browser/blob/README.md for an "
"explanation of blobs and their implementation in Chrome. These "
"can be created by scripts in a website, web platform features, or "
"internally in the browser."
trigger:
"Request for reading the contents of a blob."
data:
"A reference to a Blob, File, or CacheStorage entry created from "
"script, a web platform feature, or browser internals."
destination: LOCAL
}
policy {
cookies_allowed: NO
setting: "This feature cannot be disabled by settings."
policy_exception_justification:
"Not implemented. This is a local data fetch request and has no "
"network activity."
})");
std::unique_ptr<net::URLRequest> request = request_context->CreateRequest(
kBlobUrl, net::DEFAULT_PRIORITY, request_delegate, traffic_annotation);
request->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DO_NOT_SEND_COOKIES);
SetRequestedBlobDataHandle(request.get(), std::move(blob_data_handle));
return request;
}
// static
void BlobProtocolHandler::SetRequestedBlobDataHandle(
net::URLRequest* request,
std::unique_ptr<BlobDataHandle> blob_data_handle) {
request->SetUserData(&kUserDataKey, std::move(blob_data_handle));
}
// static
BlobDataHandle* BlobProtocolHandler::GetRequestBlobDataHandle(
net::URLRequest* request) {
return static_cast<BlobDataHandle*>(request->GetUserData(&kUserDataKey));
}
BlobProtocolHandler::BlobProtocolHandler(BlobStorageContext* context) {
if (context)
context_ = context->AsWeakPtr();
}
BlobProtocolHandler::~BlobProtocolHandler() = default;
net::URLRequestJob* BlobProtocolHandler::MaybeCreateJob(
net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
return new storage::BlobURLRequestJob(request, network_delegate,
LookupBlobHandle(request));
}
bool BlobProtocolHandler::IsSafeRedirectTarget(const GURL& location) const {
return false;
}
BlobDataHandle* BlobProtocolHandler::LookupBlobHandle(
net::URLRequest* request) const {
BlobDataHandle* blob_data_handle = GetRequestBlobDataHandle(request);
if (blob_data_handle)
return blob_data_handle;
if (!context_.get())
return nullptr;
// Support looking up based on uuid, the FeedbackExtensionAPI relies on this.
// TODO(michaeln): Replace this use case and others like it with a BlobReader
// impl that does not depend on urlfetching to perform this function.
const std::string kPrefix("blob:uuid/");
if (!base::StartsWith(request->url().spec(), kPrefix,
base::CompareCase::SENSITIVE))
return nullptr;
std::string uuid = request->url().spec().substr(kPrefix.length());
std::unique_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(uuid);
BlobDataHandle* handle_ptr = handle.get();
if (handle) {
SetRequestedBlobDataHandle(request, std::move(handle));
}
return handle_ptr;
}
} // namespace storage