Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc

Issue 1432403003: Do not call stat() when reading directories via File API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Whitespace cleanup. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <fcntl.h> 7 #include <fcntl.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/numerics/safe_conversions.h" 13 #include "base/numerics/safe_conversions.h"
14 #include "base/posix/eintr_wrapper.h" 14 #include "base/posix/eintr_wrapper.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_split.h" 16 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h"
19 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_servic e.h" 18 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_servic e.h"
20 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h" 19 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
21 #include "net/base/io_buffer.h" 20 #include "net/base/io_buffer.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h" 21 #include "third_party/cros_system_api/dbus/service_constants.h"
23 22
24 namespace { 23 namespace {
25 24
26 // File path separator constant. 25 // File path separator constant.
27 const char kRootPath[] = "/"; 26 const char kRootPath[] = "/";
28 27
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 const ErrorCallback& error_callback) { 545 const ErrorCallback& error_callback) {
547 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 546 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
548 DCHECK(!file_path.empty()); 547 DCHECK(!file_path.empty());
549 548
550 // If a ReadDirectory operation is in progress, the file info may already be 549 // If a ReadDirectory operation is in progress, the file info may already be
551 // cached. 550 // cached.
552 FileInfoCache::const_iterator it = file_info_cache_.find(file_path); 551 FileInfoCache::const_iterator it = file_info_cache_.find(file_path);
553 if (it != file_info_cache_.end()) { 552 if (it != file_info_cache_.end()) {
554 // TODO(thestig): This code is repeated in several places. Combine them. 553 // TODO(thestig): This code is repeated in several places. Combine them.
555 // e.g. c/b/media_galleries/win/mtp_device_operations_util.cc 554 // e.g. c/b/media_galleries/win/mtp_device_operations_util.cc
556 const storage::DirectoryEntry& cached_file_entry = it->second; 555 const MTPDeviceTaskHelper::MTPEntry& cached_file_entry = it->second;
557 base::File::Info info; 556 success_callback.Run(cached_file_entry.file_info);
558 info.size = cached_file_entry.size;
559 info.is_directory = cached_file_entry.is_directory;
560 info.is_symbolic_link = false;
561 info.last_modified = cached_file_entry.last_modified_time;
562 info.creation_time = base::Time();
563
564 success_callback.Run(info);
565 return; 557 return;
566 } 558 }
567 base::Closure closure = 559 base::Closure closure =
568 base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal, 560 base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal,
569 weak_ptr_factory_.GetWeakPtr(), 561 weak_ptr_factory_.GetWeakPtr(),
570 file_path, 562 file_path,
571 success_callback, 563 success_callback,
572 error_callback); 564 error_callback);
573 EnsureInitAndRunTask(PendingTaskInfo(file_path, 565 EnsureInitAndRunTask(PendingTaskInfo(file_path,
574 content::BrowserThread::IO, 566 content::BrowserThread::IO,
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 EnsureInitAndRunTask(PendingTaskInfo( 1209 EnsureInitAndRunTask(PendingTaskInfo(
1218 base::FilePath(), content::BrowserThread::IO, FROM_HERE, closure)); 1210 base::FilePath(), content::BrowserThread::IO, FROM_HERE, closure));
1219 PendingRequestDone(); 1211 PendingRequestDone();
1220 } 1212 }
1221 1213
1222 void MTPDeviceDelegateImplLinux::OnDidReadDirectoryToCreateDirectory( 1214 void MTPDeviceDelegateImplLinux::OnDidReadDirectoryToCreateDirectory(
1223 const std::vector<base::FilePath>& components, 1215 const std::vector<base::FilePath>& components,
1224 const bool exclusive, 1216 const bool exclusive,
1225 const CreateDirectorySuccessCallback& success_callback, 1217 const CreateDirectorySuccessCallback& success_callback,
1226 const ErrorCallback& error_callback, 1218 const ErrorCallback& error_callback,
1227 const storage::AsyncFileUtil::EntryList& /* file_list */, 1219 const storage::AsyncFileUtil::EntryList& /* entries */,
1228 const bool has_more) { 1220 const bool has_more) {
1229 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 1221 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1230 1222
1231 if (has_more) 1223 if (has_more)
1232 return; // Wait until all entries have been read. 1224 return; // Wait until all entries have been read.
1233 1225
1234 const base::Closure closure = 1226 const base::Closure closure =
1235 base::Bind(&MTPDeviceDelegateImplLinux::CreateDirectoryInternal, 1227 base::Bind(&MTPDeviceDelegateImplLinux::CreateDirectoryInternal,
1236 weak_ptr_factory_.GetWeakPtr(), components, exclusive, 1228 weak_ptr_factory_.GetWeakPtr(), components, exclusive,
1237 success_callback, error_callback); 1229 success_callback, error_callback);
1238 EnsureInitAndRunTask(PendingTaskInfo( 1230 EnsureInitAndRunTask(PendingTaskInfo(
1239 base::FilePath(), content::BrowserThread::IO, FROM_HERE, closure)); 1231 base::FilePath(), content::BrowserThread::IO, FROM_HERE, closure));
1240 } 1232 }
1241 1233
1242 void MTPDeviceDelegateImplLinux::OnDidReadDirectoryToDeleteDirectory( 1234 void MTPDeviceDelegateImplLinux::OnDidReadDirectoryToDeleteDirectory(
1243 const base::FilePath& directory_path, 1235 const base::FilePath& directory_path,
1244 const uint32 directory_id, 1236 const uint32 directory_id,
1245 const DeleteDirectorySuccessCallback& success_callback, 1237 const DeleteDirectorySuccessCallback& success_callback,
1246 const ErrorCallback& error_callback, 1238 const ErrorCallback& error_callback,
1247 const storage::AsyncFileUtil::EntryList& entries, 1239 const MTPDeviceTaskHelper::MTPEntries& entries,
1248 const bool has_more) { 1240 const bool has_more) {
1249 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 1241 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1250 DCHECK(!has_more); 1242 DCHECK(!has_more);
1251 1243
1252 if (entries.size() > 0) { 1244 if (entries.size() > 0) {
1253 error_callback.Run(base::File::FILE_ERROR_NOT_EMPTY); 1245 error_callback.Run(base::File::FILE_ERROR_NOT_EMPTY);
1254 } else { 1246 } else {
1255 RunDeleteObjectOnUIThread(directory_path, directory_id, success_callback, 1247 RunDeleteObjectOnUIThread(directory_path, directory_id, success_callback,
1256 error_callback); 1248 error_callback);
1257 } 1249 }
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
1562 const ErrorCallback& callback, 1554 const ErrorCallback& callback,
1563 const base::File::Error error) { 1555 const base::File::Error error) {
1564 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 1556 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1565 1557
1566 callback.Run(base::File::FILE_ERROR_FAILED); 1558 callback.Run(base::File::FILE_ERROR_FAILED);
1567 } 1559 }
1568 1560
1569 void MTPDeviceDelegateImplLinux::OnDidReadDirectory( 1561 void MTPDeviceDelegateImplLinux::OnDidReadDirectory(
1570 uint32 dir_id, 1562 uint32 dir_id,
1571 const ReadDirectorySuccessCallback& success_callback, 1563 const ReadDirectorySuccessCallback& success_callback,
1572 const storage::AsyncFileUtil::EntryList& file_list, 1564 const MTPDeviceTaskHelper::MTPEntries& mtp_entries,
1573 bool has_more) { 1565 bool has_more) {
1574 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 1566 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1575 1567
1576 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id); 1568 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id);
1577 DCHECK(it != file_id_to_node_map_.end()); 1569 DCHECK(it != file_id_to_node_map_.end());
1578 MTPFileNode* dir_node = it->second; 1570 MTPFileNode* dir_node = it->second;
1579 1571
1580 // Traverse the MTPFileNode tree to reconstuct the full path for |dir_id|. 1572 // Traverse the MTPFileNode tree to reconstuct the full path for |dir_id|.
1581 std::deque<std::string> dir_path_parts; 1573 std::deque<std::string> dir_path_parts;
1582 MTPFileNode* parent_node = dir_node; 1574 MTPFileNode* parent_node = dir_node;
1583 while (parent_node->parent()) { 1575 while (parent_node->parent()) {
1584 dir_path_parts.push_front(parent_node->file_name()); 1576 dir_path_parts.push_front(parent_node->file_name());
1585 parent_node = parent_node->parent(); 1577 parent_node = parent_node->parent();
1586 } 1578 }
1587 base::FilePath dir_path = device_path_; 1579 base::FilePath dir_path = device_path_;
1588 for (size_t i = 0; i < dir_path_parts.size(); ++i) 1580 for (size_t i = 0; i < dir_path_parts.size(); ++i)
1589 dir_path = dir_path.Append(dir_path_parts[i]); 1581 dir_path = dir_path.Append(dir_path_parts[i]);
1590 1582
1591 storage::AsyncFileUtil::EntryList normalized_file_list; 1583 storage::AsyncFileUtil::EntryList file_list;
1592 for (size_t i = 0; i < file_list.size(); ++i) { 1584 for (size_t i = 0; i < mtp_entries.size(); ++i) {
Lei Zhang 2015/11/12 07:25:16 for (const auto& mtp_entry : mtp_entries) { ...
mtomasz 2015/11/12 07:48:24 Done.
1593 normalized_file_list.push_back(file_list[i]); 1585 storage::DirectoryEntry entry;
1594 storage::DirectoryEntry& entry = normalized_file_list.back(); 1586 entry.name = mtp_entries[i].name;
1595 1587 entry.is_directory = mtp_entries[i].file_info.is_directory;
1596 // |entry.name| has the file id encoded in it. Decode here. 1588 file_list.push_back(entry);
1597 size_t separator_idx = entry.name.find_last_of(',');
1598 DCHECK_NE(std::string::npos, separator_idx);
1599 std::string file_id_str = entry.name.substr(separator_idx);
1600 file_id_str = file_id_str.substr(1); // Get rid of the comma.
1601 uint32 file_id = 0;
1602 bool ret = base::StringToUint(file_id_str, &file_id);
1603 DCHECK(ret);
1604 entry.name = entry.name.substr(0, separator_idx);
1605 1589
1606 // Refresh the in memory tree. 1590 // Refresh the in memory tree.
1607 dir_node->EnsureChildExists(entry.name, file_id); 1591 dir_node->EnsureChildExists(entry.name, mtp_entries[i].file_id);
1608 child_nodes_seen_.insert(entry.name); 1592 child_nodes_seen_.insert(entry.name);
1609 1593
1610 // Add to |file_info_cache_|. 1594 // Add to |file_info_cache_|.
1611 file_info_cache_[dir_path.Append(entry.name)] = entry; 1595 file_info_cache_[dir_path.Append(entry.name)] = mtp_entries[i];
1612 } 1596 }
1613 1597
1614 success_callback.Run(normalized_file_list, has_more); 1598 success_callback.Run(file_list, has_more);
1615 if (has_more) 1599 if (has_more)
1616 return; // Wait to be called again. 1600 return; // Wait to be called again.
1617 1601
1618 // Last call, finish book keeping and continue with the next request. 1602 // Last call, finish book keeping and continue with the next request.
1619 dir_node->ClearNonexistentChildren(child_nodes_seen_); 1603 dir_node->ClearNonexistentChildren(child_nodes_seen_);
1620 child_nodes_seen_.clear(); 1604 child_nodes_seen_.clear();
1621 file_info_cache_.clear(); 1605 file_info_cache_.clear();
1622 1606
1623 PendingRequestDone(); 1607 PendingRequestDone();
1624 } 1608 }
(...skipping 21 matching lines...) Expand all
1646 void MTPDeviceDelegateImplLinux::OnDidReadBytes( 1630 void MTPDeviceDelegateImplLinux::OnDidReadBytes(
1647 const ReadBytesSuccessCallback& success_callback, 1631 const ReadBytesSuccessCallback& success_callback,
1648 const base::File::Info& file_info, int bytes_read) { 1632 const base::File::Info& file_info, int bytes_read) {
1649 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 1633 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1650 success_callback.Run(file_info, bytes_read); 1634 success_callback.Run(file_info, bytes_read);
1651 PendingRequestDone(); 1635 PendingRequestDone();
1652 } 1636 }
1653 1637
1654 void MTPDeviceDelegateImplLinux::OnDidFillFileCache( 1638 void MTPDeviceDelegateImplLinux::OnDidFillFileCache(
1655 const base::FilePath& path, 1639 const base::FilePath& path,
1656 const storage::AsyncFileUtil::EntryList& /* file_list */, 1640 const storage::AsyncFileUtil::EntryList& /* entries */,
1657 bool has_more) { 1641 bool has_more) {
1658 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 1642 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1659 DCHECK(path.IsParent(pending_tasks_.front().path)); 1643 DCHECK(path.IsParent(pending_tasks_.front().path));
1660 if (has_more) 1644 if (has_more)
1661 return; // Wait until all entries have been read. 1645 return; // Wait until all entries have been read.
1662 pending_tasks_.front().cached_path = path; 1646 pending_tasks_.front().cached_path = path;
1663 } 1647 }
1664 1648
1665 void MTPDeviceDelegateImplLinux::OnFillFileCacheFailed( 1649 void MTPDeviceDelegateImplLinux::OnFillFileCacheFailed(
1666 base::File::Error /* error */) { 1650 base::File::Error /* error */) {
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1905 } 1889 }
1906 } 1890 }
1907 1891
1908 void CreateMTPDeviceAsyncDelegate( 1892 void CreateMTPDeviceAsyncDelegate(
1909 const std::string& device_location, 1893 const std::string& device_location,
1910 const bool read_only, 1894 const bool read_only,
1911 const CreateMTPDeviceAsyncDelegateCallback& callback) { 1895 const CreateMTPDeviceAsyncDelegateCallback& callback) {
1912 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 1896 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1913 callback.Run(new MTPDeviceDelegateImplLinux(device_location, read_only)); 1897 callback.Run(new MTPDeviceDelegateImplLinux(device_location, read_only));
1914 } 1898 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698