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 <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 } | 200 } |
201 | 201 |
202 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { | 202 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { |
203 } | 203 } |
204 | 204 |
205 // Represents a file on the MTP device. | 205 // Represents a file on the MTP device. |
206 // Lives on the IO thread. | 206 // Lives on the IO thread. |
207 class MTPDeviceDelegateImplLinux::MTPFileNode { | 207 class MTPDeviceDelegateImplLinux::MTPFileNode { |
208 public: | 208 public: |
209 MTPFileNode(uint32 file_id, | 209 MTPFileNode(uint32 file_id, |
210 const std::string& file_name, | |
210 MTPFileNode* parent, | 211 MTPFileNode* parent, |
211 FileIdToMTPFileNodeMap* file_id_to_node_map); | 212 FileIdToMTPFileNodeMap* file_id_to_node_map); |
212 ~MTPFileNode(); | 213 ~MTPFileNode(); |
213 | 214 |
214 const MTPFileNode* GetChild(const std::string& name) const; | 215 const MTPFileNode* GetChild(const std::string& name) const; |
215 | 216 |
216 void EnsureChildExists(const std::string& name, uint32 id); | 217 void EnsureChildExists(const std::string& name, uint32 id); |
217 | 218 |
218 // Clears all the children, except those in |children_to_keep|. | 219 // Clears all the children, except those in |children_to_keep|. |
219 void ClearNonexistentChildren( | 220 void ClearNonexistentChildren( |
220 const std::set<std::string>& children_to_keep); | 221 const std::set<std::string>& children_to_keep); |
221 | 222 |
222 bool DeleteChild(uint32 file_id); | 223 bool DeleteChild(uint32 file_id); |
223 | 224 |
224 uint32 file_id() const { return file_id_; } | 225 uint32 file_id() const { return file_id_; } |
226 const std::string& file_name() const { return file_name_; } | |
225 MTPFileNode* parent() { return parent_; } | 227 MTPFileNode* parent() { return parent_; } |
226 | 228 |
227 private: | 229 private: |
228 // Container for holding a node's children. | 230 // Container for holding a node's children. |
229 typedef base::ScopedPtrHashMap<std::string, MTPFileNode> ChildNodes; | 231 typedef base::ScopedPtrHashMap<std::string, MTPFileNode> ChildNodes; |
230 | 232 |
231 const uint32 file_id_; | 233 const uint32 file_id_; |
234 const std::string file_name_; | |
235 | |
232 ChildNodes children_; | 236 ChildNodes children_; |
233 MTPFileNode* const parent_; | 237 MTPFileNode* const parent_; |
234 FileIdToMTPFileNodeMap* file_id_to_node_map_; | 238 FileIdToMTPFileNodeMap* file_id_to_node_map_; |
235 | 239 |
236 DISALLOW_COPY_AND_ASSIGN(MTPFileNode); | 240 DISALLOW_COPY_AND_ASSIGN(MTPFileNode); |
237 }; | 241 }; |
238 | 242 |
239 MTPDeviceDelegateImplLinux::MTPFileNode::MTPFileNode( | 243 MTPDeviceDelegateImplLinux::MTPFileNode::MTPFileNode( |
240 uint32 file_id, | 244 uint32 file_id, |
245 const std::string& file_name, | |
241 MTPFileNode* parent, | 246 MTPFileNode* parent, |
242 FileIdToMTPFileNodeMap* file_id_to_node_map) | 247 FileIdToMTPFileNodeMap* file_id_to_node_map) |
243 : file_id_(file_id), | 248 : file_id_(file_id), |
249 file_name_(file_name), | |
244 parent_(parent), | 250 parent_(parent), |
245 file_id_to_node_map_(file_id_to_node_map) { | 251 file_id_to_node_map_(file_id_to_node_map) { |
246 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 252 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
247 DCHECK(file_id_to_node_map_); | 253 DCHECK(file_id_to_node_map_); |
248 DCHECK(!ContainsKey(*file_id_to_node_map_, file_id_)); | 254 DCHECK(!ContainsKey(*file_id_to_node_map_, file_id_)); |
249 (*file_id_to_node_map_)[file_id_] = this; | 255 (*file_id_to_node_map_)[file_id_] = this; |
250 } | 256 } |
251 | 257 |
252 MTPDeviceDelegateImplLinux::MTPFileNode::~MTPFileNode() { | 258 MTPDeviceDelegateImplLinux::MTPFileNode::~MTPFileNode() { |
253 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 259 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
(...skipping 11 matching lines...) Expand all Loading... | |
265 void MTPDeviceDelegateImplLinux::MTPFileNode::EnsureChildExists( | 271 void MTPDeviceDelegateImplLinux::MTPFileNode::EnsureChildExists( |
266 const std::string& name, | 272 const std::string& name, |
267 uint32 id) { | 273 uint32 id) { |
268 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 274 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
269 const MTPFileNode* child = GetChild(name); | 275 const MTPFileNode* child = GetChild(name); |
270 if (child && child->file_id() == id) | 276 if (child && child->file_id() == id) |
271 return; | 277 return; |
272 | 278 |
273 children_.set( | 279 children_.set( |
274 name, | 280 name, |
275 make_scoped_ptr(new MTPFileNode(id, this, file_id_to_node_map_))); | 281 make_scoped_ptr(new MTPFileNode(id, name, this, file_id_to_node_map_))); |
276 } | 282 } |
277 | 283 |
278 void MTPDeviceDelegateImplLinux::MTPFileNode::ClearNonexistentChildren( | 284 void MTPDeviceDelegateImplLinux::MTPFileNode::ClearNonexistentChildren( |
279 const std::set<std::string>& children_to_keep) { | 285 const std::set<std::string>& children_to_keep) { |
280 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 286 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
281 std::set<std::string> children_to_erase; | 287 std::set<std::string> children_to_erase; |
282 for (ChildNodes::const_iterator it = children_.begin(); | 288 for (ChildNodes::const_iterator it = children_.begin(); |
283 it != children_.end(); ++it) { | 289 it != children_.end(); ++it) { |
284 if (ContainsKey(children_to_keep, it->first)) | 290 if (ContainsKey(children_to_keep, it->first)) |
285 continue; | 291 continue; |
(...skipping 16 matching lines...) Expand all Loading... | |
302 } | 308 } |
303 return false; | 309 return false; |
304 } | 310 } |
305 | 311 |
306 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( | 312 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( |
307 const std::string& device_location) | 313 const std::string& device_location) |
308 : init_state_(UNINITIALIZED), | 314 : init_state_(UNINITIALIZED), |
309 task_in_progress_(false), | 315 task_in_progress_(false), |
310 device_path_(device_location), | 316 device_path_(device_location), |
311 root_node_(new MTPFileNode(mtpd::kRootFileId, | 317 root_node_(new MTPFileNode(mtpd::kRootFileId, |
312 NULL, | 318 "", // Root node has no name. |
319 NULL, // And no parent node. | |
313 &file_id_to_node_map_)), | 320 &file_id_to_node_map_)), |
314 weak_ptr_factory_(this) { | 321 weak_ptr_factory_(this) { |
315 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 322 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
316 DCHECK(!device_path_.empty()); | 323 DCHECK(!device_path_.empty()); |
317 base::RemoveChars(device_location, kRootPath, &storage_name_); | 324 base::RemoveChars(device_location, kRootPath, &storage_name_); |
318 DCHECK(!storage_name_.empty()); | 325 DCHECK(!storage_name_.empty()); |
319 } | 326 } |
320 | 327 |
321 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { | 328 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { |
322 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 329 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
323 } | 330 } |
324 | 331 |
325 void MTPDeviceDelegateImplLinux::GetFileInfo( | 332 void MTPDeviceDelegateImplLinux::GetFileInfo( |
326 const base::FilePath& file_path, | 333 const base::FilePath& file_path, |
327 const GetFileInfoSuccessCallback& success_callback, | 334 const GetFileInfoSuccessCallback& success_callback, |
328 const ErrorCallback& error_callback) { | 335 const ErrorCallback& error_callback) { |
329 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 336 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
330 DCHECK(!file_path.empty()); | 337 DCHECK(!file_path.empty()); |
338 | |
339 // If a ReadDirectory operation is in progress, the file info may already be | |
340 // cached. | |
341 FileInfoCache::const_iterator it = file_info_cache_.find(file_path); | |
342 if (it != file_info_cache_.end()) { | |
343 // TODO(thestig): This code is repeated in several places. Combine them. | |
344 // e.g. c/b/media_galleries/win/mtp_device_operations_util.cc | |
345 const fileapi::DirectoryEntry& cached_file_entry = it->second; | |
346 base::File::Info info; | |
347 info.size = cached_file_entry.size; | |
348 info.is_directory = cached_file_entry.is_directory; | |
349 info.is_symbolic_link = false; | |
350 info.last_modified = cached_file_entry.last_modified_time; | |
351 info.creation_time = base::Time(); | |
352 | |
353 success_callback.Run(info); | |
kinaba
2014/08/20 23:10:05
Just a comment.
Ah, I didn't fully understand the
| |
354 return; | |
355 } | |
331 base::Closure closure = | 356 base::Closure closure = |
332 base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal, | 357 base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal, |
333 weak_ptr_factory_.GetWeakPtr(), | 358 weak_ptr_factory_.GetWeakPtr(), |
334 file_path, | 359 file_path, |
335 success_callback, | 360 success_callback, |
336 error_callback); | 361 error_callback); |
337 EnsureInitAndRunTask(PendingTaskInfo(file_path, | 362 EnsureInitAndRunTask(PendingTaskInfo(file_path, |
338 content::BrowserThread::IO, | 363 content::BrowserThread::IO, |
339 FROM_HERE, | 364 FROM_HERE, |
340 closure)); | 365 closure)); |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 uint32 dir_id, | 751 uint32 dir_id, |
727 const ReadDirectorySuccessCallback& success_callback, | 752 const ReadDirectorySuccessCallback& success_callback, |
728 const fileapi::AsyncFileUtil::EntryList& file_list, | 753 const fileapi::AsyncFileUtil::EntryList& file_list, |
729 bool has_more) { | 754 bool has_more) { |
730 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 755 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
731 | 756 |
732 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id); | 757 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id); |
733 DCHECK(it != file_id_to_node_map_.end()); | 758 DCHECK(it != file_id_to_node_map_.end()); |
734 MTPFileNode* dir_node = it->second; | 759 MTPFileNode* dir_node = it->second; |
735 | 760 |
761 // Traverse the MTPFileNode tree to reconstuct the full path for |dir_id|. | |
762 std::deque<std::string> dir_path_parts; | |
763 MTPFileNode* parent_node = dir_node; | |
764 while (parent_node->parent()) { | |
765 dir_path_parts.push_front(parent_node->file_name()); | |
766 parent_node = parent_node->parent(); | |
767 } | |
768 base::FilePath dir_path = device_path_; | |
769 for (size_t i = 0; i < dir_path_parts.size(); ++i) | |
770 dir_path = dir_path.Append(dir_path_parts[i]); | |
771 | |
736 fileapi::AsyncFileUtil::EntryList normalized_file_list; | 772 fileapi::AsyncFileUtil::EntryList normalized_file_list; |
737 for (size_t i = 0; i < file_list.size(); ++i) { | 773 for (size_t i = 0; i < file_list.size(); ++i) { |
738 normalized_file_list.push_back(file_list[i]); | 774 normalized_file_list.push_back(file_list[i]); |
739 fileapi::DirectoryEntry& entry = normalized_file_list.back(); | 775 fileapi::DirectoryEntry& entry = normalized_file_list.back(); |
740 | 776 |
741 // |entry.name| has the file id encoded in it. Decode here. | 777 // |entry.name| has the file id encoded in it. Decode here. |
742 size_t separator_idx = entry.name.find_last_of(','); | 778 size_t separator_idx = entry.name.find_last_of(','); |
743 DCHECK_NE(std::string::npos, separator_idx); | 779 DCHECK_NE(std::string::npos, separator_idx); |
744 std::string file_id_str = entry.name.substr(separator_idx); | 780 std::string file_id_str = entry.name.substr(separator_idx); |
745 file_id_str = file_id_str.substr(1); // Get rid of the comma. | 781 file_id_str = file_id_str.substr(1); // Get rid of the comma. |
746 uint32 file_id = 0; | 782 uint32 file_id = 0; |
747 bool ret = base::StringToUint(file_id_str, &file_id); | 783 bool ret = base::StringToUint(file_id_str, &file_id); |
748 DCHECK(ret); | 784 DCHECK(ret); |
749 entry.name = entry.name.substr(0, separator_idx); | 785 entry.name = entry.name.substr(0, separator_idx); |
750 | 786 |
751 // Refresh the in memory tree. | 787 // Refresh the in memory tree. |
752 dir_node->EnsureChildExists(entry.name, file_id); | 788 dir_node->EnsureChildExists(entry.name, file_id); |
753 child_nodes_seen_.insert(entry.name); | 789 child_nodes_seen_.insert(entry.name); |
790 | |
791 // Add to |file_info_cache_|. | |
792 file_info_cache_[dir_path.Append(entry.name)] = entry; | |
754 } | 793 } |
755 | 794 |
756 success_callback.Run(normalized_file_list, has_more); | 795 success_callback.Run(normalized_file_list, has_more); |
757 if (has_more) | 796 if (has_more) |
758 return; // Wait to be called again. | 797 return; // Wait to be called again. |
759 | 798 |
760 // Last call, finish book keeping and continue with the next request. | 799 // Last call, finish book keeping and continue with the next request. |
761 dir_node->ClearNonexistentChildren(child_nodes_seen_); | 800 dir_node->ClearNonexistentChildren(child_nodes_seen_); |
762 child_nodes_seen_.clear(); | 801 child_nodes_seen_.clear(); |
802 file_info_cache_.clear(); | |
763 | 803 |
764 PendingRequestDone(); | 804 PendingRequestDone(); |
765 } | 805 } |
766 | 806 |
767 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile( | 807 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile( |
768 const base::File::Info& file_info, | 808 const base::File::Info& file_info, |
769 const base::FilePath& snapshot_file_path) { | 809 const base::FilePath& snapshot_file_path) { |
770 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 810 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
771 DCHECK(current_snapshot_request_info_.get()); | 811 DCHECK(current_snapshot_request_info_.get()); |
772 current_snapshot_request_info_->success_callback.Run( | 812 current_snapshot_request_info_->success_callback.Run( |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
898 *id = current_node->file_id(); | 938 *id = current_node->file_id(); |
899 return true; | 939 return true; |
900 } | 940 } |
901 | 941 |
902 void CreateMTPDeviceAsyncDelegate( | 942 void CreateMTPDeviceAsyncDelegate( |
903 const std::string& device_location, | 943 const std::string& device_location, |
904 const CreateMTPDeviceAsyncDelegateCallback& callback) { | 944 const CreateMTPDeviceAsyncDelegateCallback& callback) { |
905 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 945 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
906 callback.Run(new MTPDeviceDelegateImplLinux(device_location)); | 946 callback.Run(new MTPDeviceDelegateImplLinux(device_location)); |
907 } | 947 } |
OLD | NEW |