OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h" | 5 #include "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> |
| 9 #include <vector> |
8 | 10 |
9 #include "base/bind.h" | 11 #include "base/bind.h" |
10 #include "base/files/file_path.h" | |
11 #include "base/numerics/safe_conversions.h" | 12 #include "base/numerics/safe_conversions.h" |
| 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_split.h" |
12 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
13 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h" | 16 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h" |
14 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_servic
e.h" | 17 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_servic
e.h" |
15 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h" | 18 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h" |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "net/base/io_buffer.h" | 19 #include "net/base/io_buffer.h" |
| 20 #include "third_party/cros_system_api/dbus/service_constants.h" |
18 | 21 |
19 namespace { | 22 namespace { |
20 | 23 |
21 // File path separator constant. | 24 // File path separator constant. |
22 const char kRootPath[] = "/"; | 25 const char kRootPath[] = "/"; |
23 | 26 |
24 // Returns the device relative file path given |file_path|. | 27 // Returns the device relative file path given |file_path|. |
25 // E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path| | 28 // E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path| |
26 // is "/usb:2,2:12345", this function returns the device relative path which is | 29 // is "/usb:2,2:12345", this function returns the device relative path which is |
27 // "DCIM". | 30 // "DCIM". |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 MTPDeviceTaskHelper* task_helper = | 76 MTPDeviceTaskHelper* task_helper = |
74 GetDeviceTaskHelperForStorage(storage_name); | 77 GetDeviceTaskHelperForStorage(storage_name); |
75 if (!task_helper) { | 78 if (!task_helper) { |
76 task_helper = | 79 task_helper = |
77 MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper( | 80 MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper( |
78 storage_name); | 81 storage_name); |
79 } | 82 } |
80 task_helper->OpenStorage(storage_name, reply_callback); | 83 task_helper->OpenStorage(storage_name, reply_callback); |
81 } | 84 } |
82 | 85 |
83 // Enumerates the |root| directory file entries. | 86 // Enumerates the |dir_id| directory file entries. |
84 // | 87 // |
85 // Called on the UI thread to dispatch the request to the | 88 // Called on the UI thread to dispatch the request to the |
86 // MediaTransferProtocolManager. | 89 // MediaTransferProtocolManager. |
87 // | 90 // |
88 // |storage_name| specifies the name of the storage device. | 91 // |storage_name| specifies the name of the storage device. |
89 // |success_callback| is called when the ReadDirectory request succeeds. | 92 // |success_callback| is called when the ReadDirectory request succeeds. |
90 // |error_callback| is called when the ReadDirectory request fails. | 93 // |error_callback| is called when the ReadDirectory request fails. |
91 // |success_callback| and |error_callback| runs on the IO thread. | 94 // |success_callback| and |error_callback| runs on the IO thread. |
92 void ReadDirectoryOnUIThread( | 95 void ReadDirectoryOnUIThread( |
93 const std::string& storage_name, | 96 const std::string& storage_name, |
94 const std::string& root, | 97 uint32 dir_id, |
95 const base::Callback< | 98 const base::Callback< |
96 void(const fileapi::AsyncFileUtil::EntryList&)>& success_callback, | 99 void(const fileapi::AsyncFileUtil::EntryList&)>& success_callback, |
97 const base::Callback<void(base::File::Error)>& error_callback) { | 100 const base::Callback<void(base::File::Error)>& error_callback) { |
98 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 101 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
99 MTPDeviceTaskHelper* task_helper = | 102 MTPDeviceTaskHelper* task_helper = |
100 GetDeviceTaskHelperForStorage(storage_name); | 103 GetDeviceTaskHelperForStorage(storage_name); |
101 if (!task_helper) | 104 if (!task_helper) |
102 return; | 105 return; |
103 task_helper->ReadDirectoryByPath(root, success_callback, error_callback); | 106 task_helper->ReadDirectoryById(dir_id, success_callback, error_callback); |
104 } | 107 } |
105 | 108 |
106 // Gets the |file_path| details. | 109 // Gets the |file_path| details. |
107 // | 110 // |
108 // Called on the UI thread to dispatch the request to the | 111 // Called on the UI thread to dispatch the request to the |
109 // MediaTransferProtocolManager. | 112 // MediaTransferProtocolManager. |
110 // | 113 // |
111 // |storage_name| specifies the name of the storage device. | 114 // |storage_name| specifies the name of the storage device. |
112 // |success_callback| is called when the GetFileInfo request succeeds. | 115 // |success_callback| is called when the GetFileInfo request succeeds. |
113 // |error_callback| is called when the GetFileInfo request fails. | 116 // |error_callback| is called when the GetFileInfo request fails. |
114 // |success_callback| and |error_callback| runs on the IO thread. | 117 // |success_callback| and |error_callback| runs on the IO thread. |
115 void GetFileInfoOnUIThread( | 118 void GetFileInfoOnUIThread( |
116 const std::string& storage_name, | 119 const std::string& storage_name, |
117 const std::string& file_path, | 120 uint32 file_id, |
118 const base::Callback<void(const base::File::Info&)>& success_callback, | 121 const MTPDeviceAsyncDelegate::GetFileInfoSuccessCallback& success_callback, |
119 const base::Callback<void(base::File::Error)>& error_callback) { | 122 const MTPDeviceAsyncDelegate::ErrorCallback& error_callback) { |
120 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 123 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
121 MTPDeviceTaskHelper* task_helper = | 124 MTPDeviceTaskHelper* task_helper = |
122 GetDeviceTaskHelperForStorage(storage_name); | 125 GetDeviceTaskHelperForStorage(storage_name); |
123 if (!task_helper) | 126 if (!task_helper) |
124 return; | 127 return; |
125 task_helper->GetFileInfoByPath(file_path, success_callback, error_callback); | 128 task_helper->GetFileInfoById(file_id, success_callback, error_callback); |
126 } | 129 } |
127 | 130 |
128 // Copies the contents of |device_file_path| to |snapshot_file_path|. | 131 // Copies the contents of |device_file_path| to |snapshot_file_path|. |
129 // | 132 // |
130 // Called on the UI thread to dispatch the request to the | 133 // Called on the UI thread to dispatch the request to the |
131 // MediaTransferProtocolManager. | 134 // MediaTransferProtocolManager. |
132 // | 135 // |
133 // |storage_name| specifies the name of the storage device. | 136 // |storage_name| specifies the name of the storage device. |
134 // |device_file_path| specifies the media device file path. | 137 // |device_file_path| specifies the media device file path. |
135 // |snapshot_file_path| specifies the platform path of the snapshot file. | 138 // |snapshot_file_path| specifies the platform path of the snapshot file. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 if (!task_helper) | 184 if (!task_helper) |
182 return; | 185 return; |
183 task_helper->CloseStorage(); | 186 task_helper->CloseStorage(); |
184 MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper( | 187 MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper( |
185 storage_name); | 188 storage_name); |
186 } | 189 } |
187 | 190 |
188 } // namespace | 191 } // namespace |
189 | 192 |
190 MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo( | 193 MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo( |
| 194 const base::FilePath& path, |
| 195 content::BrowserThread::ID thread_id, |
191 const tracked_objects::Location& location, | 196 const tracked_objects::Location& location, |
192 const base::Closure& task) | 197 const base::Closure& task) |
193 : location(location), | 198 : path(path), |
| 199 thread_id(thread_id), |
| 200 location(location), |
194 task(task) { | 201 task(task) { |
195 } | 202 } |
196 | 203 |
197 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { | 204 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { |
198 } | 205 } |
199 | 206 |
| 207 // Represents a file on the MTP device. |
| 208 // Lives on the IO thread. |
| 209 class MTPDeviceDelegateImplLinux::MTPFileNode { |
| 210 public: |
| 211 MTPFileNode(uint32 file_id, |
| 212 MTPFileNode* parent, |
| 213 FileIdToMTPFileNodeMap* file_id_to_node_map); |
| 214 ~MTPFileNode(); |
| 215 |
| 216 const MTPFileNode* GetChild(const std::string& name) const; |
| 217 |
| 218 void EnsureChildExists(const std::string& name, uint32 id); |
| 219 |
| 220 // Clears all the children, except those in |children_to_keep|. |
| 221 void ClearNonexistentChildren( |
| 222 const std::set<std::string>& children_to_keep); |
| 223 |
| 224 bool DeleteChild(uint32 file_id); |
| 225 |
| 226 uint32 file_id() const { return file_id_; } |
| 227 MTPFileNode* parent() { return parent_; } |
| 228 |
| 229 private: |
| 230 // Container for holding a node's children. |
| 231 typedef base::ScopedPtrHashMap<std::string, MTPFileNode> ChildNodes; |
| 232 |
| 233 const uint32 file_id_; |
| 234 ChildNodes children_; |
| 235 MTPFileNode* const parent_; |
| 236 FileIdToMTPFileNodeMap* file_id_to_node_map_; |
| 237 |
| 238 DISALLOW_COPY_AND_ASSIGN(MTPFileNode); |
| 239 }; |
| 240 |
| 241 MTPDeviceDelegateImplLinux::MTPFileNode::MTPFileNode( |
| 242 uint32 file_id, |
| 243 MTPFileNode* parent, |
| 244 FileIdToMTPFileNodeMap* file_id_to_node_map) |
| 245 : file_id_(file_id), |
| 246 parent_(parent), |
| 247 file_id_to_node_map_(file_id_to_node_map) { |
| 248 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 249 DCHECK(file_id_to_node_map_); |
| 250 DCHECK(!ContainsKey(*file_id_to_node_map_, file_id_)); |
| 251 (*file_id_to_node_map_)[file_id_] = this; |
| 252 } |
| 253 |
| 254 MTPDeviceDelegateImplLinux::MTPFileNode::~MTPFileNode() { |
| 255 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 256 size_t erased = file_id_to_node_map_->erase(file_id_); |
| 257 DCHECK_EQ(1U, erased); |
| 258 } |
| 259 |
| 260 const MTPDeviceDelegateImplLinux::MTPFileNode* |
| 261 MTPDeviceDelegateImplLinux::MTPFileNode::GetChild( |
| 262 const std::string& name) const { |
| 263 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 264 return children_.get(name); |
| 265 } |
| 266 |
| 267 void MTPDeviceDelegateImplLinux::MTPFileNode::EnsureChildExists( |
| 268 const std::string& name, |
| 269 uint32 id) { |
| 270 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 271 const MTPFileNode* child = GetChild(name); |
| 272 if (child && child->file_id() == id) |
| 273 return; |
| 274 |
| 275 children_.set( |
| 276 name, |
| 277 make_scoped_ptr(new MTPFileNode(id, this, file_id_to_node_map_))); |
| 278 } |
| 279 |
| 280 void MTPDeviceDelegateImplLinux::MTPFileNode::ClearNonexistentChildren( |
| 281 const std::set<std::string>& children_to_keep) { |
| 282 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 283 std::set<std::string> children_to_erase; |
| 284 for (ChildNodes::const_iterator it = children_.begin(); |
| 285 it != children_.end(); ++it) { |
| 286 if (ContainsKey(children_to_keep, it->first)) |
| 287 continue; |
| 288 children_to_erase.insert(it->first); |
| 289 } |
| 290 for (std::set<std::string>::iterator it = children_to_erase.begin(); |
| 291 it != children_to_erase.end(); ++it) { |
| 292 children_.take_and_erase(*it); |
| 293 } |
| 294 } |
| 295 |
| 296 bool MTPDeviceDelegateImplLinux::MTPFileNode::DeleteChild(uint32 file_id) { |
| 297 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 298 for (ChildNodes::iterator it = children_.begin(); |
| 299 it != children_.end(); ++it) { |
| 300 if (it->second->file_id() == file_id) { |
| 301 children_.erase(it); |
| 302 return true; |
| 303 } |
| 304 } |
| 305 return false; |
| 306 } |
| 307 |
200 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( | 308 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( |
201 const std::string& device_location) | 309 const std::string& device_location) |
202 : init_state_(UNINITIALIZED), | 310 : init_state_(UNINITIALIZED), |
203 task_in_progress_(false), | 311 task_in_progress_(false), |
204 device_path_(device_location), | 312 device_path_(device_location), |
| 313 root_node_(new MTPFileNode(mtpd::kRootFileId, |
| 314 NULL, |
| 315 &file_id_to_node_map_)), |
205 weak_ptr_factory_(this) { | 316 weak_ptr_factory_(this) { |
206 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 317 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
207 DCHECK(!device_path_.empty()); | 318 DCHECK(!device_path_.empty()); |
208 base::RemoveChars(device_location, kRootPath, &storage_name_); | 319 base::RemoveChars(device_location, kRootPath, &storage_name_); |
209 DCHECK(!storage_name_.empty()); | 320 DCHECK(!storage_name_.empty()); |
210 } | 321 } |
211 | 322 |
212 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { | 323 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { |
213 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 324 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
214 } | 325 } |
215 | 326 |
216 void MTPDeviceDelegateImplLinux::GetFileInfo( | 327 void MTPDeviceDelegateImplLinux::GetFileInfo( |
217 const base::FilePath& file_path, | 328 const base::FilePath& file_path, |
218 const GetFileInfoSuccessCallback& success_callback, | 329 const GetFileInfoSuccessCallback& success_callback, |
219 const ErrorCallback& error_callback) { | 330 const ErrorCallback& error_callback) { |
220 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 331 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
221 DCHECK(!file_path.empty()); | 332 DCHECK(!file_path.empty()); |
222 base::Closure call_closure = | 333 base::Closure closure = |
223 base::Bind(&GetFileInfoOnUIThread, | 334 base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal, |
224 storage_name_, | 335 weak_ptr_factory_.GetWeakPtr(), |
225 GetDeviceRelativePath(device_path_, file_path), | 336 file_path, |
226 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo, | 337 success_callback, |
227 weak_ptr_factory_.GetWeakPtr(), | 338 error_callback); |
228 success_callback), | 339 EnsureInitAndRunTask(PendingTaskInfo(file_path, |
229 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 340 content::BrowserThread::IO, |
230 weak_ptr_factory_.GetWeakPtr(), | 341 FROM_HERE, |
231 error_callback)); | 342 closure)); |
232 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | |
233 } | 343 } |
234 | 344 |
235 void MTPDeviceDelegateImplLinux::ReadDirectory( | 345 void MTPDeviceDelegateImplLinux::ReadDirectory( |
236 const base::FilePath& root, | 346 const base::FilePath& root, |
237 const ReadDirectorySuccessCallback& success_callback, | 347 const ReadDirectorySuccessCallback& success_callback, |
238 const ErrorCallback& error_callback) { | 348 const ErrorCallback& error_callback) { |
239 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 349 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
240 DCHECK(!root.empty()); | 350 DCHECK(!root.empty()); |
241 std::string device_file_relative_path = GetDeviceRelativePath(device_path_, | 351 base::Closure closure = |
242 root); | 352 base::Bind(&MTPDeviceDelegateImplLinux::ReadDirectoryInternal, |
243 base::Closure call_closure = | 353 weak_ptr_factory_.GetWeakPtr(), |
244 base::Bind( | 354 root, |
245 &GetFileInfoOnUIThread, | 355 success_callback, |
246 storage_name_, | 356 error_callback); |
247 device_file_relative_path, | 357 EnsureInitAndRunTask(PendingTaskInfo(root, |
248 base::Bind( | 358 content::BrowserThread::IO, |
249 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory, | 359 FROM_HERE, |
250 weak_ptr_factory_.GetWeakPtr(), | 360 closure)); |
251 device_file_relative_path, | |
252 success_callback, | |
253 error_callback), | |
254 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | |
255 weak_ptr_factory_.GetWeakPtr(), | |
256 error_callback)); | |
257 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | |
258 } | 361 } |
259 | 362 |
260 void MTPDeviceDelegateImplLinux::CreateSnapshotFile( | 363 void MTPDeviceDelegateImplLinux::CreateSnapshotFile( |
261 const base::FilePath& device_file_path, | 364 const base::FilePath& device_file_path, |
262 const base::FilePath& local_path, | 365 const base::FilePath& local_path, |
263 const CreateSnapshotFileSuccessCallback& success_callback, | 366 const CreateSnapshotFileSuccessCallback& success_callback, |
264 const ErrorCallback& error_callback) { | 367 const ErrorCallback& error_callback) { |
265 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 368 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
266 DCHECK(!device_file_path.empty()); | 369 DCHECK(!device_file_path.empty()); |
267 DCHECK(!local_path.empty()); | 370 DCHECK(!local_path.empty()); |
268 std::string device_file_relative_path = | 371 base::Closure closure = |
269 GetDeviceRelativePath(device_path_, device_file_path); | 372 base::Bind(&MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal, |
270 scoped_ptr<SnapshotRequestInfo> request_info( | 373 weak_ptr_factory_.GetWeakPtr(), |
271 new SnapshotRequestInfo(device_file_relative_path, | 374 device_file_path, |
272 local_path, | 375 local_path, |
273 success_callback, | 376 success_callback, |
274 error_callback)); | 377 error_callback); |
275 base::Closure call_closure = | 378 EnsureInitAndRunTask(PendingTaskInfo(device_file_path, |
276 base::Bind( | 379 content::BrowserThread::IO, |
277 &GetFileInfoOnUIThread, | 380 FROM_HERE, |
278 storage_name_, | 381 closure)); |
279 device_file_relative_path, | |
280 base::Bind( | |
281 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile, | |
282 weak_ptr_factory_.GetWeakPtr(), | |
283 base::Passed(&request_info)), | |
284 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | |
285 weak_ptr_factory_.GetWeakPtr(), | |
286 error_callback)); | |
287 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | |
288 } | 382 } |
289 | 383 |
290 bool MTPDeviceDelegateImplLinux::IsStreaming() { | 384 bool MTPDeviceDelegateImplLinux::IsStreaming() { |
291 return true; | 385 return true; |
292 } | 386 } |
293 | 387 |
294 void MTPDeviceDelegateImplLinux::ReadBytes( | 388 void MTPDeviceDelegateImplLinux::ReadBytes( |
295 const base::FilePath& device_file_path, | 389 const base::FilePath& device_file_path, |
296 net::IOBuffer* buf, int64 offset, int buf_len, | 390 net::IOBuffer* buf, int64 offset, int buf_len, |
297 const ReadBytesSuccessCallback& success_callback, | 391 const ReadBytesSuccessCallback& success_callback, |
298 const ErrorCallback& error_callback) { | 392 const ErrorCallback& error_callback) { |
299 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 393 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
300 DCHECK(!device_file_path.empty()); | 394 DCHECK(!device_file_path.empty()); |
301 std::string device_file_relative_path = | 395 base::Closure closure = |
302 GetDeviceRelativePath(device_path_, device_file_path); | 396 base::Bind(&MTPDeviceDelegateImplLinux::ReadBytesInternal, |
303 | 397 weak_ptr_factory_.GetWeakPtr(), |
304 ReadBytesRequest request( | 398 device_file_path, |
305 device_file_relative_path, buf, offset, buf_len, | 399 make_scoped_refptr(buf), |
306 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes, | 400 offset, |
307 weak_ptr_factory_.GetWeakPtr(), success_callback), | 401 buf_len, |
308 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 402 success_callback, |
309 weak_ptr_factory_.GetWeakPtr(), error_callback)); | 403 error_callback); |
310 | 404 EnsureInitAndRunTask(PendingTaskInfo(device_file_path, |
311 base::Closure call_closure = | 405 content::BrowserThread::IO, |
312 base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request)); | 406 FROM_HERE, |
313 | 407 closure)); |
314 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | |
315 } | 408 } |
316 | 409 |
317 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() { | 410 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() { |
318 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 411 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
319 // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object. | 412 // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object. |
320 content::BrowserThread::PostTask( | 413 content::BrowserThread::PostTask( |
321 content::BrowserThread::UI, | 414 content::BrowserThread::UI, |
322 FROM_HERE, | 415 FROM_HERE, |
323 base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_)); | 416 base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_)); |
324 delete this; | 417 delete this; |
325 } | 418 } |
326 | 419 |
| 420 void MTPDeviceDelegateImplLinux::GetFileInfoInternal( |
| 421 const base::FilePath& file_path, |
| 422 const GetFileInfoSuccessCallback& success_callback, |
| 423 const ErrorCallback& error_callback) { |
| 424 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 425 |
| 426 uint32 file_id; |
| 427 if (CachedPathToId(file_path, &file_id)) { |
| 428 GetFileInfoSuccessCallback success_callback_wrapper = |
| 429 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo, |
| 430 weak_ptr_factory_.GetWeakPtr(), |
| 431 success_callback); |
| 432 ErrorCallback error_callback_wrapper = |
| 433 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
| 434 weak_ptr_factory_.GetWeakPtr(), |
| 435 error_callback, |
| 436 file_id); |
| 437 |
| 438 |
| 439 base::Closure closure = base::Bind(&GetFileInfoOnUIThread, |
| 440 storage_name_, |
| 441 file_id, |
| 442 success_callback_wrapper, |
| 443 error_callback_wrapper); |
| 444 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(), |
| 445 content::BrowserThread::UI, |
| 446 FROM_HERE, |
| 447 closure)); |
| 448 } else { |
| 449 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); |
| 450 } |
| 451 PendingRequestDone(); |
| 452 } |
| 453 |
| 454 void MTPDeviceDelegateImplLinux::ReadDirectoryInternal( |
| 455 const base::FilePath& root, |
| 456 const ReadDirectorySuccessCallback& success_callback, |
| 457 const ErrorCallback& error_callback) { |
| 458 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 459 |
| 460 uint32 dir_id; |
| 461 if (CachedPathToId(root, &dir_id)) { |
| 462 GetFileInfoSuccessCallback success_callback_wrapper = |
| 463 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory, |
| 464 weak_ptr_factory_.GetWeakPtr(), |
| 465 dir_id, |
| 466 success_callback, |
| 467 error_callback); |
| 468 ErrorCallback error_callback_wrapper = |
| 469 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
| 470 weak_ptr_factory_.GetWeakPtr(), |
| 471 error_callback, |
| 472 dir_id); |
| 473 base::Closure closure = base::Bind(&GetFileInfoOnUIThread, |
| 474 storage_name_, |
| 475 dir_id, |
| 476 success_callback_wrapper, |
| 477 error_callback_wrapper); |
| 478 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(), |
| 479 content::BrowserThread::UI, |
| 480 FROM_HERE, |
| 481 closure)); |
| 482 } else { |
| 483 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); |
| 484 } |
| 485 PendingRequestDone(); |
| 486 } |
| 487 |
| 488 void MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal( |
| 489 const base::FilePath& device_file_path, |
| 490 const base::FilePath& local_path, |
| 491 const CreateSnapshotFileSuccessCallback& success_callback, |
| 492 const ErrorCallback& error_callback) { |
| 493 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 494 |
| 495 uint32 file_id; |
| 496 if (CachedPathToId(device_file_path, &file_id)) { |
| 497 scoped_ptr<SnapshotRequestInfo> request_info( |
| 498 new SnapshotRequestInfo(file_id, |
| 499 local_path, |
| 500 success_callback, |
| 501 error_callback)); |
| 502 GetFileInfoSuccessCallback success_callback_wrapper = |
| 503 base::Bind( |
| 504 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile, |
| 505 weak_ptr_factory_.GetWeakPtr(), |
| 506 base::Passed(&request_info)); |
| 507 ErrorCallback error_callback_wrapper = |
| 508 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
| 509 weak_ptr_factory_.GetWeakPtr(), |
| 510 error_callback, |
| 511 file_id); |
| 512 base::Closure closure = base::Bind(&GetFileInfoOnUIThread, |
| 513 storage_name_, |
| 514 file_id, |
| 515 success_callback_wrapper, |
| 516 error_callback_wrapper); |
| 517 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(), |
| 518 content::BrowserThread::UI, |
| 519 FROM_HERE, |
| 520 closure)); |
| 521 } else { |
| 522 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); |
| 523 } |
| 524 PendingRequestDone(); |
| 525 } |
| 526 |
| 527 void MTPDeviceDelegateImplLinux::ReadBytesInternal( |
| 528 const base::FilePath& device_file_path, |
| 529 net::IOBuffer* buf, int64 offset, int buf_len, |
| 530 const ReadBytesSuccessCallback& success_callback, |
| 531 const ErrorCallback& error_callback) { |
| 532 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 533 |
| 534 uint32 file_id; |
| 535 if (CachedPathToId(device_file_path, &file_id)) { |
| 536 ReadBytesRequest request( |
| 537 file_id, buf, offset, buf_len, |
| 538 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes, |
| 539 weak_ptr_factory_.GetWeakPtr(), |
| 540 success_callback), |
| 541 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
| 542 weak_ptr_factory_.GetWeakPtr(), |
| 543 error_callback, |
| 544 file_id)); |
| 545 |
| 546 base::Closure closure = |
| 547 base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request)); |
| 548 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(), |
| 549 content::BrowserThread::UI, |
| 550 FROM_HERE, |
| 551 closure)); |
| 552 } else { |
| 553 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); |
| 554 } |
| 555 PendingRequestDone(); |
| 556 } |
| 557 |
327 void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask( | 558 void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask( |
328 const PendingTaskInfo& task_info) { | 559 const PendingTaskInfo& task_info) { |
329 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 560 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
330 if ((init_state_ == INITIALIZED) && !task_in_progress_) { | 561 if ((init_state_ == INITIALIZED) && !task_in_progress_) { |
331 task_in_progress_ = true; | 562 RunTask(task_info); |
332 content::BrowserThread::PostTask(content::BrowserThread::UI, | |
333 task_info.location, | |
334 task_info.task); | |
335 return; | 563 return; |
336 } | 564 } |
337 pending_tasks_.push(task_info); | 565 |
| 566 // Only *Internal functions have empty paths. Since they are the continuation |
| 567 // of the current running task, they get to cut in line. |
| 568 if (task_info.path.empty()) |
| 569 pending_tasks_.push_front(task_info); |
| 570 else |
| 571 pending_tasks_.push_back(task_info); |
| 572 |
338 if (init_state_ == UNINITIALIZED) { | 573 if (init_state_ == UNINITIALIZED) { |
339 init_state_ = PENDING_INIT; | 574 init_state_ = PENDING_INIT; |
340 task_in_progress_ = true; | 575 task_in_progress_ = true; |
341 content::BrowserThread::PostTask( | 576 content::BrowserThread::PostTask( |
342 content::BrowserThread::UI, | 577 content::BrowserThread::UI, |
343 FROM_HERE, | 578 FROM_HERE, |
344 base::Bind(&OpenStorageOnUIThread, | 579 base::Bind(&OpenStorageOnUIThread, |
345 storage_name_, | 580 storage_name_, |
346 base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted, | 581 base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted, |
347 weak_ptr_factory_.GetWeakPtr()))); | 582 weak_ptr_factory_.GetWeakPtr()))); |
348 } | 583 } |
349 } | 584 } |
350 | 585 |
| 586 void MTPDeviceDelegateImplLinux::RunTask(const PendingTaskInfo& task_info) { |
| 587 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 588 DCHECK_EQ(INITIALIZED, init_state_); |
| 589 DCHECK(!task_in_progress_); |
| 590 task_in_progress_ = true; |
| 591 |
| 592 bool need_to_check_cache = !task_info.path.empty(); |
| 593 if (need_to_check_cache) { |
| 594 base::FilePath uncached_path = |
| 595 NextUncachedPathComponent(task_info.path, task_info.cached_path); |
| 596 if (!uncached_path.empty()) { |
| 597 // Save the current task and do a cache lookup first. |
| 598 pending_tasks_.push_front(task_info); |
| 599 FillFileCache(uncached_path); |
| 600 return; |
| 601 } |
| 602 } |
| 603 |
| 604 content::BrowserThread::PostTask(task_info.thread_id, |
| 605 task_info.location, |
| 606 task_info.task); |
| 607 } |
| 608 |
351 void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile( | 609 void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile( |
352 const base::File::Info& file_info) { | 610 const base::File::Info& file_info) { |
353 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 611 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
354 DCHECK(current_snapshot_request_info_.get()); | 612 DCHECK(current_snapshot_request_info_.get()); |
355 DCHECK_GT(file_info.size, 0); | 613 DCHECK_GT(file_info.size, 0); |
356 DCHECK(task_in_progress_); | 614 DCHECK(task_in_progress_); |
357 SnapshotRequestInfo request_info( | 615 SnapshotRequestInfo request_info( |
358 current_snapshot_request_info_->device_file_path, | 616 current_snapshot_request_info_->file_id, |
359 current_snapshot_request_info_->snapshot_file_path, | 617 current_snapshot_request_info_->snapshot_file_path, |
360 base::Bind( | 618 base::Bind( |
361 &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile, | 619 &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile, |
362 weak_ptr_factory_.GetWeakPtr()), | 620 weak_ptr_factory_.GetWeakPtr()), |
363 base::Bind( | 621 base::Bind( |
364 &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError, | 622 &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError, |
365 weak_ptr_factory_.GetWeakPtr())); | 623 weak_ptr_factory_.GetWeakPtr())); |
366 | 624 |
367 base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread, | 625 base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread, |
368 storage_name_, | 626 storage_name_, |
369 request_info, | 627 request_info, |
370 file_info); | 628 file_info); |
371 content::BrowserThread::PostTask(content::BrowserThread::UI, | 629 content::BrowserThread::PostTask(content::BrowserThread::UI, |
372 FROM_HERE, | 630 FROM_HERE, |
373 task_closure); | 631 task_closure); |
374 } | 632 } |
375 | 633 |
376 void MTPDeviceDelegateImplLinux::PendingRequestDone() { | 634 void MTPDeviceDelegateImplLinux::PendingRequestDone() { |
377 DCHECK(task_in_progress_); | 635 DCHECK(task_in_progress_); |
378 task_in_progress_ = false; | 636 task_in_progress_ = false; |
379 ProcessNextPendingRequest(); | 637 ProcessNextPendingRequest(); |
380 } | 638 } |
381 | 639 |
382 void MTPDeviceDelegateImplLinux::ProcessNextPendingRequest() { | 640 void MTPDeviceDelegateImplLinux::ProcessNextPendingRequest() { |
383 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 641 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
384 DCHECK(!task_in_progress_); | 642 DCHECK(!task_in_progress_); |
385 if (pending_tasks_.empty()) | 643 if (pending_tasks_.empty()) |
386 return; | 644 return; |
387 | 645 |
388 task_in_progress_ = true; | 646 PendingTaskInfo task_info = pending_tasks_.front(); |
389 const PendingTaskInfo& task_info = pending_tasks_.front(); | 647 pending_tasks_.pop_front(); |
390 content::BrowserThread::PostTask(content::BrowserThread::UI, | 648 RunTask(task_info); |
391 task_info.location, | |
392 task_info.task); | |
393 pending_tasks_.pop(); | |
394 } | 649 } |
395 | 650 |
396 void MTPDeviceDelegateImplLinux::OnInitCompleted(bool succeeded) { | 651 void MTPDeviceDelegateImplLinux::OnInitCompleted(bool succeeded) { |
397 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 652 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
398 init_state_ = succeeded ? INITIALIZED : UNINITIALIZED; | 653 init_state_ = succeeded ? INITIALIZED : UNINITIALIZED; |
399 PendingRequestDone(); | 654 PendingRequestDone(); |
400 } | 655 } |
401 | 656 |
402 void MTPDeviceDelegateImplLinux::OnDidGetFileInfo( | 657 void MTPDeviceDelegateImplLinux::OnDidGetFileInfo( |
403 const GetFileInfoSuccessCallback& success_callback, | 658 const GetFileInfoSuccessCallback& success_callback, |
404 const base::File::Info& file_info) { | 659 const base::File::Info& file_info) { |
405 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 660 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
406 success_callback.Run(file_info); | 661 success_callback.Run(file_info); |
407 PendingRequestDone(); | 662 PendingRequestDone(); |
408 } | 663 } |
409 | 664 |
410 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory( | 665 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory( |
411 const std::string& root, | 666 uint32 dir_id, |
412 const ReadDirectorySuccessCallback& success_callback, | 667 const ReadDirectorySuccessCallback& success_callback, |
413 const ErrorCallback& error_callback, | 668 const ErrorCallback& error_callback, |
414 const base::File::Info& file_info) { | 669 const base::File::Info& file_info) { |
415 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 670 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
416 DCHECK(task_in_progress_); | 671 DCHECK(task_in_progress_); |
417 if (!file_info.is_directory) { | 672 if (!file_info.is_directory) { |
418 return HandleDeviceFileError(error_callback, | 673 return HandleDeviceFileError(error_callback, |
| 674 dir_id, |
419 base::File::FILE_ERROR_NOT_A_DIRECTORY); | 675 base::File::FILE_ERROR_NOT_A_DIRECTORY); |
420 } | 676 } |
421 | 677 |
422 base::Closure task_closure = | 678 base::Closure task_closure = |
423 base::Bind(&ReadDirectoryOnUIThread, | 679 base::Bind(&ReadDirectoryOnUIThread, |
424 storage_name_, | 680 storage_name_, |
425 root, | 681 dir_id, |
426 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory, | 682 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory, |
427 weak_ptr_factory_.GetWeakPtr(), | 683 weak_ptr_factory_.GetWeakPtr(), |
| 684 dir_id, |
428 success_callback), | 685 success_callback), |
429 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 686 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
430 weak_ptr_factory_.GetWeakPtr(), | 687 weak_ptr_factory_.GetWeakPtr(), |
431 error_callback)); | 688 error_callback, |
| 689 dir_id)); |
432 content::BrowserThread::PostTask(content::BrowserThread::UI, | 690 content::BrowserThread::PostTask(content::BrowserThread::UI, |
433 FROM_HERE, | 691 FROM_HERE, |
434 task_closure); | 692 task_closure); |
435 } | 693 } |
436 | 694 |
437 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile( | 695 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile( |
438 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, | 696 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, |
439 const base::File::Info& file_info) { | 697 const base::File::Info& file_info) { |
440 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 698 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
441 DCHECK(!current_snapshot_request_info_.get()); | 699 DCHECK(!current_snapshot_request_info_.get()); |
442 DCHECK(snapshot_request_info.get()); | 700 DCHECK(snapshot_request_info.get()); |
443 DCHECK(task_in_progress_); | 701 DCHECK(task_in_progress_); |
444 base::File::Error error = base::File::FILE_OK; | 702 base::File::Error error = base::File::FILE_OK; |
445 if (file_info.is_directory) | 703 if (file_info.is_directory) |
446 error = base::File::FILE_ERROR_NOT_A_FILE; | 704 error = base::File::FILE_ERROR_NOT_A_FILE; |
447 else if (file_info.size < 0 || file_info.size > kuint32max) | 705 else if (file_info.size < 0 || file_info.size > kuint32max) |
448 error = base::File::FILE_ERROR_FAILED; | 706 error = base::File::FILE_ERROR_FAILED; |
449 | 707 |
450 if (error != base::File::FILE_OK) | 708 if (error != base::File::FILE_OK) |
451 return HandleDeviceFileError(snapshot_request_info->error_callback, error); | 709 return HandleDeviceFileError(snapshot_request_info->error_callback, |
| 710 snapshot_request_info->file_id, |
| 711 error); |
452 | 712 |
453 base::File::Info snapshot_file_info(file_info); | 713 base::File::Info snapshot_file_info(file_info); |
454 // Modify the last modified time to null. This prevents the time stamp | 714 // Modify the last modified time to null. This prevents the time stamp |
455 // verfication in LocalFileStreamReader. | 715 // verfication in LocalFileStreamReader. |
456 snapshot_file_info.last_modified = base::Time(); | 716 snapshot_file_info.last_modified = base::Time(); |
457 | 717 |
458 current_snapshot_request_info_.reset(snapshot_request_info.release()); | 718 current_snapshot_request_info_.reset(snapshot_request_info.release()); |
459 if (file_info.size == 0) { | 719 if (file_info.size == 0) { |
460 // Empty snapshot file. | 720 // Empty snapshot file. |
461 return OnDidWriteDataIntoSnapshotFile( | 721 return OnDidWriteDataIntoSnapshotFile( |
462 snapshot_file_info, current_snapshot_request_info_->snapshot_file_path); | 722 snapshot_file_info, current_snapshot_request_info_->snapshot_file_path); |
463 } | 723 } |
464 WriteDataIntoSnapshotFile(snapshot_file_info); | 724 WriteDataIntoSnapshotFile(snapshot_file_info); |
465 } | 725 } |
466 | 726 |
467 void MTPDeviceDelegateImplLinux::OnDidReadDirectory( | 727 void MTPDeviceDelegateImplLinux::OnDidReadDirectory( |
| 728 uint32 dir_id, |
468 const ReadDirectorySuccessCallback& success_callback, | 729 const ReadDirectorySuccessCallback& success_callback, |
469 const fileapi::AsyncFileUtil::EntryList& file_list) { | 730 const fileapi::AsyncFileUtil::EntryList& file_list) { |
470 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 731 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
471 success_callback.Run(file_list, false /*no more entries*/); | 732 |
| 733 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id); |
| 734 DCHECK(it != file_id_to_node_map_.end()); |
| 735 MTPFileNode* dir_node = it->second; |
| 736 std::set<std::string> children_to_keep; |
| 737 |
| 738 fileapi::AsyncFileUtil::EntryList normalized_file_list; |
| 739 for (size_t i = 0; i < file_list.size(); ++i) { |
| 740 normalized_file_list.push_back(file_list[i]); |
| 741 fileapi::DirectoryEntry& entry = normalized_file_list.back(); |
| 742 |
| 743 // |entry.name| has the file id encoded in it. Decode here. |
| 744 size_t separator_idx = entry.name.find_last_of(','); |
| 745 DCHECK_NE(std::string::npos, separator_idx); |
| 746 std::string file_id_str = entry.name.substr(separator_idx); |
| 747 file_id_str = file_id_str.substr(1); // Get rid of the comma. |
| 748 uint32 file_id = 0; |
| 749 bool ret = base::StringToUint(file_id_str, &file_id); |
| 750 DCHECK(ret); |
| 751 entry.name = entry.name.substr(0, separator_idx); |
| 752 |
| 753 // Refresh the in memory tree. |
| 754 dir_node->EnsureChildExists(entry.name, file_id); |
| 755 children_to_keep.insert(entry.name); |
| 756 } |
| 757 dir_node->ClearNonexistentChildren(children_to_keep); |
| 758 |
| 759 success_callback.Run(normalized_file_list, false /*no more entries*/); |
472 PendingRequestDone(); | 760 PendingRequestDone(); |
473 } | 761 } |
474 | 762 |
475 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile( | 763 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile( |
476 const base::File::Info& file_info, | 764 const base::File::Info& file_info, |
477 const base::FilePath& snapshot_file_path) { | 765 const base::FilePath& snapshot_file_path) { |
478 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 766 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
479 DCHECK(current_snapshot_request_info_.get()); | 767 DCHECK(current_snapshot_request_info_.get()); |
480 current_snapshot_request_info_->success_callback.Run( | 768 current_snapshot_request_info_->success_callback.Run( |
481 file_info, snapshot_file_path); | 769 file_info, snapshot_file_path); |
(...skipping 11 matching lines...) Expand all Loading... |
493 } | 781 } |
494 | 782 |
495 void MTPDeviceDelegateImplLinux::OnDidReadBytes( | 783 void MTPDeviceDelegateImplLinux::OnDidReadBytes( |
496 const ReadBytesSuccessCallback& success_callback, | 784 const ReadBytesSuccessCallback& success_callback, |
497 const base::File::Info& file_info, int bytes_read) { | 785 const base::File::Info& file_info, int bytes_read) { |
498 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 786 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
499 success_callback.Run(file_info, bytes_read); | 787 success_callback.Run(file_info, bytes_read); |
500 PendingRequestDone(); | 788 PendingRequestDone(); |
501 } | 789 } |
502 | 790 |
| 791 void MTPDeviceDelegateImplLinux::OnDidFillFileCache( |
| 792 const base::FilePath& path, |
| 793 const fileapi::AsyncFileUtil::EntryList& /* file_list */, |
| 794 bool /* has_more */) { |
| 795 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 796 DCHECK(path.IsParent(pending_tasks_.front().path)); |
| 797 pending_tasks_.front().cached_path = path; |
| 798 } |
| 799 |
| 800 void MTPDeviceDelegateImplLinux::OnFillFileCacheFailed( |
| 801 base::File::Error /* error */) { |
| 802 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 803 // When filling the cache fails for the task at the front of the queue, clear |
| 804 // the path of the task so it will not try to do any more caching. Instead, |
| 805 // the task will just run and fail the CachedPathToId() lookup. |
| 806 pending_tasks_.front().path.clear(); |
| 807 } |
| 808 |
503 void MTPDeviceDelegateImplLinux::HandleDeviceFileError( | 809 void MTPDeviceDelegateImplLinux::HandleDeviceFileError( |
504 const ErrorCallback& error_callback, | 810 const ErrorCallback& error_callback, |
| 811 uint32 file_id, |
505 base::File::Error error) { | 812 base::File::Error error) { |
506 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 813 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 814 |
| 815 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(file_id); |
| 816 if (it != file_id_to_node_map_.end()) { |
| 817 MTPFileNode* parent = it->second->parent(); |
| 818 if (parent) { |
| 819 bool ret = parent->DeleteChild(file_id); |
| 820 DCHECK(ret); |
| 821 } |
| 822 } |
507 error_callback.Run(error); | 823 error_callback.Run(error); |
508 PendingRequestDone(); | 824 PendingRequestDone(); |
509 } | 825 } |
510 | 826 |
| 827 base::FilePath MTPDeviceDelegateImplLinux::NextUncachedPathComponent( |
| 828 const base::FilePath& path, |
| 829 const base::FilePath& cached_path) const { |
| 830 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 831 DCHECK(cached_path.empty() || cached_path.IsParent(path)); |
| 832 |
| 833 base::FilePath uncached_path; |
| 834 std::string device_relpath = GetDeviceRelativePath(device_path_, path); |
| 835 if (!device_relpath.empty() && device_relpath != kRootPath) { |
| 836 uncached_path = device_path_; |
| 837 std::vector<std::string> device_relpath_components; |
| 838 base::SplitString(device_relpath, '/', &device_relpath_components); |
| 839 DCHECK(!device_relpath_components.empty()); |
| 840 bool all_components_cached = true; |
| 841 const MTPFileNode* current_node = root_node_.get(); |
| 842 for (size_t i = 0; i < device_relpath_components.size(); ++i) { |
| 843 current_node = current_node->GetChild(device_relpath_components[i]); |
| 844 if (!current_node) { |
| 845 // With a cache miss, check if it is a genuine failure. If so, pretend |
| 846 // the entire |path| is cached, so there is no further attempt to do |
| 847 // more caching. The actual operation will then fail. |
| 848 all_components_cached = |
| 849 !cached_path.empty() && (uncached_path == cached_path); |
| 850 break; |
| 851 } |
| 852 uncached_path = uncached_path.Append(device_relpath_components[i]); |
| 853 } |
| 854 if (all_components_cached) |
| 855 uncached_path.clear(); |
| 856 } |
| 857 return uncached_path; |
| 858 } |
| 859 |
| 860 void MTPDeviceDelegateImplLinux::FillFileCache( |
| 861 const base::FilePath& uncached_path) { |
| 862 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 863 DCHECK(task_in_progress_); |
| 864 |
| 865 ReadDirectorySuccessCallback success_callback = |
| 866 base::Bind(&MTPDeviceDelegateImplLinux::OnDidFillFileCache, |
| 867 weak_ptr_factory_.GetWeakPtr(), |
| 868 uncached_path); |
| 869 ErrorCallback error_callback = |
| 870 base::Bind(&MTPDeviceDelegateImplLinux::OnFillFileCacheFailed, |
| 871 weak_ptr_factory_.GetWeakPtr()); |
| 872 ReadDirectoryInternal(uncached_path, success_callback, error_callback); |
| 873 } |
| 874 |
| 875 |
| 876 bool MTPDeviceDelegateImplLinux::CachedPathToId(const base::FilePath& path, |
| 877 uint32* id) const { |
| 878 DCHECK(id); |
| 879 |
| 880 std::string device_relpath = GetDeviceRelativePath(device_path_, path); |
| 881 if (device_relpath.empty()) |
| 882 return false; |
| 883 std::vector<std::string> device_relpath_components; |
| 884 if (device_relpath != kRootPath) |
| 885 base::SplitString(device_relpath, '/', &device_relpath_components); |
| 886 const MTPFileNode* current_node = root_node_.get(); |
| 887 for (size_t i = 0; i < device_relpath_components.size(); ++i) { |
| 888 current_node = current_node->GetChild(device_relpath_components[i]); |
| 889 if (!current_node) |
| 890 return false; |
| 891 } |
| 892 *id = current_node->file_id(); |
| 893 return true; |
| 894 } |
| 895 |
511 void CreateMTPDeviceAsyncDelegate( | 896 void CreateMTPDeviceAsyncDelegate( |
512 const std::string& device_location, | 897 const std::string& device_location, |
513 const CreateMTPDeviceAsyncDelegateCallback& callback) { | 898 const CreateMTPDeviceAsyncDelegateCallback& callback) { |
514 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 899 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
515 callback.Run(new MTPDeviceDelegateImplLinux(device_location)); | 900 callback.Run(new MTPDeviceDelegateImplLinux(device_location)); |
516 } | 901 } |
OLD | NEW |