Home | History | Annotate | Download | only in fileapi
      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 
     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 
     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 
     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 
     59 void Int64CallbackAdapter(const net::Int64CompletionCallback& callback,
     60                           int value) {
     61   callback.Run(value);
     62 }
     63 
     64 }  // namespace
     65 
     66 FileSystemFileStreamReader::~FileSystemFileStreamReader() {
     67 }
     68 
     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 
     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 
     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 
    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 
    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