Home | History | Annotate | Download | only in file_system_provider
      1 // Copyright 2014 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 "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/debug/trace_event.h"
     10 #include "base/files/file.h"
     11 #include "chrome/browser/chromeos/file_system_provider/notification_manager.h"
     12 #include "chrome/browser/chromeos/file_system_provider/operations/abort.h"
     13 #include "chrome/browser/chromeos/file_system_provider/operations/close_file.h"
     14 #include "chrome/browser/chromeos/file_system_provider/operations/copy_entry.h"
     15 #include "chrome/browser/chromeos/file_system_provider/operations/create_directory.h"
     16 #include "chrome/browser/chromeos/file_system_provider/operations/create_file.h"
     17 #include "chrome/browser/chromeos/file_system_provider/operations/delete_entry.h"
     18 #include "chrome/browser/chromeos/file_system_provider/operations/get_metadata.h"
     19 #include "chrome/browser/chromeos/file_system_provider/operations/move_entry.h"
     20 #include "chrome/browser/chromeos/file_system_provider/operations/open_file.h"
     21 #include "chrome/browser/chromeos/file_system_provider/operations/read_directory.h"
     22 #include "chrome/browser/chromeos/file_system_provider/operations/read_file.h"
     23 #include "chrome/browser/chromeos/file_system_provider/operations/truncate.h"
     24 #include "chrome/browser/chromeos/file_system_provider/operations/unmount.h"
     25 #include "chrome/browser/chromeos/file_system_provider/operations/write_file.h"
     26 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
     27 #include "chrome/browser/profiles/profile.h"
     28 #include "chrome/common/extensions/api/file_system_provider.h"
     29 #include "extensions/browser/event_router.h"
     30 
     31 namespace net {
     32 class IOBuffer;
     33 }  // namespace net
     34 
     35 namespace chromeos {
     36 namespace file_system_provider {
     37 namespace {
     38 
     39 // Dicards the result of Abort() when called from the destructor.
     40 void EmptyStatusCallback(base::File::Error /* result */) {
     41 }
     42 
     43 }  // namespace
     44 
     45 ProvidedFileSystem::ProvidedFileSystem(
     46     Profile* profile,
     47     const ProvidedFileSystemInfo& file_system_info)
     48     : profile_(profile),
     49       event_router_(extensions::EventRouter::Get(profile)),  // May be NULL.
     50       file_system_info_(file_system_info),
     51       notification_manager_(
     52           new NotificationManager(profile_, file_system_info_)),
     53       request_manager_(notification_manager_.get()),
     54       weak_ptr_factory_(this) {
     55 }
     56 
     57 ProvidedFileSystem::~ProvidedFileSystem() {
     58   const std::vector<int> request_ids = request_manager_.GetActiveRequestIds();
     59   for (size_t i = 0; i < request_ids.size(); ++i) {
     60     Abort(request_ids[i], base::Bind(&EmptyStatusCallback));
     61   }
     62 }
     63 
     64 ProvidedFileSystem::AbortCallback ProvidedFileSystem::RequestUnmount(
     65     const storage::AsyncFileUtil::StatusCallback& callback) {
     66   const int request_id = request_manager_.CreateRequest(
     67       REQUEST_UNMOUNT,
     68       scoped_ptr<RequestManager::HandlerInterface>(
     69           new operations::Unmount(event_router_, file_system_info_, callback)));
     70   if (!request_id) {
     71     callback.Run(base::File::FILE_ERROR_SECURITY);
     72     return AbortCallback();
     73   }
     74 
     75   return base::Bind(
     76       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
     77 }
     78 
     79 ProvidedFileSystem::AbortCallback ProvidedFileSystem::GetMetadata(
     80     const base::FilePath& entry_path,
     81     MetadataFieldMask fields,
     82     const GetMetadataCallback& callback) {
     83   const int request_id = request_manager_.CreateRequest(
     84       GET_METADATA,
     85       scoped_ptr<RequestManager::HandlerInterface>(new operations::GetMetadata(
     86           event_router_, file_system_info_, entry_path, fields, callback)));
     87   if (!request_id) {
     88     callback.Run(make_scoped_ptr<EntryMetadata>(NULL),
     89                  base::File::FILE_ERROR_SECURITY);
     90     return AbortCallback();
     91   }
     92 
     93   return base::Bind(
     94       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
     95 }
     96 
     97 ProvidedFileSystem::AbortCallback ProvidedFileSystem::ReadDirectory(
     98     const base::FilePath& directory_path,
     99     const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
    100   const int request_id = request_manager_.CreateRequest(
    101       READ_DIRECTORY,
    102       scoped_ptr<RequestManager::HandlerInterface>(
    103           new operations::ReadDirectory(
    104               event_router_, file_system_info_, directory_path, callback)));
    105   if (!request_id) {
    106     callback.Run(base::File::FILE_ERROR_SECURITY,
    107                  storage::AsyncFileUtil::EntryList(),
    108                  false /* has_more */);
    109     return AbortCallback();
    110   }
    111 
    112   return base::Bind(
    113       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    114 }
    115 
    116 ProvidedFileSystem::AbortCallback ProvidedFileSystem::ReadFile(
    117     int file_handle,
    118     net::IOBuffer* buffer,
    119     int64 offset,
    120     int length,
    121     const ReadChunkReceivedCallback& callback) {
    122   TRACE_EVENT1(
    123       "file_system_provider", "ProvidedFileSystem::ReadFile", "length", length);
    124   const int request_id = request_manager_.CreateRequest(
    125       READ_FILE,
    126       make_scoped_ptr<RequestManager::HandlerInterface>(
    127           new operations::ReadFile(event_router_,
    128                                    file_system_info_,
    129                                    file_handle,
    130                                    buffer,
    131                                    offset,
    132                                    length,
    133                                    callback)));
    134   if (!request_id) {
    135     callback.Run(0 /* chunk_length */,
    136                  false /* has_more */,
    137                  base::File::FILE_ERROR_SECURITY);
    138     return AbortCallback();
    139   }
    140 
    141   return base::Bind(
    142       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    143 }
    144 
    145 ProvidedFileSystem::AbortCallback ProvidedFileSystem::OpenFile(
    146     const base::FilePath& file_path,
    147     OpenFileMode mode,
    148     const OpenFileCallback& callback) {
    149   const int request_id = request_manager_.CreateRequest(
    150       OPEN_FILE,
    151       scoped_ptr<RequestManager::HandlerInterface>(new operations::OpenFile(
    152           event_router_, file_system_info_, file_path, mode, callback)));
    153   if (!request_id) {
    154     callback.Run(0 /* file_handle */, base::File::FILE_ERROR_SECURITY);
    155     return AbortCallback();
    156   }
    157 
    158   return base::Bind(
    159       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    160 }
    161 
    162 ProvidedFileSystem::AbortCallback ProvidedFileSystem::CloseFile(
    163     int file_handle,
    164     const storage::AsyncFileUtil::StatusCallback& callback) {
    165   const int request_id = request_manager_.CreateRequest(
    166       CLOSE_FILE,
    167       scoped_ptr<RequestManager::HandlerInterface>(new operations::CloseFile(
    168           event_router_, file_system_info_, file_handle, callback)));
    169   if (!request_id) {
    170     callback.Run(base::File::FILE_ERROR_SECURITY);
    171     return AbortCallback();
    172   }
    173 
    174   return base::Bind(
    175       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    176 }
    177 
    178 ProvidedFileSystem::AbortCallback ProvidedFileSystem::CreateDirectory(
    179     const base::FilePath& directory_path,
    180     bool recursive,
    181     const storage::AsyncFileUtil::StatusCallback& callback) {
    182   const int request_id = request_manager_.CreateRequest(
    183       CREATE_DIRECTORY,
    184       scoped_ptr<RequestManager::HandlerInterface>(
    185           new operations::CreateDirectory(event_router_,
    186                                           file_system_info_,
    187                                           directory_path,
    188                                           recursive,
    189                                           callback)));
    190   if (!request_id) {
    191     callback.Run(base::File::FILE_ERROR_SECURITY);
    192     return AbortCallback();
    193   }
    194 
    195   return base::Bind(
    196       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    197 }
    198 
    199 ProvidedFileSystem::AbortCallback ProvidedFileSystem::DeleteEntry(
    200     const base::FilePath& entry_path,
    201     bool recursive,
    202     const storage::AsyncFileUtil::StatusCallback& callback) {
    203   const int request_id = request_manager_.CreateRequest(
    204       DELETE_ENTRY,
    205       scoped_ptr<RequestManager::HandlerInterface>(new operations::DeleteEntry(
    206           event_router_, file_system_info_, entry_path, recursive, callback)));
    207   if (!request_id) {
    208     callback.Run(base::File::FILE_ERROR_SECURITY);
    209     return AbortCallback();
    210   }
    211 
    212   return base::Bind(
    213       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    214 }
    215 
    216 ProvidedFileSystem::AbortCallback ProvidedFileSystem::CreateFile(
    217     const base::FilePath& file_path,
    218     const storage::AsyncFileUtil::StatusCallback& callback) {
    219   const int request_id = request_manager_.CreateRequest(
    220       CREATE_FILE,
    221       scoped_ptr<RequestManager::HandlerInterface>(new operations::CreateFile(
    222           event_router_, file_system_info_, file_path, callback)));
    223   if (!request_id) {
    224     callback.Run(base::File::FILE_ERROR_SECURITY);
    225     return AbortCallback();
    226   }
    227 
    228   return base::Bind(
    229       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    230 }
    231 
    232 ProvidedFileSystem::AbortCallback ProvidedFileSystem::CopyEntry(
    233     const base::FilePath& source_path,
    234     const base::FilePath& target_path,
    235     const storage::AsyncFileUtil::StatusCallback& callback) {
    236   const int request_id = request_manager_.CreateRequest(
    237       COPY_ENTRY,
    238       scoped_ptr<RequestManager::HandlerInterface>(
    239           new operations::CopyEntry(event_router_,
    240                                     file_system_info_,
    241                                     source_path,
    242                                     target_path,
    243                                     callback)));
    244   if (!request_id) {
    245     callback.Run(base::File::FILE_ERROR_SECURITY);
    246     return AbortCallback();
    247   }
    248 
    249   return base::Bind(
    250       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    251 }
    252 
    253 ProvidedFileSystem::AbortCallback ProvidedFileSystem::WriteFile(
    254     int file_handle,
    255     net::IOBuffer* buffer,
    256     int64 offset,
    257     int length,
    258     const storage::AsyncFileUtil::StatusCallback& callback) {
    259   TRACE_EVENT1("file_system_provider",
    260                "ProvidedFileSystem::WriteFile",
    261                "length",
    262                length);
    263   const int request_id = request_manager_.CreateRequest(
    264       WRITE_FILE,
    265       make_scoped_ptr<RequestManager::HandlerInterface>(
    266           new operations::WriteFile(event_router_,
    267                                     file_system_info_,
    268                                     file_handle,
    269                                     make_scoped_refptr(buffer),
    270                                     offset,
    271                                     length,
    272                                     callback)));
    273   if (!request_id) {
    274     callback.Run(base::File::FILE_ERROR_SECURITY);
    275     return AbortCallback();
    276   }
    277 
    278   return base::Bind(
    279       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    280 }
    281 
    282 ProvidedFileSystem::AbortCallback ProvidedFileSystem::MoveEntry(
    283     const base::FilePath& source_path,
    284     const base::FilePath& target_path,
    285     const storage::AsyncFileUtil::StatusCallback& callback) {
    286   const int request_id = request_manager_.CreateRequest(
    287       MOVE_ENTRY,
    288       scoped_ptr<RequestManager::HandlerInterface>(
    289           new operations::MoveEntry(event_router_,
    290                                     file_system_info_,
    291                                     source_path,
    292                                     target_path,
    293                                     callback)));
    294   if (!request_id) {
    295     callback.Run(base::File::FILE_ERROR_SECURITY);
    296     return AbortCallback();
    297   }
    298 
    299   return base::Bind(
    300       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    301 }
    302 
    303 ProvidedFileSystem::AbortCallback ProvidedFileSystem::Truncate(
    304     const base::FilePath& file_path,
    305     int64 length,
    306     const storage::AsyncFileUtil::StatusCallback& callback) {
    307   const int request_id = request_manager_.CreateRequest(
    308       TRUNCATE,
    309       scoped_ptr<RequestManager::HandlerInterface>(new operations::Truncate(
    310           event_router_, file_system_info_, file_path, length, callback)));
    311   if (!request_id) {
    312     callback.Run(base::File::FILE_ERROR_SECURITY);
    313     return AbortCallback();
    314   }
    315 
    316   return base::Bind(
    317       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
    318 }
    319 
    320 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
    321   return file_system_info_;
    322 }
    323 
    324 RequestManager* ProvidedFileSystem::GetRequestManager() {
    325   return &request_manager_;
    326 }
    327 
    328 base::WeakPtr<ProvidedFileSystemInterface> ProvidedFileSystem::GetWeakPtr() {
    329   return weak_ptr_factory_.GetWeakPtr();
    330 }
    331 
    332 void ProvidedFileSystem::Abort(
    333     int operation_request_id,
    334     const storage::AsyncFileUtil::StatusCallback& callback) {
    335   request_manager_.RejectRequest(operation_request_id,
    336                                  make_scoped_ptr(new RequestValue()),
    337                                  base::File::FILE_ERROR_ABORT);
    338   if (!request_manager_.CreateRequest(
    339           ABORT,
    340           scoped_ptr<RequestManager::HandlerInterface>(
    341               new operations::Abort(event_router_,
    342                                     file_system_info_,
    343                                     operation_request_id,
    344                                     callback)))) {
    345     callback.Run(base::File::FILE_ERROR_SECURITY);
    346   }
    347 }
    348 
    349 }  // namespace file_system_provider
    350 }  // namespace chromeos
    351