Home | History | Annotate | Download | only in linux
      1 // Copyright 2013 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/media_galleries/linux/mtp_device_task_helper.h"
      6 
      7 #include "base/logging.h"
      8 #include "chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h"
      9 #include "chrome/browser/media_galleries/linux/mtp_read_file_worker.h"
     10 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
     11 #include "chrome/browser/storage_monitor/storage_monitor.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
     14 #include "third_party/cros_system_api/dbus/service_constants.h"
     15 #include "webkit/browser/fileapi/async_file_util.h"
     16 #include "webkit/common/fileapi/file_system_util.h"
     17 
     18 namespace {
     19 
     20 // Does nothing.
     21 // This method is used to handle the results of
     22 // MediaTransferProtocolManager::CloseStorage method call.
     23 void DoNothing(bool error) {
     24 }
     25 
     26 device::MediaTransferProtocolManager* GetMediaTransferProtocolManager() {
     27   return StorageMonitor::GetInstance()->media_transfer_protocol_manager();
     28 }
     29 
     30 }  // namespace
     31 
     32 MTPDeviceTaskHelper::MTPDeviceTaskHelper()
     33     : weak_ptr_factory_(this) {
     34   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     35 }
     36 
     37 MTPDeviceTaskHelper::~MTPDeviceTaskHelper() {
     38   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     39 }
     40 
     41 void MTPDeviceTaskHelper::OpenStorage(const std::string& storage_name,
     42                                       const OpenStorageCallback& callback) {
     43   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     44   DCHECK(!storage_name.empty());
     45   if (!device_handle_.empty()) {
     46     content::BrowserThread::PostTask(content::BrowserThread::IO,
     47                                      FROM_HERE,
     48                                      base::Bind(callback, true));
     49     return;
     50   }
     51   GetMediaTransferProtocolManager()->OpenStorage(
     52       storage_name, mtpd::kReadOnlyMode,
     53       base::Bind(&MTPDeviceTaskHelper::OnDidOpenStorage,
     54                  weak_ptr_factory_.GetWeakPtr(),
     55                  callback));
     56 }
     57 
     58 void MTPDeviceTaskHelper::GetFileInfoByPath(
     59     const std::string& file_path,
     60     const GetFileInfoSuccessCallback& success_callback,
     61     const ErrorCallback& error_callback) {
     62   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     63   if (device_handle_.empty())
     64     return HandleDeviceError(error_callback, base::PLATFORM_FILE_ERROR_FAILED);
     65 
     66   GetMediaTransferProtocolManager()->GetFileInfoByPath(
     67       device_handle_, file_path,
     68       base::Bind(&MTPDeviceTaskHelper::OnGetFileInfo,
     69                  weak_ptr_factory_.GetWeakPtr(),
     70                  success_callback,
     71                  error_callback));
     72 }
     73 
     74 void MTPDeviceTaskHelper::ReadDirectoryByPath(
     75     const std::string& dir_path,
     76     const ReadDirectorySuccessCallback& success_callback,
     77     const ErrorCallback& error_callback) {
     78   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     79   if (device_handle_.empty())
     80     return HandleDeviceError(error_callback, base::PLATFORM_FILE_ERROR_FAILED);
     81 
     82   GetMediaTransferProtocolManager()->ReadDirectoryByPath(
     83       device_handle_, dir_path,
     84       base::Bind(&MTPDeviceTaskHelper::OnDidReadDirectoryByPath,
     85                  weak_ptr_factory_.GetWeakPtr(),
     86                  success_callback,
     87                  error_callback));
     88 }
     89 
     90 void MTPDeviceTaskHelper::WriteDataIntoSnapshotFile(
     91     const SnapshotRequestInfo& request_info,
     92     const base::PlatformFileInfo& snapshot_file_info) {
     93   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     94   if (device_handle_.empty()) {
     95     return HandleDeviceError(request_info.error_callback,
     96                              base::PLATFORM_FILE_ERROR_FAILED);
     97   }
     98 
     99   if (!read_file_worker_)
    100     read_file_worker_.reset(new MTPReadFileWorker(device_handle_));
    101   read_file_worker_->WriteDataIntoSnapshotFile(request_info,
    102                                                snapshot_file_info);
    103 }
    104 
    105 void MTPDeviceTaskHelper::CloseStorage() const {
    106   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    107   if (device_handle_.empty())
    108     return;
    109   GetMediaTransferProtocolManager()->CloseStorage(device_handle_,
    110                                                   base::Bind(&DoNothing));
    111 }
    112 
    113 void MTPDeviceTaskHelper::OnDidOpenStorage(
    114     const OpenStorageCallback& completion_callback,
    115     const std::string& device_handle,
    116     bool error) {
    117   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    118   device_handle_ = device_handle;
    119   content::BrowserThread::PostTask(content::BrowserThread::IO,
    120                                    FROM_HERE,
    121                                    base::Bind(completion_callback, !error));
    122 }
    123 
    124 void MTPDeviceTaskHelper::OnGetFileInfo(
    125     const GetFileInfoSuccessCallback& success_callback,
    126     const ErrorCallback& error_callback,
    127     const MtpFileEntry& file_entry,
    128     bool error) const {
    129   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    130   if (error) {
    131     return HandleDeviceError(error_callback,
    132                              base::PLATFORM_FILE_ERROR_NOT_FOUND);
    133   }
    134 
    135   base::PlatformFileInfo file_entry_info;
    136   file_entry_info.size = file_entry.file_size();
    137   file_entry_info.is_directory =
    138       file_entry.file_type() == MtpFileEntry::FILE_TYPE_FOLDER;
    139   file_entry_info.is_symbolic_link = false;
    140   file_entry_info.last_modified =
    141       base::Time::FromTimeT(file_entry.modification_time());
    142   file_entry_info.last_accessed = file_entry_info.last_modified;
    143   file_entry_info.creation_time = base::Time();
    144   content::BrowserThread::PostTask(content::BrowserThread::IO,
    145                                    FROM_HERE,
    146                                    base::Bind(success_callback,
    147                                               file_entry_info));
    148 }
    149 
    150 void MTPDeviceTaskHelper::OnDidReadDirectoryByPath(
    151     const ReadDirectorySuccessCallback& success_callback,
    152     const ErrorCallback& error_callback,
    153     const std::vector<MtpFileEntry>& file_entries,
    154     bool error) const {
    155   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    156   if (error)
    157     return HandleDeviceError(error_callback, base::PLATFORM_FILE_ERROR_FAILED);
    158 
    159   fileapi::AsyncFileUtil::EntryList entries;
    160   base::FilePath current;
    161   MTPDeviceObjectEnumerator file_enum(file_entries);
    162   while (!(current = file_enum.Next()).empty()) {
    163     fileapi::DirectoryEntry entry;
    164     entry.name = fileapi::VirtualPath::BaseName(current).value();
    165     entry.is_directory = file_enum.IsDirectory();
    166     entry.size = file_enum.Size();
    167     entry.last_modified_time = file_enum.LastModifiedTime();
    168     entries.push_back(entry);
    169   }
    170   content::BrowserThread::PostTask(content::BrowserThread::IO,
    171                                    FROM_HERE,
    172                                    base::Bind(success_callback, entries));
    173 }
    174 
    175 void MTPDeviceTaskHelper::HandleDeviceError(
    176     const ErrorCallback& error_callback,
    177     base::PlatformFileError error) const {
    178   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    179   content::BrowserThread::PostTask(content::BrowserThread::IO,
    180                                    FROM_HERE,
    181                                    base::Bind(error_callback, error));
    182 }
    183