summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-18 10:34:59 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-18 10:34:59 +0000
commit2b6fe01fb5686449a4b1dff5a80cde6667df6f2c (patch)
tree2033a1eb8cc3e68ed754081338c147c6305b2b95
parent1ee8078746d9cdaee48fdfe1c6806feda4f7e865 (diff)
downloadchromium_src-2b6fe01fb5686449a4b1dff5a80cde6667df6f2c.zip
chromium_src-2b6fe01fb5686449a4b1dff5a80cde6667df6f2c.tar.gz
chromium_src-2b6fe01fb5686449a4b1dff5a80cde6667df6f2c.tar.bz2
Add FileReader interface and implement FileSystemFileReader.
- Split LocalFileReader into FileReader interface and LocalFileReader implementation - Adding FileSystemFileReader as a default implementation for FileSystem files The FileSystemFileReader implementation uses CreateSnapshotFile which may force downloading the entire file (as the initial generic version). This would need to be changed in remote filesystem implementation. BUG=114999 TEST=FileSystemURLRequestJobTest, BlobURLRequestJobTest Review URL: https://chromiumcodereview.appspot.com/10038019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132774 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/blob/blob_url_request_job.cc2
-rw-r--r--webkit/blob/file_reader.h42
-rw-r--r--webkit/blob/local_file_reader.cc35
-rw-r--r--webkit/blob/local_file_reader.h31
-rw-r--r--webkit/fileapi/file_system_file_reader.cc101
-rw-r--r--webkit/fileapi/file_system_file_reader.h70
-rw-r--r--webkit/fileapi/file_system_url_request_job.cc31
-rw-r--r--webkit/fileapi/file_system_url_request_job.h16
-rw-r--r--webkit/fileapi/webkit_fileapi.gypi2
9 files changed, 267 insertions, 63 deletions
diff --git a/webkit/blob/blob_url_request_job.cc b/webkit/blob/blob_url_request_job.cc
index 49f9b04..65f8e08 100644
--- a/webkit/blob/blob_url_request_job.cc
+++ b/webkit/blob/blob_url_request_job.cc
@@ -239,7 +239,7 @@ void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) {
// in the real time.
int64 item_length = static_cast<int64>(item.length);
if (item_length == -1)
- item_length = result;
+ item_length = result - item.offset;
// Cache the size and add it to the total size.
DCHECK_LT(index, item_length_list_.size());
diff --git a/webkit/blob/file_reader.h b/webkit/blob/file_reader.h
new file mode 100644
index 0000000..78dfbf9
--- /dev/null
+++ b/webkit/blob/file_reader.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 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.
+
+#ifndef WEBKIT_BLOB_FILE_READER_H_
+#define WEBKIT_BLOB_FILE_READER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "net/base/completion_callback.h"
+#include "webkit/blob/blob_export.h"
+
+namespace net {
+class FileStream;
+class IOBuffer;
+}
+
+namespace webkit_blob {
+
+// A generic interface for reading a file-like object.
+class BLOB_EXPORT FileReader {
+ public:
+ virtual ~FileReader() {}
+
+ // Reads from the current cursor position asynchronously.
+ //
+ // Up to buf_len bytes will be copied into buf. (In other words, partial
+ // reads are allowed.) Returns the number of bytes copied, 0 if at
+ // end-of-file, or an error code if the operation could not be performed.
+ // If the read could not complete synchronously, then ERR_IO_PENDING is
+ // returned, and the callback will be run on the thread where Read()
+ // was called, when the read has completed.
+ //
+ // It is invalid to call Read while there is an in-flight Read operation.
+ virtual int Read(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) = 0;
+};
+
+} // namespace webkit_blob
+
+#endif // WEBKIT_BLOB_FILE_READER_H_
diff --git a/webkit/blob/local_file_reader.cc b/webkit/blob/local_file_reader.cc
index c728a8b..8948ac0 100644
--- a/webkit/blob/local_file_reader.cc
+++ b/webkit/blob/local_file_reader.cc
@@ -21,19 +21,6 @@ const int kOpenFlagsForRead = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_ASYNC;
-int PlatformFileErrorToNetError(base::PlatformFileError file_error) {
- switch (file_error) {
- case base::PLATFORM_FILE_OK:
- return net::OK;
- case base::PLATFORM_FILE_ERROR_NOT_FOUND:
- return net::ERR_FILE_NOT_FOUND;
- case base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
- return net::ERR_ACCESS_DENIED;
- default:
- return net::ERR_FAILED;
- }
-}
-
// Verify if the underlying file has not been modified.
bool VerifySnapshotTime(const base::Time& expected_modification_time,
const base::PlatformFileInfo& file_info) {
@@ -44,7 +31,6 @@ bool VerifySnapshotTime(const base::Time& expected_modification_time,
void DidGetFileInfoForGetLength(const net::Int64CompletionCallback& callback,
const base::Time& expected_modification_time,
- int64 initial_offset,
base::PlatformFileError error,
const base::PlatformFileInfo& file_info) {
if (file_info.is_directory) {
@@ -52,14 +38,14 @@ void DidGetFileInfoForGetLength(const net::Int64CompletionCallback& callback,
return;
}
if (error != base::PLATFORM_FILE_OK) {
- callback.Run(PlatformFileErrorToNetError(error));
+ callback.Run(LocalFileReader::PlatformFileErrorToNetError(error));
return;
}
if (!VerifySnapshotTime(expected_modification_time, file_info)) {
callback.Run(net::ERR_UPLOAD_FILE_CHANGED);
return;
}
- callback.Run(file_info.size - initial_offset);
+ callback.Run(file_info.size);
}
void DidSeekFile(const LocalFileReader::OpenFileStreamCallback& callback,
@@ -78,6 +64,21 @@ void EmptyCompletionCallback(int) {}
} // namespace
+// static
+int LocalFileReader::PlatformFileErrorToNetError(
+ base::PlatformFileError file_error) {
+ switch (file_error) {
+ case base::PLATFORM_FILE_OK:
+ return net::OK;
+ case base::PLATFORM_FILE_ERROR_NOT_FOUND:
+ return net::ERR_FILE_NOT_FOUND;
+ case base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
+ return net::ERR_ACCESS_DENIED;
+ default:
+ return net::ERR_FAILED;
+ }
+}
+
// A helper class to open, verify and seek a file stream for a given path.
class LocalFileReader::OpenFileStreamHelper {
public:
@@ -173,7 +174,7 @@ int LocalFileReader::GetLength(const net::Int64CompletionCallback& callback) {
const bool posted = base::FileUtilProxy::GetFileInfo(
file_thread_proxy_, file_path_,
base::Bind(&DidGetFileInfoForGetLength, callback,
- expected_modification_time_, initial_offset_));
+ expected_modification_time_));
DCHECK(posted);
return net::ERR_IO_PENDING;
}
diff --git a/webkit/blob/local_file_reader.h b/webkit/blob/local_file_reader.h
index 2b2c67e..23abe7b 100644
--- a/webkit/blob/local_file_reader.h
+++ b/webkit/blob/local_file_reader.h
@@ -9,29 +9,28 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
+#include "base/platform_file.h"
#include "base/memory/weak_ptr.h"
#include "base/time.h"
-#include "net/base/completion_callback.h"
#include "webkit/blob/blob_export.h"
+#include "webkit/blob/file_reader.h"
namespace base {
class MessageLoopProxy;
}
-namespace net {
-class FileStream;
-class IOBuffer;
-}
-
namespace webkit_blob {
// A thin wrapper of net::FileStream with range support for sliced file
// handling.
-class BLOB_EXPORT LocalFileReader {
+class BLOB_EXPORT LocalFileReader : public FileReader {
public:
typedef base::Callback<void(int error, scoped_ptr<net::FileStream> stream)>
OpenFileStreamCallback;
+ // A convenient method to translate platform file error to net error code.
+ static int PlatformFileErrorToNetError(base::PlatformFileError file_error);
+
// Creates a new FileReader for a local file |file_path|.
// |initial_offset| specifies the offset in the file where the first read
// should start. If the given offset is out of the file range any
@@ -42,22 +41,20 @@ class BLOB_EXPORT LocalFileReader {
// actual modification time to see if the file has been modified, and if
// it does any succeeding read operations should fail with
// ERR_UPLOAD_FILE_CHANGED error.
+ // TODO(kinuko): Consider using SequencedWorkerPool.
LocalFileReader(base::MessageLoopProxy* file_thread_proxy,
const FilePath& file_path,
int64 initial_offset,
const base::Time& expected_modification_time);
+ virtual ~LocalFileReader();
- ~LocalFileReader();
-
- // Reads from the current cursor position asynchronously.
- // This works mostly same as how net::FileStream::Read() works except that
- // it internally opens (and seeks) the file if it is not opened yet.
- // It is invalid to call Read while there is an in-flight Read operation.
- int Read(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback);
+ // FileReader overrides.
+ virtual int Read(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) OVERRIDE;
- // Returns the number of bytes available to read from the beginning of
- // the file (or initial_offset) until the end of the file (rv >= 0 cases).
+ // Returns the length of the file if it could successfully retrieve the
+ // file info *and* its last modification time equals to
+ // expected_modification_time_ (rv >= 0 cases).
// Otherwise, a negative error code is returned (rv < 0 cases).
int GetLength(const net::Int64CompletionCallback& callback);
diff --git a/webkit/fileapi/file_system_file_reader.cc b/webkit/fileapi/file_system_file_reader.cc
new file mode 100644
index 0000000..c15a607
--- /dev/null
+++ b/webkit/fileapi/file_system_file_reader.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2012 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 "webkit/fileapi/file_system_file_reader.h"
+
+#include "base/file_util_proxy.h"
+#include "base/message_loop_proxy.h"
+#include "base/platform_file.h"
+#include "net/base/file_stream.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "webkit/blob/local_file_reader.h"
+#include "webkit/fileapi/file_system_context.h"
+#include "webkit/fileapi/file_system_operation_interface.h"
+
+using webkit_blob::LocalFileReader;
+
+namespace fileapi {
+
+namespace {
+
+void ReadAdapter(base::WeakPtr<FileSystemFileReader> reader,
+ net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) {
+ if (!reader.get())
+ return;
+ int rv = reader->Read(buf, buf_len, callback);
+ if (rv != net::ERR_IO_PENDING)
+ callback.Run(rv);
+}
+
+}
+
+FileSystemFileReader::FileSystemFileReader(
+ base::MessageLoopProxy* file_thread_proxy,
+ FileSystemContext* file_system_context,
+ const GURL& url,
+ int64 initial_offset)
+ : file_thread_proxy_(file_thread_proxy),
+ file_system_context_(file_system_context),
+ url_(url),
+ initial_offset_(initial_offset),
+ has_pending_create_snapshot_(false),
+ weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+FileSystemFileReader::~FileSystemFileReader() {
+}
+
+int FileSystemFileReader::Read(
+ net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) {
+ if (local_file_reader_.get())
+ return local_file_reader_->Read(buf, buf_len, callback);
+ DCHECK(!has_pending_create_snapshot_);
+ FileSystemOperationInterface* operation =
+ file_system_context_->CreateFileSystemOperation(
+ url_, file_thread_proxy_);
+ if (!operation)
+ return net::ERR_INVALID_URL;
+ has_pending_create_snapshot_ = true;
+ operation->CreateSnapshotFile(
+ url_,
+ base::Bind(&FileSystemFileReader::DidCreateSnapshot,
+ weak_factory_.GetWeakPtr(),
+ base::Bind(&ReadAdapter, weak_factory_.GetWeakPtr(),
+ make_scoped_refptr(buf), buf_len, callback),
+ callback));
+ return net::ERR_IO_PENDING;
+}
+
+void FileSystemFileReader::DidCreateSnapshot(
+ const base::Closure& read_closure,
+ const net::CompletionCallback& callback,
+ base::PlatformFileError file_error,
+ const base::PlatformFileInfo& file_info,
+ const FilePath& platform_path,
+ const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
+ DCHECK(has_pending_create_snapshot_);
+ DCHECK(!local_file_reader_.get());
+ has_pending_create_snapshot_ = false;
+
+ if (file_error != base::PLATFORM_FILE_OK) {
+ callback.Run(LocalFileReader::PlatformFileErrorToNetError(file_error));
+ return;
+ }
+
+ // Keep the reference (if it's non-null) so that the file won't go away.
+ snapshot_ref_ = file_ref;
+
+ local_file_reader_.reset(
+ new LocalFileReader(file_thread_proxy_,
+ platform_path,
+ initial_offset_,
+ base::Time()));
+
+ read_closure.Run();
+}
+
+} // namespace fileapi
diff --git a/webkit/fileapi/file_system_file_reader.h b/webkit/fileapi/file_system_file_reader.h
new file mode 100644
index 0000000..cc9a4f3
--- /dev/null
+++ b/webkit/fileapi/file_system_file_reader.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2012 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.
+
+#ifndef WEBKIT_FILEAPI_FILE_SYSTEM_FILE_READER_H_
+#define WEBKIT_FILEAPI_FILE_SYSTEM_FILE_READER_H_
+#pragma once
+
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/platform_file.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/blob/file_reader.h"
+
+class FilePath;
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace webkit_blob {
+class LocalFileReader;
+class ShareableFileReference;
+}
+
+namespace fileapi {
+
+class FileSystemContext;
+
+// TODO(kinaba,satorux): This generic implementation would work for any
+// filesystems but remote filesystem should implement its own reader
+// rather than relying on FileSystemOperation::GetSnapshotFile() which
+// may force downloading the entire contents for remote files.
+class FileSystemFileReader : public webkit_blob::FileReader {
+ public:
+ // Creates a new FileReader for a filesystem URL |url| form |initial_offset|.
+ FileSystemFileReader(base::MessageLoopProxy* file_thread_proxy,
+ FileSystemContext* file_system_context,
+ const GURL& url,
+ int64 initial_offset);
+ virtual ~FileSystemFileReader();
+
+ // FileReader override.
+ virtual int Read(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) OVERRIDE;
+
+ private:
+ void DidCreateSnapshot(
+ const base::Closure& read_closure,
+ const net::CompletionCallback& callback,
+ base::PlatformFileError file_error,
+ const base::PlatformFileInfo& file_info,
+ const FilePath& platform_path,
+ const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
+
+ scoped_refptr<base::MessageLoopProxy> file_thread_proxy_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ const GURL url_;
+ const int64 initial_offset_;
+ scoped_ptr<webkit_blob::LocalFileReader> local_file_reader_;
+ scoped_refptr<webkit_blob::ShareableFileReference> snapshot_ref_;
+ bool has_pending_create_snapshot_;
+ base::WeakPtrFactory<FileSystemFileReader> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemFileReader);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_FILE_SYSTEM_FILE_READER_H_
diff --git a/webkit/fileapi/file_system_url_request_job.cc b/webkit/fileapi/file_system_url_request_job.cc
index 420fee2..79b2491 100644
--- a/webkit/fileapi/file_system_url_request_job.cc
+++ b/webkit/fileapi/file_system_url_request_job.cc
@@ -4,6 +4,8 @@
#include "webkit/fileapi/file_system_url_request_job.h"
+#include <vector>
+
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
@@ -23,9 +25,8 @@
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
-#include "webkit/blob/local_file_reader.h"
-#include "webkit/blob/shareable_file_reference.h"
#include "webkit/fileapi/file_system_context.h"
+#include "webkit/fileapi/file_system_file_reader.h"
#include "webkit/fileapi/file_system_operation.h"
#include "webkit/fileapi/file_system_util.h"
@@ -73,8 +74,7 @@ void FileSystemURLRequestJob::Start() {
}
void FileSystemURLRequestJob::Kill() {
- if (reader_.get() != NULL)
- reader_.reset();
+ reader_.reset();
URLRequestJob::Kill();
weak_factory_.InvalidateWeakPtrs();
}
@@ -157,6 +157,7 @@ int FileSystemURLRequestJob::GetResponseCode() const {
void FileSystemURLRequestJob::StartAsync() {
if (!request_)
return;
+ DCHECK(!reader_.get());
FileSystemOperationInterface* operation =
file_system_context_->CreateFileSystemOperation(
request_->url(),
@@ -166,16 +167,16 @@ void FileSystemURLRequestJob::StartAsync() {
net::ERR_INVALID_URL));
return;
}
- operation->CreateSnapshotFile(
+ operation->GetMetadata(
request_->url(),
- base::Bind(&FileSystemURLRequestJob::DidCreateSnapshot, this));
+ base::Bind(&FileSystemURLRequestJob::DidGetMetadata,
+ weak_factory_.GetWeakPtr()));
}
-void FileSystemURLRequestJob::DidCreateSnapshot(
+void FileSystemURLRequestJob::DidGetMetadata(
base::PlatformFileError error_code,
const base::PlatformFileInfo& file_info,
- const FilePath& platform_path,
- const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
+ const FilePath& platform_path) {
if (error_code != base::PLATFORM_FILE_OK) {
NotifyFailed(error_code == base::PLATFORM_FILE_ERROR_INVALID_URL ?
net::ERR_INVALID_URL : net::ERR_FILE_NOT_FOUND);
@@ -188,9 +189,6 @@ void FileSystemURLRequestJob::DidCreateSnapshot(
is_directory_ = file_info.is_directory;
- // Keep the reference (if it's non-null) so that the file won't go away.
- snapshot_ref_ = file_ref;
-
if (!byte_range_.ComputeBounds(file_info.size)) {
NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
return;
@@ -206,10 +204,11 @@ void FileSystemURLRequestJob::DidCreateSnapshot(
DCHECK_GE(remaining_bytes_, 0);
DCHECK(!reader_.get());
- reader_.reset(new LocalFileReader(
- file_thread_proxy_, platform_path,
- byte_range_.first_byte_position(),
- base::Time()));
+ reader_.reset(new FileSystemFileReader(
+ file_thread_proxy_,
+ file_system_context_,
+ request_->url(),
+ byte_range_.first_byte_position()));
set_expected_content_size(remaining_bytes_);
response_info_.reset(new net::HttpResponseInfo());
diff --git a/webkit/fileapi/file_system_url_request_job.h b/webkit/fileapi/file_system_url_request_job.h
index f0f9a18..9541c31 100644
--- a/webkit/fileapi/file_system_url_request_job.h
+++ b/webkit/fileapi/file_system_url_request_job.h
@@ -19,13 +19,9 @@
class GURL;
class FilePath;
-namespace webkit_blob {
-class LocalFileReader;
-class ShareableFileReference;
-}
-
namespace fileapi {
class FileSystemContext;
+class FileSystemFileReader;
// A request job that handles reading filesystem: URLs
class FileSystemURLRequestJob : public net::URLRequestJob {
@@ -57,21 +53,17 @@ class FileSystemURLRequestJob : public net::URLRequestJob {
virtual ~FileSystemURLRequestJob();
void StartAsync();
- void DidCreateSnapshot(
+ void DidGetMetadata(
base::PlatformFileError error_code,
const base::PlatformFileInfo& file_info,
- const FilePath& platform_path,
- const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
- void DidOpen(base::PlatformFileError error_code,
- base::PassPlatformFile file, bool created);
+ const FilePath& platform_path);
void DidRead(int result);
void NotifyFailed(int rv);
FileSystemContext* file_system_context_;
scoped_refptr<base::MessageLoopProxy> file_thread_proxy_;
base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_;
- scoped_ptr<webkit_blob::LocalFileReader> reader_;
- scoped_refptr<webkit_blob::ShareableFileReference> snapshot_ref_;
+ scoped_ptr<FileSystemFileReader> reader_;
bool is_directory_;
scoped_ptr<net::HttpResponseInfo> response_info_;
int64 remaining_bytes_;
diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi
index 66485b4..51253e1 100644
--- a/webkit/fileapi/webkit_fileapi.gypi
+++ b/webkit/fileapi/webkit_fileapi.gypi
@@ -24,6 +24,8 @@
'file_system_dir_url_request_job.h',
'file_system_directory_database.cc',
'file_system_directory_database.h',
+ 'file_system_file_reader.cc',
+ 'file_system_file_reader.h',
'file_system_file_util.cc',
'file_system_file_util.h',
'file_system_file_util_proxy.cc',