1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/media_galleries/linux/mtp_read_file_worker.h"
8 #include "base/file_util.h"
9 #include "base/files/file_path.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
12 #include "components/storage_monitor/storage_monitor.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
17 using content::BrowserThread;
18 using storage_monitor::StorageMonitor;
22 // Appends |data| to the snapshot file specified by the |snapshot_file_path| on
24 // Returns the number of bytes written to the snapshot file. In case of failure,
26 uint32 WriteDataChunkIntoSnapshotFileOnFileThread(
27 const base::FilePath& snapshot_file_path,
28 const std::string& data) {
29 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
31 base::AppendToFile(snapshot_file_path, data.data(),
32 base::checked_cast<int>(data.size()));
33 return (static_cast<int>(data.size()) == bytes_written) ?
34 base::checked_cast<uint32>(bytes_written) : 0;
39 MTPReadFileWorker::MTPReadFileWorker(const std::string& device_handle)
40 : device_handle_(device_handle),
41 weak_ptr_factory_(this) {
42 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
43 DCHECK(!device_handle_.empty());
46 MTPReadFileWorker::~MTPReadFileWorker() {
49 void MTPReadFileWorker::WriteDataIntoSnapshotFile(
50 const SnapshotRequestInfo& request_info,
51 const base::File::Info& snapshot_file_info) {
52 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
53 ReadDataChunkFromDeviceFile(
54 make_scoped_ptr(new SnapshotFileDetails(request_info,
55 snapshot_file_info)));
58 void MTPReadFileWorker::ReadDataChunkFromDeviceFile(
59 scoped_ptr<SnapshotFileDetails> snapshot_file_details) {
60 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
61 DCHECK(snapshot_file_details.get());
63 // To avoid calling |snapshot_file_details| methods and passing ownership of
64 // |snapshot_file_details| in the same_line.
65 SnapshotFileDetails* snapshot_file_details_ptr = snapshot_file_details.get();
67 device::MediaTransferProtocolManager* mtp_device_manager =
68 StorageMonitor::GetInstance()->media_transfer_protocol_manager();
69 mtp_device_manager->ReadFileChunk(
71 snapshot_file_details_ptr->file_id(),
72 snapshot_file_details_ptr->bytes_written(),
73 snapshot_file_details_ptr->BytesToRead(),
74 base::Bind(&MTPReadFileWorker::OnDidReadDataChunkFromDeviceFile,
75 weak_ptr_factory_.GetWeakPtr(),
76 base::Passed(&snapshot_file_details)));
79 void MTPReadFileWorker::OnDidReadDataChunkFromDeviceFile(
80 scoped_ptr<SnapshotFileDetails> snapshot_file_details,
81 const std::string& data,
83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
84 DCHECK(snapshot_file_details.get());
85 snapshot_file_details->set_error_occurred(
86 error || (data.size() != snapshot_file_details->BytesToRead()));
87 if (snapshot_file_details->error_occurred()) {
88 OnDidWriteIntoSnapshotFile(snapshot_file_details.Pass());
92 // To avoid calling |snapshot_file_details| methods and passing ownership of
93 // |snapshot_file_details| in the same_line.
94 SnapshotFileDetails* snapshot_file_details_ptr = snapshot_file_details.get();
95 content::BrowserThread::PostTaskAndReplyWithResult(
96 content::BrowserThread::FILE,
98 base::Bind(&WriteDataChunkIntoSnapshotFileOnFileThread,
99 snapshot_file_details_ptr->snapshot_file_path(),
101 base::Bind(&MTPReadFileWorker::OnDidWriteDataChunkIntoSnapshotFile,
102 weak_ptr_factory_.GetWeakPtr(),
103 base::Passed(&snapshot_file_details)));
106 void MTPReadFileWorker::OnDidWriteDataChunkIntoSnapshotFile(
107 scoped_ptr<SnapshotFileDetails> snapshot_file_details,
108 uint32 bytes_written) {
109 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
110 DCHECK(snapshot_file_details.get());
111 if (snapshot_file_details->AddBytesWritten(bytes_written)) {
112 if (!snapshot_file_details->IsSnapshotFileWriteComplete()) {
113 ReadDataChunkFromDeviceFile(snapshot_file_details.Pass());
117 snapshot_file_details->set_error_occurred(true);
119 OnDidWriteIntoSnapshotFile(snapshot_file_details.Pass());
122 void MTPReadFileWorker::OnDidWriteIntoSnapshotFile(
123 scoped_ptr<SnapshotFileDetails> snapshot_file_details) {
124 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
125 DCHECK(snapshot_file_details.get());
127 if (snapshot_file_details->error_occurred()) {
128 content::BrowserThread::PostTask(
129 content::BrowserThread::IO,
131 base::Bind(snapshot_file_details->error_callback(),
132 base::File::FILE_ERROR_FAILED));
135 content::BrowserThread::PostTask(
136 content::BrowserThread::IO,
138 base::Bind(snapshot_file_details->success_callback(),
139 snapshot_file_details->file_info(),
140 snapshot_file_details->snapshot_file_path()));