mtp_device_delegate_impl_linux.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <algorithm>
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <vector>
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/numerics/safe_conversions.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/string_number_conversions.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/string_split.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/io_buffer.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/cros_system_api/dbus/service_constants.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// File path separator constant.
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kRootPath[] = "/";
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the device relative file path given |file_path|.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path|
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is "/usb:2,2:12345", this function returns the device relative path which is
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// "DCIM".
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// In the special case when |registered_dev_path| and |file_path| are the same,
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// return |kRootPath|.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GetDeviceRelativePath(const base::FilePath& registered_dev_path,
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const base::FilePath& file_path) {
34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!registered_dev_path.empty());
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!file_path.empty());
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string result;
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (registered_dev_path == file_path) {
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    result = kRootPath;
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::FilePath relative_path;
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (registered_dev_path.AppendRelativePath(file_path, &relative_path)) {
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DCHECK(!relative_path.empty());
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      result = relative_path.value();
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return result;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the MTPDeviceTaskHelper object associated with the MTP device
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// storage.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns NULL if the |storage_name| is no longer valid (e.g. because the
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// corresponding storage device is detached, etc).
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceTaskHelper* GetDeviceTaskHelperForStorage(
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name) {
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return MTPDeviceTaskHelperMapService::GetInstance()->GetDeviceTaskHelper(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      storage_name);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Opens the storage device for communication.
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |reply_callback| is called when the OpenStorage request completes.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |reply_callback| runs on the IO thread.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OpenStorageOnUIThread(
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const MTPDeviceTaskHelper::OpenStorageCallback& reply_callback) {
74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    task_helper =
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper(
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            storage_name);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->OpenStorage(storage_name, reply_callback);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Enumerates the |dir_id| directory file entries.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| is called when the ReadDirectory request succeeds.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |error_callback| is called when the ReadDirectory request fails.
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| and |error_callback| runs on the IO thread.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReadDirectoryOnUIThread(
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 dir_id,
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const MTPDeviceTaskHelper::ReadDirectorySuccessCallback& success_callback,
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const MTPDeviceTaskHelper::ErrorCallback& error_callback) {
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  task_helper->ReadDirectory(dir_id, success_callback, error_callback);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Gets the |file_path| details.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| is called when the GetFileInfo request succeeds.
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |error_callback| is called when the GetFileInfo request fails.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| and |error_callback| runs on the IO thread.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetFileInfoOnUIThread(
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 file_id,
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const MTPDeviceTaskHelper::GetFileInfoSuccessCallback& success_callback,
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const MTPDeviceTaskHelper::ErrorCallback& error_callback) {
121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  task_helper->GetFileInfo(file_id, success_callback, error_callback);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copies the contents of |device_file_path| to |snapshot_file_path|.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |storage_name| specifies the name of the storage device.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |device_file_path| specifies the media device file path.
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |snapshot_file_path| specifies the platform path of the snapshot file.
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |file_size| specifies the number of bytes that will be written to the
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// snapshot file.
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| is called when the copy operation succeeds.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |error_callback| is called when the copy operation fails.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |success_callback| and |error_callback| runs on the IO thread.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WriteDataIntoSnapshotFileOnUIThread(
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SnapshotRequestInfo& request_info,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& snapshot_file_info) {
146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->WriteDataIntoSnapshotFile(request_info, snapshot_file_info);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copies the contents of |device_file_path| to |snapshot_file_path|.
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Called on the UI thread to dispatch the request to the
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// MediaTransferProtocolManager.
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |storage_name| specifies the name of the storage device.
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |request| is a struct containing details about the byte read request.
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ReadBytesOnUIThread(
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& storage_name,
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const MTPDeviceAsyncDelegate::ReadBytesRequest& request) {
164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!task_helper)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  task_helper->ReadBytes(request);
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Closes the device storage specified by the |storage_name| and destroys the
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MTPDeviceTaskHelper object associated with the device storage.
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on the UI thread to dispatch the request to the
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MediaTransferProtocolManager.
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CloseStorageAndDestroyTaskHelperOnUIThread(
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_name) {
179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelper* task_helper =
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDeviceTaskHelperForStorage(storage_name);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!task_helper)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_helper->CloseStorage();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper(
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      storage_name);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo(
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& path,
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserThread::ID thread_id,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const tracked_objects::Location& location,
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& task)
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : path(path),
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      thread_id(thread_id),
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      location(location),
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      task(task) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Represents a file on the MTP device.
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Lives on the IO thread.
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass MTPDeviceDelegateImplLinux::MTPFileNode {
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MTPFileNode(uint32 file_id,
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)              const std::string& file_name,
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              MTPFileNode* parent,
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              FileIdToMTPFileNodeMap* file_id_to_node_map);
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ~MTPFileNode();
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const MTPFileNode* GetChild(const std::string& name) const;
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void EnsureChildExists(const std::string& name, uint32 id);
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Clears all the children, except those in |children_to_keep|.
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void ClearNonexistentChildren(
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const std::set<std::string>& children_to_keep);
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool DeleteChild(uint32 file_id);
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 file_id() const { return file_id_; }
22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const std::string& file_name() const { return file_name_; }
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MTPFileNode* parent() { return parent_; }
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Container for holding a node's children.
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  typedef base::ScopedPtrHashMap<std::string, MTPFileNode> ChildNodes;
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const uint32 file_id_;
23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const std::string file_name_;
23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ChildNodes children_;
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MTPFileNode* const parent_;
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileIdToMTPFileNodeMap* file_id_to_node_map_;
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(MTPFileNode);
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
243116680a4aac90f2aa7413d9095a592090648e557Ben MurdochMTPDeviceDelegateImplLinux::MTPFileNode::MTPFileNode(
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 file_id,
24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::string& file_name,
246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    MTPFileNode* parent,
247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FileIdToMTPFileNodeMap* file_id_to_node_map)
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : file_id_(file_id),
24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      file_name_(file_name),
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      parent_(parent),
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      file_id_to_node_map_(file_id_to_node_map) {
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(file_id_to_node_map_);
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!ContainsKey(*file_id_to_node_map_, file_id_));
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  (*file_id_to_node_map_)[file_id_] = this;
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
258116680a4aac90f2aa7413d9095a592090648e557Ben MurdochMTPDeviceDelegateImplLinux::MTPFileNode::~MTPFileNode() {
259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t erased = file_id_to_node_map_->erase(file_id_);
261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(1U, erased);
262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
264116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst MTPDeviceDelegateImplLinux::MTPFileNode*
265116680a4aac90f2aa7413d9095a592090648e557Ben MurdochMTPDeviceDelegateImplLinux::MTPFileNode::GetChild(
266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& name) const {
267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return children_.get(name);
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
271116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::MTPFileNode::EnsureChildExists(
272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& name,
273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 id) {
274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const MTPFileNode* child = GetChild(name);
276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (child && child->file_id() == id)
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  children_.set(
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      name,
28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      make_scoped_ptr(new MTPFileNode(id, name, this, file_id_to_node_map_)));
282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::MTPFileNode::ClearNonexistentChildren(
285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::set<std::string>& children_to_keep) {
286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::set<std::string> children_to_erase;
288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (ChildNodes::const_iterator it = children_.begin();
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       it != children_.end(); ++it) {
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (ContainsKey(children_to_keep, it->first))
291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      continue;
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    children_to_erase.insert(it->first);
293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (std::set<std::string>::iterator it = children_to_erase.begin();
295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       it != children_to_erase.end(); ++it) {
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    children_.take_and_erase(*it);
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool MTPDeviceDelegateImplLinux::MTPFileNode::DeleteChild(uint32 file_id) {
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (ChildNodes::iterator it = children_.begin();
303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       it != children_.end(); ++it) {
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (it->second->file_id() == file_id) {
305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      children_.erase(it);
306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return true;
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return false;
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux(
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_location)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : init_state_(UNINITIALIZED),
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      task_in_progress_(false),
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      device_path_(device_location),
317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      root_node_(new MTPFileNode(mtpd::kRootFileId,
31803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                 "",    // Root node has no name.
31903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                 NULL,  // And no parent node.
320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 &file_id_to_node_map_)),
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!device_path_.empty());
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RemoveChars(device_location, kRootPath, &storage_name_);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!storage_name_.empty());
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() {
329e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::GetFileInfo(
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& file_path,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GetFileInfoSuccessCallback& success_callback,
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
336e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!file_path.empty());
33803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // If a ReadDirectory operation is in progress, the file info may already be
34003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // cached.
34103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  FileInfoCache::const_iterator it = file_info_cache_.find(file_path);
34203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (it != file_info_cache_.end()) {
34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // TODO(thestig): This code is repeated in several places. Combine them.
34403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // e.g. c/b/media_galleries/win/mtp_device_operations_util.cc
34503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::DirectoryEntry& cached_file_entry = it->second;
34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::File::Info info;
34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    info.size = cached_file_entry.size;
34803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    info.is_directory = cached_file_entry.is_directory;
34903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    info.is_symbolic_link = false;
35003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    info.last_modified = cached_file_entry.last_modified_time;
35103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    info.creation_time = base::Time();
35203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
35303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    success_callback.Run(info);
35403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
35503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Closure closure =
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal,
358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 file_path,
360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 success_callback,
361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 error_callback);
362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EnsureInitAndRunTask(PendingTaskInfo(file_path,
363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       content::BrowserThread::IO,
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       FROM_HERE,
365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       closure));
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::ReadDirectory(
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& root,
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
372e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!root.empty());
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Closure closure =
375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::ReadDirectoryInternal,
376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 root,
378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 success_callback,
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 error_callback);
380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EnsureInitAndRunTask(PendingTaskInfo(root,
381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       content::BrowserThread::IO,
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       FROM_HERE,
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       closure));
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::CreateSnapshotFile(
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& device_file_path,
388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& local_path,
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CreateSnapshotFileSuccessCallback& success_callback,
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
391e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!device_file_path.empty());
393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!local_path.empty());
394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Closure closure =
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal,
396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 device_file_path,
398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 local_path,
399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 success_callback,
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 error_callback);
401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EnsureInitAndRunTask(PendingTaskInfo(device_file_path,
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       content::BrowserThread::IO,
403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       FROM_HERE,
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       closure));
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MTPDeviceDelegateImplLinux::IsStreaming() {
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MTPDeviceDelegateImplLinux::ReadBytes(
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::FilePath& device_file_path,
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    net::IOBuffer* buf, int64 offset, int buf_len,
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReadBytesSuccessCallback& success_callback,
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ErrorCallback& error_callback) {
416e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!device_file_path.empty());
418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Closure closure =
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::ReadBytesInternal,
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 device_file_path,
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 make_scoped_refptr(buf),
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 offset,
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 buf_len,
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 success_callback,
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 error_callback);
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EnsureInitAndRunTask(PendingTaskInfo(device_file_path,
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       content::BrowserThread::IO,
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       FROM_HERE,
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       closure));
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() {
434e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object.
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::BrowserThread::UI,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_));
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete this;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::GetFileInfoInternal(
444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& file_path,
445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GetFileInfoSuccessCallback& success_callback,
446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 file_id;
450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(file_path, &file_id)) {
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetFileInfoSuccessCallback success_callback_wrapper =
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo,
453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   success_callback);
455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorCallback error_callback_wrapper =
456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   file_id);
460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       storage_name_,
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       file_id,
465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       success_callback_wrapper,
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       error_callback_wrapper);
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
477116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::ReadDirectoryInternal(
478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& root,
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ReadDirectorySuccessCallback& success_callback,
480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 dir_id;
484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(root, &dir_id)) {
485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetFileInfoSuccessCallback success_callback_wrapper =
486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory,
487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   dir_id,
489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   success_callback,
490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback);
491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorCallback error_callback_wrapper =
492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   dir_id);
496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       storage_name_,
498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       dir_id,
499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       success_callback_wrapper,
500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       error_callback_wrapper);
501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
502116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
504116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
511116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal(
512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& device_file_path,
513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& local_path,
514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const CreateSnapshotFileSuccessCallback& success_callback,
515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 file_id;
519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(device_file_path, &file_id)) {
520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<SnapshotRequestInfo> request_info(
521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        new SnapshotRequestInfo(file_id,
522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                local_path,
523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                success_callback,
524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                error_callback));
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetFileInfoSuccessCallback success_callback_wrapper =
526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(
527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile,
528116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            weak_ptr_factory_.GetWeakPtr(),
529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            base::Passed(&request_info));
530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorCallback error_callback_wrapper =
531116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   file_id);
535116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
536116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       storage_name_,
537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       file_id,
538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       success_callback_wrapper,
539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       error_callback_wrapper);
540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
542116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
544116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
545116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
546116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
547116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
548116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
549116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
550116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::ReadBytesInternal(
551116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& device_file_path,
552116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    net::IOBuffer* buf, int64 offset, int buf_len,
553116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ReadBytesSuccessCallback& success_callback,
554116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
557116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 file_id;
558116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(device_file_path, &file_id)) {
559116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReadBytesRequest request(
560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        file_id, buf, offset, buf_len,
561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes,
562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   success_callback),
564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   file_id));
568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure =
570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request));
571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask(
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PendingTaskInfo& task_info) {
583e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((init_state_ == INITIALIZED) && !task_in_progress_) {
585116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RunTask(task_info);
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
588116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
589116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Only *Internal functions have empty paths. Since they are the continuation
590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // of the current running task, they get to cut in line.
591116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (task_info.path.empty())
592116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    pending_tasks_.push_front(task_info);
593116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  else
594116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    pending_tasks_.push_back(task_info);
595116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (init_state_ == UNINITIALIZED) {
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    init_state_ = PENDING_INIT;
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    task_in_progress_ = true;
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::BrowserThread::PostTask(
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::BrowserThread::UI,
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&OpenStorageOnUIThread,
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   storage_name_,
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted,
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              weak_ptr_factory_.GetWeakPtr())));
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
609116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::RunTask(const PendingTaskInfo& task_info) {
610116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
611116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(INITIALIZED, init_state_);
612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!task_in_progress_);
613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  task_in_progress_ = true;
614116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
615116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool need_to_check_cache = !task_info.path.empty();
616116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (need_to_check_cache) {
617116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::FilePath uncached_path =
618116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        NextUncachedPathComponent(task_info.path, task_info.cached_path);
619116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!uncached_path.empty()) {
620116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Save the current task and do a cache lookup first.
621116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pending_tasks_.push_front(task_info);
622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      FillFileCache(uncached_path);
623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
626116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
627116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  content::BrowserThread::PostTask(task_info.thread_id,
628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          task_info.location,
629116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          task_info.task);
630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile(
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
634e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(file_info.size, 0);
637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(task_in_progress_);
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SnapshotRequestInfo request_info(
639116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      current_snapshot_request_info_->file_id,
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_snapshot_request_info_->snapshot_file_path,
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile,
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()),
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError,
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()));
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread,
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          storage_name_,
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          request_info,
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          file_info);
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI,
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   FROM_HERE,
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_closure);
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
657116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::PendingRequestDone() {
658116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(task_in_progress_);
659116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  task_in_progress_ = false;
660116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ProcessNextPendingRequest();
661116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::ProcessNextPendingRequest() {
664e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!task_in_progress_);
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_tasks_.empty())
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
669116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingTaskInfo task_info = pending_tasks_.front();
670116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pending_tasks_.pop_front();
671116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RunTask(task_info);
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnInitCompleted(bool succeeded) {
675e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  init_state_ = succeeded ? INITIALIZED : UNINITIALIZED;
677116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfo(
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GetFileInfoSuccessCallback& success_callback,
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
683e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  success_callback.Run(file_info);
685116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory(
689116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 dir_id,
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback,
6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
693e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!file_info.is_directory) {
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HandleDeviceFileError(error_callback,
697116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 dir_id,
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 base::File::FILE_ERROR_NOT_A_DIRECTORY);
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure task_closure =
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ReadDirectoryOnUIThread,
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 storage_name_,
704116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 dir_id,
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory,
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
707116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            dir_id,
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            success_callback),
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
711116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            error_callback,
712116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            dir_id));
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI,
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   FROM_HERE,
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_closure);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile(
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<SnapshotRequestInfo> snapshot_request_info,
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
721e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!current_snapshot_request_info_.get());
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(snapshot_request_info.get());
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error error = base::File::FILE_OK;
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_info.is_directory)
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = base::File::FILE_ERROR_NOT_A_FILE;
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (file_info.size < 0 || file_info.size > kuint32max)
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = base::File::FILE_ERROR_FAILED;
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != base::File::FILE_OK)
732116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return HandleDeviceFileError(snapshot_request_info->error_callback,
733116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 snapshot_request_info->file_id,
734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 error);
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Info snapshot_file_info(file_info);
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Modify the last modified time to null. This prevents the time stamp
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // verfication in LocalFileStreamReader.
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  snapshot_file_info.last_modified = base::Time();
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset(snapshot_request_info.release());
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_info.size == 0) {
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Empty snapshot file.
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OnDidWriteDataIntoSnapshotFile(
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        snapshot_file_info, current_snapshot_request_info_->snapshot_file_path);
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WriteDataIntoSnapshotFile(snapshot_file_info);
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidReadDirectory(
751116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 dir_id,
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
75303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::AsyncFileUtil::EntryList& file_list,
7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool has_more) {
755e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
756116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
757116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id);
758116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(it != file_id_to_node_map_.end());
759116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MTPFileNode* dir_node = it->second;
760116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
76103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Traverse the MTPFileNode tree to reconstuct the full path for |dir_id|.
76203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::deque<std::string> dir_path_parts;
76303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  MTPFileNode* parent_node = dir_node;
76403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  while (parent_node->parent()) {
76503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    dir_path_parts.push_front(parent_node->file_name());
76603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    parent_node = parent_node->parent();
76703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
76803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::FilePath dir_path = device_path_;
76903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < dir_path_parts.size(); ++i)
77003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    dir_path = dir_path.Append(dir_path_parts[i]);
77103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
77203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::AsyncFileUtil::EntryList normalized_file_list;
773116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < file_list.size(); ++i) {
774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    normalized_file_list.push_back(file_list[i]);
77503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::DirectoryEntry& entry = normalized_file_list.back();
776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
777116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // |entry.name| has the file id encoded in it. Decode here.
778116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    size_t separator_idx = entry.name.find_last_of(',');
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK_NE(std::string::npos, separator_idx);
780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::string file_id_str = entry.name.substr(separator_idx);
781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    file_id_str = file_id_str.substr(1);  // Get rid of the comma.
782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 file_id = 0;
783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool ret = base::StringToUint(file_id_str, &file_id);
784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(ret);
785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    entry.name = entry.name.substr(0, separator_idx);
786116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
787116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Refresh the in memory tree.
788116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    dir_node->EnsureChildExists(entry.name, file_id);
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_nodes_seen_.insert(entry.name);
79003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
79103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // Add to |file_info_cache_|.
79203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    file_info_cache_[dir_path.Append(entry.name)] = entry;
793116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
794116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  success_callback.Run(normalized_file_list, has_more);
7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (has_more)
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;  // Wait to be called again.
7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Last call, finish book keeping and continue with the next request.
8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  dir_node->ClearNonexistentChildren(child_nodes_seen_);
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  child_nodes_seen_.clear();
80203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  file_info_cache_.clear();
8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
804116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile(
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info,
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& snapshot_file_path) {
810e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_->success_callback.Run(
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      file_info, snapshot_file_path);
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset();
815116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError(
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
820e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_->error_callback.Run(error);
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset();
824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidReadBytes(
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReadBytesSuccessCallback& success_callback,
829a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::File::Info& file_info, int bytes_read) {
830e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
831a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  success_callback.Run(file_info, bytes_read);
832116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
833116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
834116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
835116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::OnDidFillFileCache(
836116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& path,
83703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::AsyncFileUtil::EntryList& /* file_list */,
8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool has_more) {
839116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
840116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(path.IsParent(pending_tasks_.front().path));
8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (has_more)
8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;  // Wait until all entries have been read.
843116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pending_tasks_.front().cached_path = path;
844116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
845116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
846116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::OnFillFileCacheFailed(
847116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::File::Error /* error */) {
848116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
849116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // When filling the cache fails for the task at the front of the queue, clear
850116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the path of the task so it will not try to do any more caching. Instead,
851116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the task will just run and fail the CachedPathToId() lookup.
852116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pending_tasks_.front().path.clear();
8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::HandleDeviceFileError(
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback,
857116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 file_id,
8585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
859e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
860116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
861116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(file_id);
862116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (it != file_id_to_node_map_.end()) {
863116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    MTPFileNode* parent = it->second->parent();
864116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (parent) {
865116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      bool ret = parent->DeleteChild(file_id);
866116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DCHECK(ret);
867116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
868116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error_callback.Run(error);
870116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
871116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
872116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
873116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbase::FilePath MTPDeviceDelegateImplLinux::NextUncachedPathComponent(
874116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& path,
875116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& cached_path) const {
876116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
877116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(cached_path.empty() || cached_path.IsParent(path));
878116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
879116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::FilePath uncached_path;
880116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string device_relpath = GetDeviceRelativePath(device_path_, path);
881116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!device_relpath.empty() && device_relpath != kRootPath) {
882116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uncached_path = device_path_;
883116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::vector<std::string> device_relpath_components;
884116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::SplitString(device_relpath, '/', &device_relpath_components);
885116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(!device_relpath_components.empty());
886116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool all_components_cached = true;
887116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const MTPFileNode* current_node = root_node_.get();
888116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (size_t i = 0; i < device_relpath_components.size(); ++i) {
889116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      current_node = current_node->GetChild(device_relpath_components[i]);
890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (!current_node) {
891116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // With a cache miss, check if it is a genuine failure. If so, pretend
892116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // the entire |path| is cached, so there is no further attempt to do
893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // more caching. The actual operation will then fail.
894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        all_components_cached =
895116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            !cached_path.empty() && (uncached_path == cached_path);
896116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        break;
897116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
898116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      uncached_path = uncached_path.Append(device_relpath_components[i]);
899116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
900116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (all_components_cached)
901116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      uncached_path.clear();
902116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return uncached_path;
904116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
906116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::FillFileCache(
907116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& uncached_path) {
908116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
909116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(task_in_progress_);
910116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
911116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ReadDirectorySuccessCallback success_callback =
912116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::OnDidFillFileCache,
913116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
914116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 uncached_path);
915116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ErrorCallback error_callback =
916116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::OnFillFileCacheFailed,
917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr());
918116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ReadDirectoryInternal(uncached_path, success_callback, error_callback);
919116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
920116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
921116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
922116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool MTPDeviceDelegateImplLinux::CachedPathToId(const base::FilePath& path,
923116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                uint32* id) const {
924116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(id);
925116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
926116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string device_relpath = GetDeviceRelativePath(device_path_, path);
927116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (device_relpath.empty())
928116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
929116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<std::string> device_relpath_components;
930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (device_relpath != kRootPath)
931116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::SplitString(device_relpath, '/', &device_relpath_components);
932116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const MTPFileNode* current_node = root_node_.get();
933116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < device_relpath_components.size(); ++i) {
934116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    current_node = current_node->GetChild(device_relpath_components[i]);
935116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!current_node)
936116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
937116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
938116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *id = current_node->file_id();
939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CreateMTPDeviceAsyncDelegate(
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_location,
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CreateMTPDeviceAsyncDelegateCallback& callback) {
945e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(new MTPDeviceDelegateImplLinux(device_location));
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
948