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/files/file_path.h"
9 #include "base/files/file_util.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);
30 return base::AppendToFile(snapshot_file_path
, data
.c_str(), data
.size())
31 ? base::checked_cast
<uint32
>(data
.size())
37 MTPReadFileWorker::MTPReadFileWorker(const std::string
& device_handle
)
38 : device_handle_(device_handle
),
39 weak_ptr_factory_(this) {
40 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
41 DCHECK(!device_handle_
.empty());
44 MTPReadFileWorker::~MTPReadFileWorker() {
47 void MTPReadFileWorker::WriteDataIntoSnapshotFile(
48 const SnapshotRequestInfo
& request_info
,
49 const base::File::Info
& snapshot_file_info
) {
50 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
51 ReadDataChunkFromDeviceFile(
52 make_scoped_ptr(new SnapshotFileDetails(request_info
,
53 snapshot_file_info
)));
56 void MTPReadFileWorker::ReadDataChunkFromDeviceFile(
57 scoped_ptr
<SnapshotFileDetails
> snapshot_file_details
) {
58 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
59 DCHECK(snapshot_file_details
.get());
61 // To avoid calling |snapshot_file_details| methods and passing ownership of
62 // |snapshot_file_details| in the same_line.
63 SnapshotFileDetails
* snapshot_file_details_ptr
= snapshot_file_details
.get();
65 device::MediaTransferProtocolManager
* mtp_device_manager
=
66 StorageMonitor::GetInstance()->media_transfer_protocol_manager();
67 mtp_device_manager
->ReadFileChunk(
69 snapshot_file_details_ptr
->file_id(),
70 snapshot_file_details_ptr
->bytes_written(),
71 snapshot_file_details_ptr
->BytesToRead(),
72 base::Bind(&MTPReadFileWorker::OnDidReadDataChunkFromDeviceFile
,
73 weak_ptr_factory_
.GetWeakPtr(),
74 base::Passed(&snapshot_file_details
)));
77 void MTPReadFileWorker::OnDidReadDataChunkFromDeviceFile(
78 scoped_ptr
<SnapshotFileDetails
> snapshot_file_details
,
79 const std::string
& data
,
81 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
82 DCHECK(snapshot_file_details
.get());
83 snapshot_file_details
->set_error_occurred(
84 error
|| (data
.size() != snapshot_file_details
->BytesToRead()));
85 if (snapshot_file_details
->error_occurred()) {
86 OnDidWriteIntoSnapshotFile(snapshot_file_details
.Pass());
90 // To avoid calling |snapshot_file_details| methods and passing ownership of
91 // |snapshot_file_details| in the same_line.
92 SnapshotFileDetails
* snapshot_file_details_ptr
= snapshot_file_details
.get();
93 content::BrowserThread::PostTaskAndReplyWithResult(
94 content::BrowserThread::FILE,
96 base::Bind(&WriteDataChunkIntoSnapshotFileOnFileThread
,
97 snapshot_file_details_ptr
->snapshot_file_path(),
99 base::Bind(&MTPReadFileWorker::OnDidWriteDataChunkIntoSnapshotFile
,
100 weak_ptr_factory_
.GetWeakPtr(),
101 base::Passed(&snapshot_file_details
)));
104 void MTPReadFileWorker::OnDidWriteDataChunkIntoSnapshotFile(
105 scoped_ptr
<SnapshotFileDetails
> snapshot_file_details
,
106 uint32 bytes_written
) {
107 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
108 DCHECK(snapshot_file_details
.get());
109 if (snapshot_file_details
->AddBytesWritten(bytes_written
)) {
110 if (!snapshot_file_details
->IsSnapshotFileWriteComplete()) {
111 ReadDataChunkFromDeviceFile(snapshot_file_details
.Pass());
115 snapshot_file_details
->set_error_occurred(true);
117 OnDidWriteIntoSnapshotFile(snapshot_file_details
.Pass());
120 void MTPReadFileWorker::OnDidWriteIntoSnapshotFile(
121 scoped_ptr
<SnapshotFileDetails
> snapshot_file_details
) {
122 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
123 DCHECK(snapshot_file_details
.get());
125 if (snapshot_file_details
->error_occurred()) {
126 content::BrowserThread::PostTask(
127 content::BrowserThread::IO
,
129 base::Bind(snapshot_file_details
->error_callback(),
130 base::File::FILE_ERROR_FAILED
));
133 content::BrowserThread::PostTask(
134 content::BrowserThread::IO
,
136 base::Bind(snapshot_file_details
->success_callback(),
137 snapshot_file_details
->file_info(),
138 snapshot_file_details
->snapshot_file_path()));