Commit a324fc57 authored by Stuart Langley's avatar Stuart Langley Committed by Commit Bot

Store completion callback in member variable and flow that around.

Prevents stack overflow when copying/moving large files caused by continually
wrapping the callback with base::AdaptCallbackForRepeating.

Bug: 905798
Change-Id: I5bd6c923a27d626cd2c2b157c301c7e43de923ce
Reviewed-on: https://chromium-review.googlesource.com/c/1353042Reviewed-by: default avatarSam McNally <sammc@chromium.org>
Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Commit-Queue: Stuart Langley <slangley@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612031}
parent eb746a5c
...@@ -613,79 +613,73 @@ CopyOrMoveOperationDelegate::StreamCopyHelper::~StreamCopyHelper() = default; ...@@ -613,79 +613,73 @@ CopyOrMoveOperationDelegate::StreamCopyHelper::~StreamCopyHelper() = default;
void CopyOrMoveOperationDelegate::StreamCopyHelper::Run( void CopyOrMoveOperationDelegate::StreamCopyHelper::Run(
StatusCallback callback) { StatusCallback callback) {
DCHECK(callback);
DCHECK(!completion_callback_);
completion_callback_ = std::move(callback);
file_progress_callback_.Run(0); file_progress_callback_.Run(0);
last_progress_callback_invocation_time_ = base::Time::Now(); last_progress_callback_invocation_time_ = base::Time::Now();
Read(std::move(callback)); Read();
} }
void CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel() { void CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel() {
cancel_requested_ = true; cancel_requested_ = true;
} }
void CopyOrMoveOperationDelegate::StreamCopyHelper::Read( void CopyOrMoveOperationDelegate::StreamCopyHelper::Read() {
StatusCallback callback) {
auto repeatable_callback =
base::AdaptCallbackForRepeating(std::move(callback));
int result = reader_->Read( int result = reader_->Read(
io_buffer_.get(), io_buffer_->size(), io_buffer_.get(), io_buffer_->size(),
base::BindOnce(&StreamCopyHelper::DidRead, weak_factory_.GetWeakPtr(), base::BindOnce(&StreamCopyHelper::DidRead, weak_factory_.GetWeakPtr()));
repeatable_callback));
if (result != net::ERR_IO_PENDING) if (result != net::ERR_IO_PENDING)
DidRead(repeatable_callback, result); DidRead(result);
} }
void CopyOrMoveOperationDelegate::StreamCopyHelper::DidRead( void CopyOrMoveOperationDelegate::StreamCopyHelper::DidRead(int result) {
StatusCallback callback,
int result) {
if (cancel_requested_) { if (cancel_requested_) {
std::move(callback).Run(base::File::FILE_ERROR_ABORT); std::move(completion_callback_).Run(base::File::FILE_ERROR_ABORT);
return; return;
} }
if (result < 0) { if (result < 0) {
std::move(callback).Run(NetErrorToFileError(result)); std::move(completion_callback_).Run(NetErrorToFileError(result));
return; return;
} }
if (result == 0) { if (result == 0) {
// Here is the EOF. // Here is the EOF.
if (flush_policy_ == storage::FlushPolicy::FLUSH_ON_COMPLETION) if (flush_policy_ == storage::FlushPolicy::FLUSH_ON_COMPLETION)
Flush(std::move(callback), true /* is_eof */); Flush(true /* is_eof */);
else else
std::move(callback).Run(base::File::FILE_OK); std::move(completion_callback_).Run(base::File::FILE_OK);
return; return;
} }
Write(std::move(callback), Write(base::MakeRefCounted<net::DrainableIOBuffer>(io_buffer_, result));
base::MakeRefCounted<net::DrainableIOBuffer>(io_buffer_, result));
} }
void CopyOrMoveOperationDelegate::StreamCopyHelper::Write( void CopyOrMoveOperationDelegate::StreamCopyHelper::Write(
StatusCallback callback,
scoped_refptr<net::DrainableIOBuffer> buffer) { scoped_refptr<net::DrainableIOBuffer> buffer) {
DCHECK_GT(buffer->BytesRemaining(), 0); DCHECK_GT(buffer->BytesRemaining(), 0);
auto repeatable_callback = int result =
base::AdaptCallbackForRepeating(std::move(callback)); writer_->Write(buffer.get(), buffer->BytesRemaining(),
int result = writer_->Write( base::BindOnce(&StreamCopyHelper::DidWrite,
buffer.get(), buffer->BytesRemaining(), weak_factory_.GetWeakPtr(), buffer));
base::BindOnce(&StreamCopyHelper::DidWrite, weak_factory_.GetWeakPtr(),
repeatable_callback, buffer));
if (result != net::ERR_IO_PENDING) if (result != net::ERR_IO_PENDING)
DidWrite(repeatable_callback, buffer, result); DidWrite(buffer, result);
} }
void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite( void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite(
StatusCallback callback,
scoped_refptr<net::DrainableIOBuffer> buffer, scoped_refptr<net::DrainableIOBuffer> buffer,
int result) { int result) {
if (cancel_requested_) { if (cancel_requested_) {
std::move(callback).Run(base::File::FILE_ERROR_ABORT); std::move(completion_callback_).Run(base::File::FILE_ERROR_ABORT);
return; return;
} }
if (result < 0) { if (result < 0) {
std::move(callback).Run(NetErrorToFileError(result)); std::move(completion_callback_).Run(NetErrorToFileError(result));
return; return;
} }
...@@ -701,44 +695,38 @@ void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite( ...@@ -701,44 +695,38 @@ void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite(
} }
if (buffer->BytesRemaining() > 0) { if (buffer->BytesRemaining() > 0) {
Write(std::move(callback), buffer); Write(buffer);
return; return;
} }
if (flush_policy_ == storage::FlushPolicy::FLUSH_ON_COMPLETION && if (flush_policy_ == storage::FlushPolicy::FLUSH_ON_COMPLETION &&
(num_copied_bytes_ - previous_flush_offset_) > kFlushIntervalInBytes) { (num_copied_bytes_ - previous_flush_offset_) > kFlushIntervalInBytes) {
Flush(std::move(callback), false /* not is_eof */); Flush(false /* not is_eof */);
} else { } else {
Read(std::move(callback)); Read();
} }
} }
void CopyOrMoveOperationDelegate::StreamCopyHelper::Flush( void CopyOrMoveOperationDelegate::StreamCopyHelper::Flush(bool is_eof) {
StatusCallback callback, int result = writer_->Flush(base::BindOnce(
bool is_eof) { &StreamCopyHelper::DidFlush, weak_factory_.GetWeakPtr(), is_eof));
auto repeatable_callback =
base::AdaptCallbackForRepeating(std::move(callback));
int result = writer_->Flush(base::BindOnce(&StreamCopyHelper::DidFlush,
weak_factory_.GetWeakPtr(),
repeatable_callback, is_eof));
if (result != net::ERR_IO_PENDING) if (result != net::ERR_IO_PENDING)
DidFlush(repeatable_callback, is_eof, result); DidFlush(is_eof, result);
} }
void CopyOrMoveOperationDelegate::StreamCopyHelper::DidFlush( void CopyOrMoveOperationDelegate::StreamCopyHelper::DidFlush(
StatusCallback callback,
bool is_eof, bool is_eof,
int result) { int result) {
if (cancel_requested_) { if (cancel_requested_) {
std::move(callback).Run(base::File::FILE_ERROR_ABORT); std::move(completion_callback_).Run(base::File::FILE_ERROR_ABORT);
return; return;
} }
previous_flush_offset_ = num_copied_bytes_; previous_flush_offset_ = num_copied_bytes_;
if (is_eof) if (is_eof)
std::move(callback).Run(NetErrorToFileError(result)); std::move(completion_callback_).Run(NetErrorToFileError(result));
else else
Read(std::move(callback)); Read();
} }
CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate( CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate(
......
...@@ -64,24 +64,22 @@ class CopyOrMoveOperationDelegate ...@@ -64,24 +64,22 @@ class CopyOrMoveOperationDelegate
private: private:
// Reads the content from the |reader_|. // Reads the content from the |reader_|.
void Read(StatusCallback callback); void Read();
void DidRead(StatusCallback callback, int result); void DidRead(int result);
// Writes the content in |buffer| to |writer_|. // Writes the content in |buffer| to |writer_|.
void Write(StatusCallback callback, void Write(scoped_refptr<net::DrainableIOBuffer> buffer);
scoped_refptr<net::DrainableIOBuffer> buffer); void DidWrite(scoped_refptr<net::DrainableIOBuffer> buffer, int result);
void DidWrite(StatusCallback callback,
scoped_refptr<net::DrainableIOBuffer> buffer,
int result);
// Flushes the written content in |writer_|. // Flushes the written content in |writer_|.
void Flush(StatusCallback callback, bool is_eof); void Flush(bool is_eof);
void DidFlush(StatusCallback callback, bool is_eof, int result); void DidFlush(bool is_eof, int result);
std::unique_ptr<storage::FileStreamReader> reader_; std::unique_ptr<storage::FileStreamReader> reader_;
std::unique_ptr<FileStreamWriter> writer_; std::unique_ptr<FileStreamWriter> writer_;
const FlushPolicy flush_policy_; const FlushPolicy flush_policy_;
FileSystemOperation::CopyFileProgressCallback file_progress_callback_; FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
StatusCallback completion_callback_;
scoped_refptr<net::IOBufferWithSize> io_buffer_; scoped_refptr<net::IOBufferWithSize> io_buffer_;
int64_t num_copied_bytes_; int64_t num_copied_bytes_;
int64_t previous_flush_offset_; int64_t previous_flush_offset_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment