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