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