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