Commit d58c3417 authored by kinuko@chromium.org's avatar kinuko@chromium.org

Reland 132134 with memory fix - Use LocalFileReader in FileSystemURLRequestJob

LocalFileReader change https://chromiumcodereview.appspot.com/10065011
with memory fix http://codereview.chromium.org/10067031/

BUG=113300, 114999, 123302
TEST=FileSystemURLRequestJobTest.*

Review URL: https://chromiumcodereview.appspot.com/10080001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132559 0039d316-1c4b-4281-b951-d872f2087c98
parent 9485ad7b
...@@ -43,10 +43,6 @@ const char kHTTPRequestedRangeNotSatisfiableText[] = ...@@ -43,10 +43,6 @@ const char kHTTPRequestedRangeNotSatisfiableText[] =
"Requested Range Not Satisfiable"; "Requested Range Not Satisfiable";
const char kHTTPInternalErrorText[] = "Internal Server Error"; const char kHTTPInternalErrorText[] = "Internal Server Error";
const int kFileOpenFlags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_ASYNC;
} // namespace } // namespace
BlobURLRequestJob::BlobURLRequestJob( BlobURLRequestJob::BlobURLRequestJob(
...@@ -361,12 +357,18 @@ bool BlobURLRequestJob::ReadFileItem(LocalFileReader* reader, ...@@ -361,12 +357,18 @@ bool BlobURLRequestJob::ReadFileItem(LocalFileReader* reader,
read_buf_, bytes_to_read, read_buf_, bytes_to_read,
base::Bind(&BlobURLRequestJob::DidReadFile, base::Bind(&BlobURLRequestJob::DidReadFile,
base::Unretained(this))); base::Unretained(this)));
if (result != net::ERR_IO_PENDING) { if (result >= 0) {
DCHECK(result != net::OK); // Data is immediately available.
NotifyFailure(result); if (GetStatus().is_io_pending())
return false; DidReadFile(result);
else
AdvanceBytesRead(result);
return true;
} }
if (result == net::ERR_IO_PENDING)
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
else
NotifyFailure(result);
return false; return false;
} }
......
...@@ -70,7 +70,7 @@ void DidSeekFile(const LocalFileReader::OpenFileStreamCallback& callback, ...@@ -70,7 +70,7 @@ void DidSeekFile(const LocalFileReader::OpenFileStreamCallback& callback,
if (new_offset < 0) if (new_offset < 0)
result = static_cast<int>(new_offset); result = static_cast<int>(new_offset);
else if (new_offset != initial_offset) else if (new_offset != initial_offset)
result = net::ERR_FAILED; result = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
callback.Run(result, stream_impl.Pass()); callback.Run(result, stream_impl.Pass());
} }
......
...@@ -34,7 +34,9 @@ class BLOB_EXPORT LocalFileReader { ...@@ -34,7 +34,9 @@ class BLOB_EXPORT LocalFileReader {
// Creates a new FileReader for a local file |file_path|. // Creates a new FileReader for a local file |file_path|.
// |initial_offset| specifies the offset in the file where the first read // |initial_offset| specifies the offset in the file where the first read
// should start. // should start. If the given offset is out of the file range any
// read operation may error out with net::ERR_REQUEST_RANGE_NOT_SATISFIABLE.
//
// |expected_modification_time| specifies the expected last modification // |expected_modification_time| specifies the expected last modification
// If the value is non-null, the reader will check the underlying file's // If the value is non-null, the reader will check the underlying file's
// actual modification time to see if the file has been modified, and if // actual modification time to see if the file has been modified, and if
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
#include "webkit/fileapi/file_system_url_request_job.h" #include "webkit/fileapi/file_system_url_request_job.h"
#include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/file_path.h" #include "base/file_path.h"
...@@ -13,6 +11,7 @@ ...@@ -13,6 +11,7 @@
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/platform_file.h" #include "base/platform_file.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "googleurl/src/gurl.h" #include "googleurl/src/gurl.h"
#include "net/base/file_stream.h" #include "net/base/file_stream.h"
...@@ -24,6 +23,7 @@ ...@@ -24,6 +23,7 @@
#include "net/http/http_response_info.h" #include "net/http/http_response_info.h"
#include "net/http/http_util.h" #include "net/http/http_util.h"
#include "net/url_request/url_request.h" #include "net/url_request/url_request.h"
#include "webkit/blob/local_file_reader.h"
#include "webkit/blob/shareable_file_reference.h" #include "webkit/blob/shareable_file_reference.h"
#include "webkit/fileapi/file_system_context.h" #include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_operation.h" #include "webkit/fileapi/file_system_operation.h"
...@@ -32,13 +32,10 @@ ...@@ -32,13 +32,10 @@
using net::URLRequest; using net::URLRequest;
using net::URLRequestJob; using net::URLRequestJob;
using net::URLRequestStatus; using net::URLRequestStatus;
using webkit_blob::LocalFileReader;
namespace fileapi { namespace fileapi {
static const int kFileFlags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_ASYNC;
static net::HttpResponseHeaders* CreateHttpResponseHeaders() { static net::HttpResponseHeaders* CreateHttpResponseHeaders() {
// HttpResponseHeaders expects its input string to be terminated by two NULs. // HttpResponseHeaders expects its input string to be terminated by two NULs.
static const char kStatus[] = "HTTP/1.1 200 OK\0"; static const char kStatus[] = "HTTP/1.1 200 OK\0";
...@@ -62,20 +59,11 @@ FileSystemURLRequestJob::FileSystemURLRequestJob( ...@@ -62,20 +59,11 @@ FileSystemURLRequestJob::FileSystemURLRequestJob(
file_system_context_(file_system_context), file_system_context_(file_system_context),
file_thread_proxy_(file_thread_proxy), file_thread_proxy_(file_thread_proxy),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
stream_(NULL),
is_directory_(false), is_directory_(false),
remaining_bytes_(0) { remaining_bytes_(0) {
} }
FileSystemURLRequestJob::~FileSystemURLRequestJob() { FileSystemURLRequestJob::~FileSystemURLRequestJob() {}
// Since we use the two-arg constructor of FileStream, we need to call Close()
// manually: ~FileStream won't call it for us.
if (stream_ != NULL) {
// Close() performs file IO: crbug.com/113300.
base::ThreadRestrictions::ScopedAllowIO allow_io;
stream_->CloseSync();
}
}
void FileSystemURLRequestJob::Start() { void FileSystemURLRequestJob::Start() {
MessageLoop::current()->PostTask( MessageLoop::current()->PostTask(
...@@ -85,12 +73,8 @@ void FileSystemURLRequestJob::Start() { ...@@ -85,12 +73,8 @@ void FileSystemURLRequestJob::Start() {
} }
void FileSystemURLRequestJob::Kill() { void FileSystemURLRequestJob::Kill() {
if (stream_ != NULL) { if (reader_.get() != NULL)
// Close() performs file IO: crbug.com/113300. reader_.reset();
base::ThreadRestrictions::ScopedAllowIO allow_io;
stream_->CloseSync();
stream_.reset(NULL);
}
URLRequestJob::Kill(); URLRequestJob::Kill();
weak_factory_.InvalidateWeakPtrs(); weak_factory_.InvalidateWeakPtrs();
} }
...@@ -101,7 +85,7 @@ bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, ...@@ -101,7 +85,7 @@ bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size,
DCHECK(bytes_read); DCHECK(bytes_read);
DCHECK_GE(remaining_bytes_, 0); DCHECK_GE(remaining_bytes_, 0);
if (stream_ == NULL) if (reader_.get() == NULL)
return false; return false;
if (remaining_bytes_ < dest_size) if (remaining_bytes_ < dest_size)
...@@ -112,7 +96,7 @@ bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, ...@@ -112,7 +96,7 @@ bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size,
return true; return true;
} }
int rv = stream_->Read(dest, dest_size, const int rv = reader_->Read(dest, dest_size,
base::Bind(&FileSystemURLRequestJob::DidRead, base::Bind(&FileSystemURLRequestJob::DidRead,
base::Unretained(this))); base::Unretained(this)));
if (rv >= 0) { if (rv >= 0) {
...@@ -122,8 +106,6 @@ bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, ...@@ -122,8 +106,6 @@ bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size,
DCHECK_GE(remaining_bytes_, 0); DCHECK_GE(remaining_bytes_, 0);
return true; return true;
} }
// Otherwise, a read error occured. We may just need to wait...
if (rv == net::ERR_IO_PENDING) if (rv == net::ERR_IO_PENDING)
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
else else
...@@ -214,47 +196,24 @@ void FileSystemURLRequestJob::DidCreateSnapshot( ...@@ -214,47 +196,24 @@ void FileSystemURLRequestJob::DidCreateSnapshot(
return; return;
} }
if (!is_directory_) { if (is_directory_) {
base::FileUtilProxy::CreateOrOpen(
file_thread_proxy_, platform_path, kFileFlags,
base::Bind(&FileSystemURLRequestJob::DidOpen,
weak_factory_.GetWeakPtr()));
} else {
NotifyHeadersComplete(); NotifyHeadersComplete();
}
}
void FileSystemURLRequestJob::DidOpen(base::PlatformFileError error_code,
base::PassPlatformFile file,
bool created) {
if (error_code != base::PLATFORM_FILE_OK) {
NotifyFailed(error_code);
return; return;
} }
stream_.reset(new net::FileStream(file.ReleaseValue(), kFileFlags, NULL));
remaining_bytes_ = byte_range_.last_byte_position() - remaining_bytes_ = byte_range_.last_byte_position() -
byte_range_.first_byte_position() + 1; byte_range_.first_byte_position() + 1;
DCHECK_GE(remaining_bytes_, 0); DCHECK_GE(remaining_bytes_, 0);
// TODO(adamk): Please remove this ScopedAllowIO once we support async seek DCHECK(!reader_.get());
// on FileStream. crbug.com/113300 reader_.reset(new LocalFileReader(
base::ThreadRestrictions::ScopedAllowIO allow_io; file_thread_proxy_, platform_path,
// Do the seek at the beginning of the request. byte_range_.first_byte_position(),
if (remaining_bytes_ > 0 && base::Time()));
byte_range_.first_byte_position() != 0 &&
byte_range_.first_byte_position() !=
stream_->SeekSync(net::FROM_BEGIN,
byte_range_.first_byte_position())) {
NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
return;
}
set_expected_content_size(remaining_bytes_); set_expected_content_size(remaining_bytes_);
response_info_.reset(new net::HttpResponseInfo()); response_info_.reset(new net::HttpResponseInfo());
response_info_->headers = CreateHttpResponseHeaders(); response_info_->headers = CreateHttpResponseHeaders();
NotifyHeadersComplete(); NotifyHeadersComplete();
} }
......
...@@ -19,11 +19,8 @@ ...@@ -19,11 +19,8 @@
class GURL; class GURL;
class FilePath; class FilePath;
namespace net {
class FileStream;
}
namespace webkit_blob { namespace webkit_blob {
class LocalFileReader;
class ShareableFileReference; class ShareableFileReference;
} }
...@@ -73,7 +70,7 @@ class FileSystemURLRequestJob : public net::URLRequestJob { ...@@ -73,7 +70,7 @@ class FileSystemURLRequestJob : public net::URLRequestJob {
FileSystemContext* file_system_context_; FileSystemContext* file_system_context_;
scoped_refptr<base::MessageLoopProxy> file_thread_proxy_; scoped_refptr<base::MessageLoopProxy> file_thread_proxy_;
base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_; base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_;
scoped_ptr<net::FileStream> stream_; scoped_ptr<webkit_blob::LocalFileReader> reader_;
scoped_refptr<webkit_blob::ShareableFileReference> snapshot_ref_; scoped_refptr<webkit_blob::ShareableFileReference> snapshot_ref_;
bool is_directory_; bool is_directory_;
scoped_ptr<net::HttpResponseInfo> response_info_; scoped_ptr<net::HttpResponseInfo> response_info_;
......
...@@ -70,7 +70,7 @@ class FileSystemURLRequestJobTest : public testing::Test { ...@@ -70,7 +70,7 @@ class FileSystemURLRequestJobTest : public testing::Test {
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
} }
virtual void SetUp() { virtual void SetUp() OVERRIDE {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
special_storage_policy_ = new quota::MockSpecialStoragePolicy; special_storage_policy_ = new quota::MockSpecialStoragePolicy;
...@@ -94,9 +94,15 @@ class FileSystemURLRequestJobTest : public testing::Test { ...@@ -94,9 +94,15 @@ class FileSystemURLRequestJobTest : public testing::Test {
"filesystem", &FileSystemURLRequestJobFactory); "filesystem", &FileSystemURLRequestJobFactory);
} }
virtual void TearDown() { virtual void TearDown() OVERRIDE {
net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL); net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL);
ClearUnusedJob(); ClearUnusedJob();
if (pending_job_) {
pending_job_->Kill();
pending_job_ = NULL;
}
// FileReader posts a task to close the file in destructor.
MessageLoop::current()->RunAllPending();
} }
void OnValidateFileSystem(base::PlatformFileError result) { void OnValidateFileSystem(base::PlatformFileError result) {
...@@ -113,10 +119,12 @@ class FileSystemURLRequestJobTest : public testing::Test { ...@@ -113,10 +119,12 @@ class FileSystemURLRequestJobTest : public testing::Test {
request_.reset(new net::URLRequest(url, delegate_.get())); request_.reset(new net::URLRequest(url, delegate_.get()));
if (headers) if (headers)
request_->SetExtraRequestHeaders(*headers); request_->SetExtraRequestHeaders(*headers);
ASSERT_TRUE(!job_);
job_ = new FileSystemURLRequestJob( job_ = new FileSystemURLRequestJob(
request_.get(), request_.get(),
file_system_context_.get(), file_system_context_.get(),
base::MessageLoopProxy::current()); base::MessageLoopProxy::current());
pending_job_ = job_;
request_->Start(); request_->Start();
ASSERT_TRUE(request_->is_pending()); // verify that we're starting async ASSERT_TRUE(request_->is_pending()); // verify that we're starting async
...@@ -212,6 +220,7 @@ class FileSystemURLRequestJobTest : public testing::Test { ...@@ -212,6 +220,7 @@ class FileSystemURLRequestJobTest : public testing::Test {
scoped_ptr<TestDelegate> delegate_; scoped_ptr<TestDelegate> delegate_;
scoped_ptr<net::URLRequest> request_; scoped_ptr<net::URLRequest> request_;
scoped_refptr<net::URLRequestJob> pending_job_;
static net::URLRequestJob* job_; static net::URLRequestJob* job_;
}; };
......
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