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,
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<net::IOBuffer>& buf,
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int64 offset,
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int buf_len,
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReadBytesSuccessCallback& success_callback,
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ErrorCallback& error_callback) {
418e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!device_file_path.empty());
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Closure closure =
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::ReadBytesInternal,
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 device_file_path,
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 buf,
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 offset,
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 buf_len,
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 success_callback,
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 error_callback);
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EnsureInitAndRunTask(PendingTaskInfo(device_file_path,
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       content::BrowserThread::IO,
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       FROM_HERE,
432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       closure));
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() {
436e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object.
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::BrowserThread::UI,
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_));
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete this;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
445116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::GetFileInfoInternal(
446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& file_path,
447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GetFileInfoSuccessCallback& success_callback,
448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 file_id;
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(file_path, &file_id)) {
453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetFileInfoSuccessCallback success_callback_wrapper =
454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo,
455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   success_callback);
457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorCallback error_callback_wrapper =
458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   file_id);
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       storage_name_,
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       file_id,
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       success_callback_wrapper,
468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       error_callback_wrapper);
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::ReadDirectoryInternal(
480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& root,
481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ReadDirectorySuccessCallback& success_callback,
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 dir_id;
486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(root, &dir_id)) {
487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetFileInfoSuccessCallback success_callback_wrapper =
488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory,
489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   dir_id,
491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   success_callback,
492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback);
493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorCallback error_callback_wrapper =
494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   dir_id);
498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       storage_name_,
500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       dir_id,
501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       success_callback_wrapper,
502116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       error_callback_wrapper);
503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
504116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
511116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
513116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal(
514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& device_file_path,
515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& local_path,
516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const CreateSnapshotFileSuccessCallback& success_callback,
517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 file_id;
521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(device_file_path, &file_id)) {
522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<SnapshotRequestInfo> request_info(
523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        new SnapshotRequestInfo(file_id,
524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                local_path,
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                success_callback,
526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                error_callback));
527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetFileInfoSuccessCallback success_callback_wrapper =
528116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(
529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile,
530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            weak_ptr_factory_.GetWeakPtr(),
531116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            base::Passed(&request_info));
532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorCallback error_callback_wrapper =
533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
535116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
536116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   file_id);
537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       storage_name_,
539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       file_id,
540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       success_callback_wrapper,
541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       error_callback_wrapper);
542116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
544116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
545116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
546116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
547116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
548116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
549116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
550116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
551116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
552116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::ReadBytesInternal(
553116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& device_file_path,
554116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    net::IOBuffer* buf, int64 offset, int buf_len,
555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ReadBytesSuccessCallback& success_callback,
556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ErrorCallback& error_callback) {
557116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
558116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
559116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 file_id;
560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CachedPathToId(device_file_path, &file_id)) {
561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReadBytesRequest request(
562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        file_id, buf, offset, buf_len,
563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes,
564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   success_callback),
566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   error_callback,
569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   file_id));
570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Closure closure =
572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request));
573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         content::BrowserThread::UI,
575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         FROM_HERE,
576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         closure));
577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask(
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PendingTaskInfo& task_info) {
585e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((init_state_ == INITIALIZED) && !task_in_progress_) {
587116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RunTask(task_info);
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
591116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Only *Internal functions have empty paths. Since they are the continuation
592116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // of the current running task, they get to cut in line.
593116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (task_info.path.empty())
594116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    pending_tasks_.push_front(task_info);
595116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  else
596116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    pending_tasks_.push_back(task_info);
597116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (init_state_ == UNINITIALIZED) {
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    init_state_ = PENDING_INIT;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    task_in_progress_ = true;
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::BrowserThread::PostTask(
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::BrowserThread::UI,
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&OpenStorageOnUIThread,
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   storage_name_,
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted,
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              weak_ptr_factory_.GetWeakPtr())));
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
611116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::RunTask(const PendingTaskInfo& task_info) {
612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(INITIALIZED, init_state_);
614116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!task_in_progress_);
615116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  task_in_progress_ = true;
616116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
617116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool need_to_check_cache = !task_info.path.empty();
618116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (need_to_check_cache) {
619116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::FilePath uncached_path =
620116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        NextUncachedPathComponent(task_info.path, task_info.cached_path);
621116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!uncached_path.empty()) {
622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Save the current task and do a cache lookup first.
623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pending_tasks_.push_front(task_info);
624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      FillFileCache(uncached_path);
625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
626116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
627116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
629116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  content::BrowserThread::PostTask(task_info.thread_id,
630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          task_info.location,
631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          task_info.task);
632116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
633116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile(
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
636e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(file_info.size, 0);
639116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(task_in_progress_);
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SnapshotRequestInfo request_info(
641116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      current_snapshot_request_info_->file_id,
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_snapshot_request_info_->snapshot_file_path,
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile,
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()),
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError,
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()));
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread,
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          storage_name_,
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          request_info,
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          file_info);
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI,
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   FROM_HERE,
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_closure);
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
659116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::PendingRequestDone() {
660116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(task_in_progress_);
661116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  task_in_progress_ = false;
662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ProcessNextPendingRequest();
663116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
664116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::ProcessNextPendingRequest() {
666e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!task_in_progress_);
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_tasks_.empty())
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
671116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingTaskInfo task_info = pending_tasks_.front();
672116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pending_tasks_.pop_front();
673116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RunTask(task_info);
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnInitCompleted(bool succeeded) {
677e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  init_state_ = succeeded ? INITIALIZED : UNINITIALIZED;
679116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfo(
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GetFileInfoSuccessCallback& success_callback,
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
685e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  success_callback.Run(file_info);
687116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory(
691116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 dir_id,
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback,
6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
695e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!file_info.is_directory) {
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HandleDeviceFileError(error_callback,
699116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 dir_id,
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 base::File::FILE_ERROR_NOT_A_DIRECTORY);
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure task_closure =
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ReadDirectoryOnUIThread,
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 storage_name_,
706116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 dir_id,
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory,
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
709116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            dir_id,
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            success_callback),
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
713116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            error_callback,
714116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            dir_id));
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI,
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   FROM_HERE,
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   task_closure);
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile(
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<SnapshotRequestInfo> snapshot_request_info,
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
723e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!current_snapshot_request_info_.get());
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(snapshot_request_info.get());
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(task_in_progress_);
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error error = base::File::FILE_OK;
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_info.is_directory)
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = base::File::FILE_ERROR_NOT_A_FILE;
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (file_info.size < 0 || file_info.size > kuint32max)
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = base::File::FILE_ERROR_FAILED;
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != base::File::FILE_OK)
734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return HandleDeviceFileError(snapshot_request_info->error_callback,
735116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 snapshot_request_info->file_id,
736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 error);
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Info snapshot_file_info(file_info);
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Modify the last modified time to null. This prevents the time stamp
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // verfication in LocalFileStreamReader.
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  snapshot_file_info.last_modified = base::Time();
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset(snapshot_request_info.release());
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_info.size == 0) {
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Empty snapshot file.
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OnDidWriteDataIntoSnapshotFile(
747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        snapshot_file_info, current_snapshot_request_info_->snapshot_file_path);
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WriteDataIntoSnapshotFile(snapshot_file_info);
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidReadDirectory(
753116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 dir_id,
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectorySuccessCallback& success_callback,
75503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::AsyncFileUtil::EntryList& file_list,
7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool has_more) {
757e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
758116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
759116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id);
760116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(it != file_id_to_node_map_.end());
761116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MTPFileNode* dir_node = it->second;
762116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
76303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Traverse the MTPFileNode tree to reconstuct the full path for |dir_id|.
76403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::deque<std::string> dir_path_parts;
76503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  MTPFileNode* parent_node = dir_node;
76603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  while (parent_node->parent()) {
76703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    dir_path_parts.push_front(parent_node->file_name());
76803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    parent_node = parent_node->parent();
76903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
77003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::FilePath dir_path = device_path_;
77103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < dir_path_parts.size(); ++i)
77203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    dir_path = dir_path.Append(dir_path_parts[i]);
77303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
77403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::AsyncFileUtil::EntryList normalized_file_list;
775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < file_list.size(); ++i) {
776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    normalized_file_list.push_back(file_list[i]);
77703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::DirectoryEntry& entry = normalized_file_list.back();
778116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // |entry.name| has the file id encoded in it. Decode here.
780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    size_t separator_idx = entry.name.find_last_of(',');
781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK_NE(std::string::npos, separator_idx);
782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::string file_id_str = entry.name.substr(separator_idx);
783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    file_id_str = file_id_str.substr(1);  // Get rid of the comma.
784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 file_id = 0;
785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool ret = base::StringToUint(file_id_str, &file_id);
786116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(ret);
787116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    entry.name = entry.name.substr(0, separator_idx);
788116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
789116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Refresh the in memory tree.
790116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    dir_node->EnsureChildExists(entry.name, file_id);
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_nodes_seen_.insert(entry.name);
79203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
79303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // Add to |file_info_cache_|.
79403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    file_info_cache_[dir_path.Append(entry.name)] = entry;
795116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
796116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  success_callback.Run(normalized_file_list, has_more);
7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (has_more)
7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;  // Wait to be called again.
8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Last call, finish book keeping and continue with the next request.
8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  dir_node->ClearNonexistentChildren(child_nodes_seen_);
8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  child_nodes_seen_.clear();
80403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  file_info_cache_.clear();
8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
806116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile(
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info,
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& snapshot_file_path) {
812e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_->success_callback.Run(
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      file_info, snapshot_file_path);
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset();
817116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError(
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
822e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(current_snapshot_request_info_.get());
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_->error_callback.Run(error);
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_snapshot_request_info_.reset();
826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MTPDeviceDelegateImplLinux::OnDidReadBytes(
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReadBytesSuccessCallback& success_callback,
831a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::File::Info& file_info, int bytes_read) {
832e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
833a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  success_callback.Run(file_info, bytes_read);
834116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
835116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
836116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
837116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::OnDidFillFileCache(
838116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& path,
83903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::AsyncFileUtil::EntryList& /* file_list */,
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool has_more) {
841116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
842116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(path.IsParent(pending_tasks_.front().path));
8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (has_more)
8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;  // Wait until all entries have been read.
845116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pending_tasks_.front().cached_path = path;
846116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
847116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
848116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::OnFillFileCacheFailed(
849116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::File::Error /* error */) {
850116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
851116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // When filling the cache fails for the task at the front of the queue, clear
852116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the path of the task so it will not try to do any more caching. Instead,
853116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the task will just run and fail the CachedPathToId() lookup.
854116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pending_tasks_.front().path.clear();
8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MTPDeviceDelegateImplLinux::HandleDeviceFileError(
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback,
859116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint32 file_id,
8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
861e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
862116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
863116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(file_id);
864116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (it != file_id_to_node_map_.end()) {
865116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    MTPFileNode* parent = it->second->parent();
866116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (parent) {
867116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      bool ret = parent->DeleteChild(file_id);
868116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DCHECK(ret);
869116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
870116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error_callback.Run(error);
872116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PendingRequestDone();
873116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
874116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
875116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbase::FilePath MTPDeviceDelegateImplLinux::NextUncachedPathComponent(
876116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& path,
877116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& cached_path) const {
878116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
879116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(cached_path.empty() || cached_path.IsParent(path));
880116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
881116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::FilePath uncached_path;
882116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string device_relpath = GetDeviceRelativePath(device_path_, path);
883116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!device_relpath.empty() && device_relpath != kRootPath) {
884116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uncached_path = device_path_;
885116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::vector<std::string> device_relpath_components;
886116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::SplitString(device_relpath, '/', &device_relpath_components);
887116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(!device_relpath_components.empty());
888116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool all_components_cached = true;
889116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const MTPFileNode* current_node = root_node_.get();
890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (size_t i = 0; i < device_relpath_components.size(); ++i) {
891116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      current_node = current_node->GetChild(device_relpath_components[i]);
892116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (!current_node) {
893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // With a cache miss, check if it is a genuine failure. If so, pretend
894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // the entire |path| is cached, so there is no further attempt to do
895116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // more caching. The actual operation will then fail.
896116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        all_components_cached =
897116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            !cached_path.empty() && (uncached_path == cached_path);
898116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        break;
899116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
900116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      uncached_path = uncached_path.Append(device_relpath_components[i]);
901116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
902116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (all_components_cached)
903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      uncached_path.clear();
904116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return uncached_path;
906116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
907116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
908116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MTPDeviceDelegateImplLinux::FillFileCache(
909116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& uncached_path) {
910116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
911116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(task_in_progress_);
912116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
913116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ReadDirectorySuccessCallback success_callback =
914116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::OnDidFillFileCache,
915116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
916116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 uncached_path);
917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ErrorCallback error_callback =
918116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&MTPDeviceDelegateImplLinux::OnFillFileCacheFailed,
919116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr());
920116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ReadDirectoryInternal(uncached_path, success_callback, error_callback);
921116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
922116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
923116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
924116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool MTPDeviceDelegateImplLinux::CachedPathToId(const base::FilePath& path,
925116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                uint32* id) const {
926116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(id);
927116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
928116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string device_relpath = GetDeviceRelativePath(device_path_, path);
929116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (device_relpath.empty())
930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
931116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<std::string> device_relpath_components;
932116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (device_relpath != kRootPath)
933116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::SplitString(device_relpath, '/', &device_relpath_components);
934116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const MTPFileNode* current_node = root_node_.get();
935116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < device_relpath_components.size(); ++i) {
936116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    current_node = current_node->GetChild(device_relpath_components[i]);
937116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!current_node)
938116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
940116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *id = current_node->file_id();
941116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CreateMTPDeviceAsyncDelegate(
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_location,
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CreateMTPDeviceAsyncDelegateCallback& callback) {
947e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(new MTPDeviceDelegateImplLinux(device_location));
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
950