OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
Lei Zhang
2012/12/03 22:23:54
Can you tweak the git similarity parameter so this
kmadhusu
2012/12/03 23:30:00
I tried with different similiarity(e.g 60, 80, 75,
Lei Zhang
2012/12/03 23:46:27
Aww, too bad. It would be nice to preserve the his
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/media_gallery/linux/mtp_device_delegate_impl_linux.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/file_path.h" | |
9 #include "base/file_util.h" | |
10 #include "base/sequenced_task_runner.h" | |
11 #include "base/string_util.h" | |
12 #include "base/threading/sequenced_worker_pool.h" | |
13 #include "chrome/browser/media_gallery/linux/get_mtp_file_info_worker.h" | |
14 #include "chrome/browser/media_gallery/linux/mtp_device_object_enumerator.h" | |
15 #include "chrome/browser/media_gallery/linux/mtp_device_operations_utils.h" | |
16 #include "chrome/browser/media_gallery/linux/open_mtp_storage_worker.h" | |
17 #include "chrome/browser/media_gallery/linux/read_mtp_directory_worker.h" | |
18 #include "chrome/browser/media_gallery/linux/read_mtp_file_worker.h" | |
19 #include "chrome/browser/media_gallery/linux/recursive_mtp_device_object_enumera tor.h" | |
20 #include "chrome/browser/media_transfer_protocol/media_transfer_protocol_manager .h" | |
21 #include "content/public/browser/browser_thread.h" | |
22 | |
23 using base::Bind; | |
24 using base::PlatformFileError; | |
25 using base::PlatformFileInfo; | |
26 using base::SequencedTaskRunner; | |
27 using content::BrowserThread; | |
28 using fileapi::FileSystemFileUtil; | |
29 | |
30 namespace chrome { | |
31 | |
32 namespace { | |
33 | |
34 // File path separator constant. | |
35 const char kRootPath[] = "/"; | |
36 | |
37 // Does nothing. | |
38 // This method is used to handle the results of | |
39 // MediaTransferProtocolManager::CloseStorage method call. | |
40 void DoNothing(bool error) { | |
41 } | |
42 | |
43 // Closes the device storage on the UI thread. | |
44 void CloseStorageOnUIThread(const std::string& device_handle) { | |
45 DCHECK(!device_handle.empty()); | |
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
47 GetMediaTransferProtocolManager()->CloseStorage(device_handle, | |
48 Bind(&DoNothing)); | |
49 } | |
50 | |
51 // Returns the device relative file path given |file_path|. | |
52 // E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path| | |
53 // is "/usb:2,2:12345", this function returns the device relative path which is | |
54 // "/DCIM". | |
55 std::string GetDeviceRelativePath(const std::string& registered_dev_path, | |
56 const std::string& file_path) { | |
57 DCHECK(!registered_dev_path.empty()); | |
58 DCHECK(!file_path.empty()); | |
59 | |
60 std::string actual_file_path; | |
61 if (registered_dev_path == file_path) { | |
62 actual_file_path = kRootPath; | |
63 } else { | |
64 actual_file_path = file_path; | |
65 ReplaceFirstSubstringAfterOffset(&actual_file_path, 0, | |
66 registered_dev_path.c_str(), ""); | |
67 } | |
68 DCHECK(!actual_file_path.empty()); | |
69 return actual_file_path; | |
70 } | |
71 | |
72 } // namespace | |
73 | |
74 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( | |
75 const std::string& device_location) | |
76 : device_path_(device_location), | |
77 on_task_completed_event_(false, false), | |
78 on_shutdown_event_(true, false) { | |
79 CHECK(!device_path_.empty()); | |
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
81 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); | |
82 base::SequencedWorkerPool::SequenceToken media_sequence_token = | |
83 pool->GetNamedSequenceToken("media-task-runner"); | |
84 media_task_runner_ = pool->GetSequencedTaskRunner(media_sequence_token); | |
85 } | |
86 | |
87 PlatformFileError MTPDeviceDelegateImplLinux::GetFileInfo( | |
88 const FilePath& file_path, | |
89 PlatformFileInfo* file_info) { | |
90 if (!LazyInit()) | |
91 return base::PLATFORM_FILE_ERROR_FAILED; | |
92 | |
93 scoped_refptr<GetMTPFileInfoWorker> worker(new GetMTPFileInfoWorker( | |
94 device_handle_, GetDeviceRelativePath(device_path_, file_path.value()), | |
95 media_task_runner_, &on_task_completed_event_, &on_shutdown_event_)); | |
96 worker->Run(); | |
97 return worker->get_file_info(file_info); | |
98 } | |
99 | |
100 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> | |
101 MTPDeviceDelegateImplLinux::CreateFileEnumerator( | |
102 const FilePath& root, | |
103 bool recursive) { | |
104 if (root.value().empty() || !LazyInit()) { | |
105 return make_scoped_ptr(new FileSystemFileUtil::EmptyFileEnumerator()) | |
106 .PassAs<FileSystemFileUtil::AbstractFileEnumerator>(); | |
107 } | |
108 | |
109 scoped_refptr<ReadMTPDirectoryWorker> worker(new ReadMTPDirectoryWorker( | |
110 device_handle_, GetDeviceRelativePath(device_path_, root.value()), | |
111 media_task_runner_, &on_task_completed_event_, &on_shutdown_event_)); | |
112 worker->Run(); | |
113 | |
114 if (worker->get_file_entries().empty()) { | |
115 return make_scoped_ptr(new FileSystemFileUtil::EmptyFileEnumerator()) | |
116 .PassAs<FileSystemFileUtil::AbstractFileEnumerator>(); | |
117 } | |
118 | |
119 if (recursive) { | |
120 return make_scoped_ptr(new RecursiveMTPDeviceObjectEnumerator( | |
121 device_handle_, media_task_runner_, worker->get_file_entries(), | |
122 &on_task_completed_event_, &on_shutdown_event_)) | |
123 .PassAs<FileSystemFileUtil::AbstractFileEnumerator>(); | |
124 } | |
125 return make_scoped_ptr( | |
126 new MTPDeviceObjectEnumerator(worker->get_file_entries())) | |
127 .PassAs<FileSystemFileUtil::AbstractFileEnumerator>(); | |
128 } | |
129 | |
130 PlatformFileError MTPDeviceDelegateImplLinux::CreateSnapshotFile( | |
131 const FilePath& device_file_path, | |
132 const FilePath& local_path, | |
133 PlatformFileInfo* file_info) { | |
134 if (!LazyInit()) | |
135 return base::PLATFORM_FILE_ERROR_FAILED; | |
136 | |
137 PlatformFileError error = GetFileInfo(device_file_path, file_info); | |
138 if (error != base::PLATFORM_FILE_OK) | |
139 return error; | |
140 | |
141 if (file_info->size <= 0 || file_info->size > kuint32max) | |
142 return base::PLATFORM_FILE_ERROR_FAILED; | |
143 | |
144 scoped_refptr<ReadMTPFileWorker> worker(new ReadMTPFileWorker( | |
145 device_handle_, | |
146 GetDeviceRelativePath(device_path_, device_file_path.value()), | |
147 file_info->size, local_path, media_task_runner_, | |
148 &on_task_completed_event_, &on_shutdown_event_)); | |
149 worker->Run(); | |
150 if (!worker->Succeeded()) | |
151 return base::PLATFORM_FILE_ERROR_FAILED; | |
152 | |
153 // Modify the last modified time to null. This prevents the time stamp | |
154 // verfication in LocalFileStreamReader. | |
155 file_info->last_modified = base::Time(); | |
156 return base::PLATFORM_FILE_OK; | |
157 } | |
158 | |
159 SequencedTaskRunner* MTPDeviceDelegateImplLinux::GetMediaTaskRunner() { | |
160 return media_task_runner_.get(); | |
161 } | |
162 | |
163 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() { | |
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
165 // Caution: This function is called on the IO thread. Access only the thread | |
166 // safe member variables in this function. Do all the clean up operations in | |
167 // DeleteDelegateOnTaskRunner(). | |
168 on_shutdown_event_.Signal(); | |
169 on_task_completed_event_.Signal(); | |
170 media_task_runner_->PostTask( | |
171 FROM_HERE, | |
172 base::Bind(&MTPDeviceDelegateImplLinux::DeleteDelegateOnTaskRunner, | |
173 base::Unretained(this))); | |
174 } | |
175 | |
176 base::WeakPtr<fileapi::MTPDeviceDelegate> MTPDeviceDelegateImplLinux:: | |
177 GetAsWeakPtrOnIOThread() { | |
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
179 base::WeakPtr<fileapi::MTPDeviceDelegate> delegate = AsWeakPtr(); | |
180 // The weak pointer is instantiated on the IO thread, but only accessed on | |
181 // |media_task_runner_|. Therefore, detach from the current thread. | |
182 DetachFromThread(); | |
183 return delegate; | |
184 } | |
185 | |
186 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { | |
187 DCHECK(media_task_runner_->RunsTasksOnCurrentThread()); | |
188 // Do all the clean up operations on DeleteDelegateOnTaskRunner(). | |
189 } | |
190 | |
191 bool MTPDeviceDelegateImplLinux::LazyInit() { | |
192 DCHECK(media_task_runner_); | |
193 DCHECK(media_task_runner_->RunsTasksOnCurrentThread()); | |
194 | |
195 if (!device_handle_.empty()) | |
196 return true; // Already successfully initialized. | |
197 | |
198 std::string storage_name; | |
199 RemoveChars(device_path_, kRootPath, &storage_name); | |
200 DCHECK(!storage_name.empty()); | |
201 scoped_refptr<OpenMTPStorageWorker> worker(new OpenMTPStorageWorker( | |
202 storage_name, media_task_runner_, &on_task_completed_event_, | |
203 &on_shutdown_event_)); | |
204 worker->Run(); | |
205 device_handle_ = worker->device_handle(); | |
206 return !device_handle_.empty(); | |
207 } | |
208 | |
209 void MTPDeviceDelegateImplLinux::DeleteDelegateOnTaskRunner() { | |
210 DCHECK(media_task_runner_->RunsTasksOnCurrentThread()); | |
211 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
212 Bind(&CloseStorageOnUIThread, device_handle_)); | |
213 delete this; | |
214 } | |
215 | |
216 } // namespace chrome | |
OLD | NEW |