mtp_device_delegate_impl_linux.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/string_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chrome {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// File path separator constant.
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kRootPath[] = "/";
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the device relative file path given |file_path|.
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path|
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is "/usb:2,2:12345", this function returns the device relative path which is
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// "/DCIM".
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GetDeviceRelativePath(const base::FilePath& registered_dev_path,
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const base::FilePath& file_path) {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!registered_dev_path.empty());
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!file_path.empty());
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (registered_dev_path == file_path)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kRootPath;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath relative_path;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!registered_dev_path.AppendRelativePath(file_path, &relative_path))
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return std::string();
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!relative_path.empty());
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return relative_path.value();
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the MTPDeviceTaskHelper object associated with the MTP device
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// storage.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns NULL if the |storage_name| is no longer valid (e.g. because the
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// corresponding storage device is detached, etc).
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceTaskHelper* GetDeviceTaskHelperForStorage(
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return MTPDeviceTaskHelperMapService::GetInstance()->GetDeviceTaskHelper(
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      storage_name);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Opens the storage device for communication.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |reply_callback| is called when the OpenStorage request completes.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |reply_callback| runs on the IO thread.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OpenStorageOnUIThread(
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Callback<void(bool)>& reply_callback) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper) {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    task_helper =
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper(
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            storage_name);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->OpenStorage(storage_name, reply_callback);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Enumerates the |root| directory file entries.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| is called when the ReadDirectory request succeeds.
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |error_callback| is called when the ReadDirectory request fails.
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| and |error_callback| runs on the IO thread.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReadDirectoryOnUIThread(
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& root,
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Callback<
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        void(const fileapi::AsyncFileUtil::EntryList&)>& success_callback,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Callback<void(base::PlatformFileError)>& error_callback) {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->ReadDirectoryByPath(root, success_callback, error_callback);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Gets the |file_path| details.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| is called when the GetFileInfo request succeeds.
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |error_callback| is called when the GetFileInfo request fails.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| and |error_callback| runs on the IO thread.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetFileInfoOnUIThread(
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& file_path,
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Callback<void(const base::PlatformFileInfo&)>& success_callback,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Callback<void(base::PlatformFileError)>& error_callback) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->GetFileInfoByPath(file_path, success_callback, error_callback);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copies the contents of |device_file_path| to |snapshot_file_path|.
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |device_file_path| specifies the media device file path.
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |snapshot_file_path| specifies the platform path of the snapshot file.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |file_size| specifies the number of bytes that will be written to the
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// snapshot file.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| is called when the copy operation succeeds.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |error_callback| is called when the copy operation fails.
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| and |error_callback| runs on the IO thread.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WriteDataIntoSnapshotFileOnUIThread(
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SnapshotRequestInfo& request_info,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::PlatformFileInfo& snapshot_file_info) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->WriteDataIntoSnapshotFile(request_info, snapshot_file_info);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Closes the device storage specified by the |storage_name| and destroys the
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MTPDeviceTaskHelper object associated with the device storage.
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CloseStorageAndDestroyTaskHelperOnUIThread(
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->CloseStorage();
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper(
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      storage_name);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo(
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const tracked_objects::Location& location,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& task)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : location(location),
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      task(task) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux(
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_location)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : init_state_(UNINITIALIZED),
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      task_in_progress_(false),
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      device_path_(device_location),
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!device_path_.empty());
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RemoveChars(device_location, kRootPath, &storage_name_);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!storage_name_.empty());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::GetFileInfo(
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& file_path,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GetFileInfoSuccessCallback& success_callback,
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!file_path.empty());
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure call_closure =
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&GetFileInfoOnUIThread,
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 storage_name_,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 GetDeviceRelativePath(device_path_, file_path),
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            success_callback),
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            error_callback));
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure));
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::ReadDirectory(
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& root,
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!root.empty());
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string device_file_relative_path = GetDeviceRelativePath(device_path_,
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                                root);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure call_closure =
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &GetFileInfoOnUIThread,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          storage_name_,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          device_file_relative_path,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              weak_ptr_factory_.GetWeakPtr(),
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              device_file_relative_path,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              success_callback,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              error_callback),
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     error_callback));
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure));
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::CreateSnapshotFile(
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& device_file_path,
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& snapshot_file_path,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CreateSnapshotFileSuccessCallback& success_callback,
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!device_file_path.empty());
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!snapshot_file_path.empty());
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string device_file_relative_path =
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceRelativePath(device_path_, device_file_path);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SnapshotRequestInfo> request_info(
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new SnapshotRequestInfo(device_file_relative_path,
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              snapshot_file_path,
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              success_callback,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              error_callback));
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure call_closure =
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &GetFileInfoOnUIThread,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          storage_name_,
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          device_file_relative_path,
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              weak_ptr_factory_.GetWeakPtr(),
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              base::Passed(&request_info)),
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     error_callback));
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure));
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object.
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::BrowserThread::UI,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_));
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete this;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask(
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PendingTaskInfo& task_info) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((init_state_ == INITIALIZED) && !task_in_progress_) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    task_in_progress_ = true;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::BrowserThread::PostTask(content::BrowserThread::UI,
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     task_info.location,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     task_info.task);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_tasks_.push(task_info);
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (init_state_ == UNINITIALIZED) {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    init_state_ = PENDING_INIT;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    task_in_progress_ = true;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::BrowserThread::PostTask(
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::BrowserThread::UI,
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&OpenStorageOnUIThread,
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   storage_name_,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              weak_ptr_factory_.GetWeakPtr())));
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile(
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::PlatformFileInfo& file_info) {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(file_info.size, 0);
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = true;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SnapshotRequestInfo request_info(
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_snapshot_request_info_->device_file_path,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_snapshot_request_info_->snapshot_file_path,
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile,
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()),
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError,
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()));
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread,
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          storage_name_,
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          request_info,
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          file_info);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   FROM_HERE,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_closure);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::ProcessNextPendingRequest() {
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!task_in_progress_);
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_tasks_.empty())
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = true;
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const PendingTaskInfo& task_info = pending_tasks_.front();
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_info.location,
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_info.task);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_tasks_.pop();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnInitCompleted(bool succeeded) {
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  init_state_ = succeeded ? INITIALIZED : UNINITIALIZED;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = false;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessNextPendingRequest();
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfo(
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GetFileInfoSuccessCallback& success_callback,
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::PlatformFileInfo& file_info) {
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  success_callback.Run(file_info);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = false;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessNextPendingRequest();
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory(
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& root,
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::PlatformFileInfo& file_info) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!file_info.is_directory) {
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HandleDeviceFileError(error_callback,
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure task_closure =
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ReadDirectoryOnUIThread,
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 storage_name_,
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 root,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            success_callback),
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            error_callback));
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   FROM_HERE,
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_closure);
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile(
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<SnapshotRequestInfo> snapshot_request_info,
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::PlatformFileInfo& file_info) {
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!current_snapshot_request_info_.get());
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(snapshot_request_info.get());
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::PlatformFileError error = base::PLATFORM_FILE_OK;
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_info.is_directory)
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error = base::PLATFORM_FILE_ERROR_NOT_A_FILE;
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (file_info.size < 0 || file_info.size > kuint32max)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error = base::PLATFORM_FILE_ERROR_FAILED;
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (error != base::PLATFORM_FILE_OK)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HandleDeviceFileError(snapshot_request_info->error_callback, error);
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::PlatformFileInfo snapshot_file_info(file_info);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Modify the last modified time to null. This prevents the time stamp
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // verfication in LocalFileStreamReader.
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  snapshot_file_info.last_modified = base::Time();
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset(snapshot_request_info.release());
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_info.size == 0) {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Empty snapshot file.
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OnDidWriteDataIntoSnapshotFile(
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        snapshot_file_info, current_snapshot_request_info_->snapshot_file_path);
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WriteDataIntoSnapshotFile(snapshot_file_info);
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidReadDirectory(
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const fileapi::AsyncFileUtil::EntryList& file_list) {
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  success_callback.Run(file_list, false /*no more entries*/);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = false;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessNextPendingRequest();
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile(
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::PlatformFileInfo& file_info,
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& snapshot_file_path) {
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_->success_callback.Run(
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      file_info, snapshot_file_path);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = false;
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset();
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessNextPendingRequest();
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError(
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PlatformFileError error) {
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_->error_callback.Run(error);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = false;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset();
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessNextPendingRequest();
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::HandleDeviceFileError(
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PlatformFileError error) {
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error_callback.Run(error);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_in_progress_ = false;
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessNextPendingRequest();
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CreateMTPDeviceAsyncDelegate(
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_location,
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CreateMTPDeviceAsyncDelegateCallback& callback) {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(new MTPDeviceDelegateImplLinux(device_location));
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chrome
462