blob: a1e044e13ced9cb257db7d61dc6e6142d338ab9a [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "storage/browser/file_system/sandbox_file_stream_reader.h"
#include <stdint.h>
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_operation_runner.h"
#include "storage/browser/file_system/memory_file_stream_reader.h"
#include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h"
#include "storage/browser/file_system/sandbox_file_system_backend_delegate.h"
// TODO(kinuko): Remove this temporary namespace hack after we move both
// blob and fileapi into content namespace.
namespace storage {
SandboxFileStreamReader::SandboxFileStreamReader(
FileSystemContext* file_system_context,
const FileSystemURL& url,
int64_t initial_offset,
const base::Time& expected_modification_time)
: file_system_context_(file_system_context),
url_(url),
initial_offset_(initial_offset),
expected_modification_time_(expected_modification_time),
has_pending_create_snapshot_(false) {}
SandboxFileStreamReader::~SandboxFileStreamReader() = default;
int SandboxFileStreamReader::Read(net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback) {
DCHECK(buf);
if (file_reader_)
return file_reader_->Read(buf, buf_len, std::move(callback));
return CreateSnapshot(
base::BindOnce(&SandboxFileStreamReader::DidCreateSnapshotForRead,
weak_factory_.GetWeakPtr(), base::Unretained(buf), buf_len,
std::move(callback)));
}
int64_t SandboxFileStreamReader::GetLength(
net::Int64CompletionOnceCallback callback) {
if (file_reader_)
return file_reader_->GetLength(std::move(callback));
return CreateSnapshot(
base::BindOnce(&SandboxFileStreamReader::DidCreateSnapshotForGetLength,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
int SandboxFileStreamReader::CreateSnapshot(SnapshotCallback callback) {
DCHECK(!has_pending_create_snapshot_);
has_pending_create_snapshot_ = true;
file_system_context_->operation_runner()->CreateSnapshotFile(
url_, std::move(callback));
return net::ERR_IO_PENDING;
}
void SandboxFileStreamReader::DidCreateSnapshotForRead(
net::IOBuffer* read_buf,
int read_len,
net::CompletionOnceCallback callback,
base::File::Error file_error,
const base::File::Info& file_info,
const base::FilePath& platform_path,
scoped_refptr<ShareableFileReference> file_ref) {
DCHECK(has_pending_create_snapshot_);
DCHECK(!file_reader_.get());
has_pending_create_snapshot_ = false;
if (file_error != base::File::FILE_OK) {
std::move(callback).Run(net::FileErrorToNetError(file_error));
return;
}
// Keep the reference (if it's non-null) so that the file won't go away.
snapshot_ref_ = std::move(file_ref);
CreateFileReader(platform_path);
auto callback_pair = base::SplitOnceCallback(std::move(callback));
DCHECK(read_buf);
int rv = Read(read_buf, read_len,
base::BindOnce(&SandboxFileStreamReader::OnRead,
weak_factory_.GetWeakPtr(),
std::move(callback_pair.first)));
if (rv != net::ERR_IO_PENDING) {
std::move(callback_pair.second).Run(rv);
}
}
void SandboxFileStreamReader::DidCreateSnapshotForGetLength(
net::Int64CompletionOnceCallback callback,
base::File::Error file_error,
const base::File::Info& file_info,
const base::FilePath& platform_path,
scoped_refptr<ShareableFileReference> file_ref) {
DCHECK(has_pending_create_snapshot_);
DCHECK(!file_reader_.get());
has_pending_create_snapshot_ = false;
if (file_error != base::File::FILE_OK) {
std::move(callback).Run(net::FileErrorToNetError(file_error));
return;
}
// Keep the reference (if it's non-null) so that the file won't go away.
snapshot_ref_ = std::move(file_ref);
CreateFileReader(platform_path);
auto callback_pair = base::SplitOnceCallback(std::move(callback));
int64_t rv = file_reader_->GetLength(base::BindOnce(
&SandboxFileStreamReader::OnGetLength, weak_factory_.GetWeakPtr(),
std::move(callback_pair.first)));
if (rv != net::ERR_IO_PENDING)
std::move(callback_pair.second).Run(rv);
}
void SandboxFileStreamReader::CreateFileReader(
const base::FilePath& platform_path) {
if (file_system_context_->is_incognito()) {
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_delegate =
file_system_context_->sandbox_delegate()->memory_file_util_delegate();
file_reader_ = std::make_unique<MemoryFileStreamReader>(
file_system_context_->default_file_task_runner(),
memory_file_util_delegate, platform_path, initial_offset_,
expected_modification_time_);
} else {
file_reader_ = FileStreamReader::CreateForLocalFile(
file_system_context_->default_file_task_runner(), platform_path,
initial_offset_, expected_modification_time_);
}
}
void SandboxFileStreamReader::OnRead(net::CompletionOnceCallback callback,
int rv) {
std::move(callback).Run(rv);
}
void SandboxFileStreamReader::OnGetLength(
net::Int64CompletionOnceCallback callback,
int64_t rv) {
std::move(callback).Run(rv);
}
} // namespace storage