• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "webkit/browser/fileapi/file_system_file_stream_reader.h"
6 
7 #include "base/files/file_util_proxy.h"
8 #include "base/single_thread_task_runner.h"
9 #include "net/base/file_stream.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12 #include "webkit/browser/blob/file_stream_reader.h"
13 #include "webkit/browser/fileapi/file_system_context.h"
14 #include "webkit/browser/fileapi/file_system_operation_runner.h"
15 
16 using webkit_blob::FileStreamReader;
17 
18 // TODO(kinuko): Remove this temporary namespace hack after we move both
19 // blob and fileapi into content namespace.
20 namespace webkit_blob {
21 
CreateForFileSystemFile(fileapi::FileSystemContext * file_system_context,const fileapi::FileSystemURL & url,int64 initial_offset,const base::Time & expected_modification_time)22 FileStreamReader* FileStreamReader::CreateForFileSystemFile(
23     fileapi::FileSystemContext* file_system_context,
24     const fileapi::FileSystemURL& url,
25     int64 initial_offset,
26     const base::Time& expected_modification_time) {
27   return new fileapi::FileSystemFileStreamReader(
28       file_system_context,
29       url,
30       initial_offset,
31       expected_modification_time);
32 }
33 
34 }  // namespace webkit_blob
35 
36 namespace fileapi {
37 
38 namespace {
39 
ReadAdapter(base::WeakPtr<FileSystemFileStreamReader> reader,net::IOBuffer * buf,int buf_len,const net::CompletionCallback & callback)40 void ReadAdapter(base::WeakPtr<FileSystemFileStreamReader> reader,
41                  net::IOBuffer* buf, int buf_len,
42                  const net::CompletionCallback& callback) {
43   if (!reader.get())
44     return;
45   int rv = reader->Read(buf, buf_len, callback);
46   if (rv != net::ERR_IO_PENDING)
47     callback.Run(rv);
48 }
49 
GetLengthAdapter(base::WeakPtr<FileSystemFileStreamReader> reader,const net::Int64CompletionCallback & callback)50 void GetLengthAdapter(base::WeakPtr<FileSystemFileStreamReader> reader,
51                       const net::Int64CompletionCallback& callback) {
52   if (!reader.get())
53     return;
54   int rv = reader->GetLength(callback);
55   if (rv != net::ERR_IO_PENDING)
56     callback.Run(rv);
57 }
58 
Int64CallbackAdapter(const net::Int64CompletionCallback & callback,int value)59 void Int64CallbackAdapter(const net::Int64CompletionCallback& callback,
60                           int value) {
61   callback.Run(value);
62 }
63 
64 }  // namespace
65 
~FileSystemFileStreamReader()66 FileSystemFileStreamReader::~FileSystemFileStreamReader() {
67 }
68 
Read(net::IOBuffer * buf,int buf_len,const net::CompletionCallback & callback)69 int FileSystemFileStreamReader::Read(
70     net::IOBuffer* buf, int buf_len,
71     const net::CompletionCallback& callback) {
72   if (local_file_reader_)
73     return local_file_reader_->Read(buf, buf_len, callback);
74   return CreateSnapshot(
75       base::Bind(&ReadAdapter, weak_factory_.GetWeakPtr(),
76                  make_scoped_refptr(buf), buf_len, callback),
77       callback);
78 }
79 
GetLength(const net::Int64CompletionCallback & callback)80 int64 FileSystemFileStreamReader::GetLength(
81     const net::Int64CompletionCallback& callback) {
82   if (local_file_reader_)
83     return local_file_reader_->GetLength(callback);
84   return CreateSnapshot(
85       base::Bind(&GetLengthAdapter, weak_factory_.GetWeakPtr(), callback),
86       base::Bind(&Int64CallbackAdapter, callback));
87 }
88 
FileSystemFileStreamReader(FileSystemContext * file_system_context,const FileSystemURL & url,int64 initial_offset,const base::Time & expected_modification_time)89 FileSystemFileStreamReader::FileSystemFileStreamReader(
90     FileSystemContext* file_system_context,
91     const FileSystemURL& url,
92     int64 initial_offset,
93     const base::Time& expected_modification_time)
94     : file_system_context_(file_system_context),
95       url_(url),
96       initial_offset_(initial_offset),
97       expected_modification_time_(expected_modification_time),
98       has_pending_create_snapshot_(false),
99       weak_factory_(this) {
100 }
101 
CreateSnapshot(const base::Closure & callback,const net::CompletionCallback & error_callback)102 int FileSystemFileStreamReader::CreateSnapshot(
103     const base::Closure& callback,
104     const net::CompletionCallback& error_callback) {
105   DCHECK(!has_pending_create_snapshot_);
106   has_pending_create_snapshot_ = true;
107   file_system_context_->operation_runner()->CreateSnapshotFile(
108       url_,
109       base::Bind(&FileSystemFileStreamReader::DidCreateSnapshot,
110                  weak_factory_.GetWeakPtr(),
111                  callback,
112                  error_callback));
113   return net::ERR_IO_PENDING;
114 }
115 
DidCreateSnapshot(const base::Closure & callback,const net::CompletionCallback & error_callback,base::File::Error file_error,const base::File::Info & file_info,const base::FilePath & platform_path,const scoped_refptr<webkit_blob::ShareableFileReference> & file_ref)116 void FileSystemFileStreamReader::DidCreateSnapshot(
117     const base::Closure& callback,
118     const net::CompletionCallback& error_callback,
119     base::File::Error file_error,
120     const base::File::Info& file_info,
121     const base::FilePath& platform_path,
122     const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
123   DCHECK(has_pending_create_snapshot_);
124   DCHECK(!local_file_reader_.get());
125   has_pending_create_snapshot_ = false;
126 
127   if (file_error != base::File::FILE_OK) {
128     error_callback.Run(net::FileErrorToNetError(file_error));
129     return;
130   }
131 
132   // Keep the reference (if it's non-null) so that the file won't go away.
133   snapshot_ref_ = file_ref;
134 
135   local_file_reader_.reset(
136       FileStreamReader::CreateForLocalFile(
137           file_system_context_->default_file_task_runner(),
138           platform_path, initial_offset_, expected_modification_time_));
139 
140   callback.Run();
141 }
142 
143 }  // namespace fileapi
144