Chromium Code Reviews| Index: chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc |
| diff --git a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc |
| index 82bf26ce53bb952fc88eb276b1e4c6eaeefdb1d8..947068fa1f05aec13e28e1b5654fd1586b1ce970 100644 |
| --- a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc |
| +++ b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc |
| @@ -207,6 +207,7 @@ MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { |
| class MTPDeviceDelegateImplLinux::MTPFileNode { |
| public: |
| MTPFileNode(uint32 file_id, |
| + const std::string& file_name, |
| MTPFileNode* parent, |
| FileIdToMTPFileNodeMap* file_id_to_node_map); |
| ~MTPFileNode(); |
| @@ -222,6 +223,7 @@ class MTPDeviceDelegateImplLinux::MTPFileNode { |
| bool DeleteChild(uint32 file_id); |
| uint32 file_id() const { return file_id_; } |
| + const std::string& file_name() const { return file_name_; } |
| MTPFileNode* parent() { return parent_; } |
| private: |
| @@ -229,6 +231,8 @@ class MTPDeviceDelegateImplLinux::MTPFileNode { |
| typedef base::ScopedPtrHashMap<std::string, MTPFileNode> ChildNodes; |
| const uint32 file_id_; |
| + const std::string file_name_; |
| + |
| ChildNodes children_; |
| MTPFileNode* const parent_; |
| FileIdToMTPFileNodeMap* file_id_to_node_map_; |
| @@ -238,9 +242,11 @@ class MTPDeviceDelegateImplLinux::MTPFileNode { |
| MTPDeviceDelegateImplLinux::MTPFileNode::MTPFileNode( |
| uint32 file_id, |
| + const std::string& file_name, |
| MTPFileNode* parent, |
| FileIdToMTPFileNodeMap* file_id_to_node_map) |
| : file_id_(file_id), |
| + file_name_(file_name), |
| parent_(parent), |
| file_id_to_node_map_(file_id_to_node_map) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| @@ -272,7 +278,7 @@ void MTPDeviceDelegateImplLinux::MTPFileNode::EnsureChildExists( |
| children_.set( |
| name, |
| - make_scoped_ptr(new MTPFileNode(id, this, file_id_to_node_map_))); |
| + make_scoped_ptr(new MTPFileNode(id, name, this, file_id_to_node_map_))); |
| } |
| void MTPDeviceDelegateImplLinux::MTPFileNode::ClearNonexistentChildren( |
| @@ -309,7 +315,8 @@ MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( |
| task_in_progress_(false), |
| device_path_(device_location), |
| root_node_(new MTPFileNode(mtpd::kRootFileId, |
| - NULL, |
| + "", // Root node has no name. |
| + NULL, // And no parent node. |
| &file_id_to_node_map_)), |
| weak_ptr_factory_(this) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| @@ -328,6 +335,24 @@ void MTPDeviceDelegateImplLinux::GetFileInfo( |
| const ErrorCallback& error_callback) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| DCHECK(!file_path.empty()); |
| + |
| + // If a ReadDirectory operation is in progress, the file info may already be |
| + // cached. |
| + FileInfoCache::const_iterator it = file_info_cache_.find(file_path); |
| + if (it != file_info_cache_.end()) { |
| + // TODO(thestig): This code is repeated in several places. Combine them. |
| + // e.g. c/b/media_galleries/win/mtp_device_operations_util.cc |
| + const fileapi::DirectoryEntry& cached_file_entry = it->second; |
| + base::File::Info info; |
| + info.size = cached_file_entry.size; |
| + info.is_directory = cached_file_entry.is_directory; |
| + info.is_symbolic_link = false; |
| + info.last_modified = cached_file_entry.last_modified_time; |
| + info.creation_time = base::Time(); |
| + |
| + success_callback.Run(info); |
|
kinaba
2014/08/20 23:10:05
Just a comment.
Ah, I didn't fully understand the
|
| + return; |
| + } |
| base::Closure closure = |
| base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal, |
| weak_ptr_factory_.GetWeakPtr(), |
| @@ -733,6 +758,17 @@ void MTPDeviceDelegateImplLinux::OnDidReadDirectory( |
| DCHECK(it != file_id_to_node_map_.end()); |
| MTPFileNode* dir_node = it->second; |
| + // Traverse the MTPFileNode tree to reconstuct the full path for |dir_id|. |
| + std::deque<std::string> dir_path_parts; |
| + MTPFileNode* parent_node = dir_node; |
| + while (parent_node->parent()) { |
| + dir_path_parts.push_front(parent_node->file_name()); |
| + parent_node = parent_node->parent(); |
| + } |
| + base::FilePath dir_path = device_path_; |
| + for (size_t i = 0; i < dir_path_parts.size(); ++i) |
| + dir_path = dir_path.Append(dir_path_parts[i]); |
| + |
| fileapi::AsyncFileUtil::EntryList normalized_file_list; |
| for (size_t i = 0; i < file_list.size(); ++i) { |
| normalized_file_list.push_back(file_list[i]); |
| @@ -751,6 +787,9 @@ void MTPDeviceDelegateImplLinux::OnDidReadDirectory( |
| // Refresh the in memory tree. |
| dir_node->EnsureChildExists(entry.name, file_id); |
| child_nodes_seen_.insert(entry.name); |
| + |
| + // Add to |file_info_cache_|. |
| + file_info_cache_[dir_path.Append(entry.name)] = entry; |
| } |
| success_callback.Run(normalized_file_list, has_more); |
| @@ -760,6 +799,7 @@ void MTPDeviceDelegateImplLinux::OnDidReadDirectory( |
| // Last call, finish book keeping and continue with the next request. |
| dir_node->ClearNonexistentChildren(child_nodes_seen_); |
| child_nodes_seen_.clear(); |
| + file_info_cache_.clear(); |
| PendingRequestDone(); |
| } |