blob: 55e63a1b620697add3368bf82cd0537387de0eb5 [file] [log] [blame]
// Copyright (c) 2013 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_data_handle.h"
#include <stdint.h>
#include <memory>
#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner.h"
#include "base/time/time.h"
#include "storage/browser/blob/blob_data_snapshot.h"
#include "storage/browser/blob/blob_reader.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/fileapi/file_stream_reader.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "url/gurl.h"
namespace storage {
using BlobState = BlobStorageRegistry::BlobState;
namespace {
class FileStreamReaderProviderImpl
: public BlobReader::FileStreamReaderProvider {
public:
explicit FileStreamReaderProviderImpl(FileSystemContext* file_system_context)
: file_system_context_(file_system_context) {}
~FileStreamReaderProviderImpl() override {}
std::unique_ptr<FileStreamReader> CreateForLocalFile(
base::TaskRunner* task_runner,
const base::FilePath& file_path,
int64_t initial_offset,
const base::Time& expected_modification_time) override {
return base::WrapUnique(FileStreamReader::CreateForLocalFile(
task_runner, file_path, initial_offset, expected_modification_time));
}
std::unique_ptr<FileStreamReader> CreateFileStreamReader(
const GURL& filesystem_url,
int64_t offset,
int64_t max_bytes_to_read,
const base::Time& expected_modification_time) override {
return file_system_context_->CreateFileStreamReader(
storage::FileSystemURL(file_system_context_->CrackURL(filesystem_url)),
offset, max_bytes_to_read, expected_modification_time);
}
private:
scoped_refptr<FileSystemContext> file_system_context_;
DISALLOW_COPY_AND_ASSIGN(FileStreamReaderProviderImpl);
};
} // namespace
BlobDataHandle::BlobDataHandleShared::BlobDataHandleShared(
const std::string& uuid,
const std::string& content_type,
const std::string& content_disposition,
BlobStorageContext* context)
: uuid_(uuid),
content_type_(content_type),
content_disposition_(content_disposition),
context_(context->AsWeakPtr()) {
context_->IncrementBlobRefCount(uuid);
}
std::unique_ptr<BlobReader> BlobDataHandle::CreateReader(
FileSystemContext* file_system_context,
base::SequencedTaskRunner* file_task_runner) const {
return std::unique_ptr<BlobReader>(new BlobReader(
this, std::unique_ptr<BlobReader::FileStreamReaderProvider>(
new FileStreamReaderProviderImpl(file_system_context)),
file_task_runner));
}
BlobDataHandle::BlobDataHandleShared::~BlobDataHandleShared() {
if (context_.get())
context_->DecrementBlobRefCount(uuid_);
}
BlobDataHandle::BlobDataHandle(const std::string& uuid,
const std::string& content_type,
const std::string& content_disposition,
BlobStorageContext* context,
base::SequencedTaskRunner* io_task_runner)
: io_task_runner_(io_task_runner),
shared_(new BlobDataHandleShared(uuid,
content_type,
content_disposition,
context)) {
DCHECK(io_task_runner_.get());
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
}
BlobDataHandle::BlobDataHandle(const BlobDataHandle& other) {
io_task_runner_ = other.io_task_runner_;
shared_ = other.shared_;
}
BlobDataHandle::~BlobDataHandle() {
if (!io_task_runner_->RunsTasksOnCurrentThread()) {
BlobDataHandleShared* raw = shared_.get();
raw->AddRef();
shared_ = nullptr;
io_task_runner_->ReleaseSoon(FROM_HERE, raw);
}
}
bool BlobDataHandle::IsBeingBuilt() const {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
if (!shared_->context_)
return false;
return shared_->context_->IsBeingBuilt(shared_->uuid_);
}
bool BlobDataHandle::IsBroken() const {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
if (!shared_->context_)
return true;
return shared_->context_->IsBroken(shared_->uuid_);
}
void BlobDataHandle::RunOnConstructionComplete(
const BlobConstructedCallback& done) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
if (!shared_->context_.get()) {
done.Run(false, IPCBlobCreationCancelCode::UNKNOWN);
return;
}
shared_->context_->RunOnConstructionComplete(shared_->uuid_, done);
}
std::unique_ptr<BlobDataSnapshot> BlobDataHandle::CreateSnapshot() const {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
if (!shared_->context_.get())
return nullptr;
return shared_->context_->CreateSnapshot(shared_->uuid_);
}
const std::string& BlobDataHandle::uuid() const {
return shared_->uuid_;
}
const std::string& BlobDataHandle::content_type() const {
return shared_->content_type_;
}
const std::string& BlobDataHandle::content_disposition() const {
return shared_->content_disposition_;
}
} // namespace storage