Index: net/base/directory_lister.cc |
=================================================================== |
--- net/base/directory_lister.cc (revision 56913) |
+++ net/base/directory_lister.cc (working copy) |
@@ -17,8 +17,9 @@ |
static const int kFilesPerEvent = 8; |
+// A task which is used to signal the delegate asynchronously. |
class DirectoryDataEvent : public Task { |
- public: |
+public: |
explicit DirectoryDataEvent(DirectoryLister* d) : lister(d), error(0) { |
// Allocations of the FindInfo aren't super cheap, so reserve space. |
data.reserve(64); |
@@ -33,70 +34,85 @@ |
} |
scoped_refptr<DirectoryLister> lister; |
- std::vector<file_util::FileEnumerator::FindInfo> data; |
+ std::vector<DirectoryLister::DirectoryListerData> data; |
int error; |
}; |
-// Comparator for sorting FindInfo's. This uses the locale aware filename |
+// Comparator for sorting lister results. This uses the locale aware filename |
// comparison function on the filenames for sorting in the user's locale. |
-static bool CompareFindInfoAlpha(const file_util::FileEnumerator::FindInfo& a, |
- const file_util::FileEnumerator::FindInfo& b) { |
+// Static. |
+bool DirectoryLister::CompareAlphaDirsFirst(const DirectoryListerData& a, |
+ const DirectoryListerData& b) { |
// Parent directory before all else. |
- if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a))) |
+ if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a.info))) |
return true; |
- if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b))) |
+ if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b.info))) |
return false; |
// Directories before regular files. |
- bool a_is_directory = file_util::FileEnumerator::IsDirectory(a); |
- bool b_is_directory = file_util::FileEnumerator::IsDirectory(b); |
+ bool a_is_directory = file_util::FileEnumerator::IsDirectory(a.info); |
+ bool b_is_directory = file_util::FileEnumerator::IsDirectory(b.info); |
if (a_is_directory != b_is_directory) |
return a_is_directory; |
return file_util::LocaleAwareCompareFilenames( |
- file_util::FileEnumerator::GetFilename(a), |
- file_util::FileEnumerator::GetFilename(b)); |
+ file_util::FileEnumerator::GetFilename(a.info), |
+ file_util::FileEnumerator::GetFilename(b.info)); |
} |
-static bool CompareFindInfoDate(const file_util::FileEnumerator::FindInfo& a, |
- const file_util::FileEnumerator::FindInfo& b) { |
+// Static. |
+bool DirectoryLister::CompareDate(const DirectoryListerData& a, |
+ const DirectoryListerData& b) { |
// Parent directory before all else. |
- if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a))) |
+ if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a.info))) |
return true; |
- if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b))) |
+ if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b.info))) |
return false; |
// Directories before regular files. |
- bool a_is_directory = file_util::FileEnumerator::IsDirectory(a); |
- bool b_is_directory = file_util::FileEnumerator::IsDirectory(b); |
+ bool a_is_directory = file_util::FileEnumerator::IsDirectory(a.info); |
+ bool b_is_directory = file_util::FileEnumerator::IsDirectory(b.info); |
if (a_is_directory != b_is_directory) |
return a_is_directory; |
#if defined(OS_POSIX) |
- return a.stat.st_mtime > b.stat.st_mtime; |
+ return a.info.stat.st_mtime > b.info.stat.st_mtime; |
#elif defined(OS_WIN) |
- if (a.ftLastWriteTime.dwHighDateTime == b.ftLastWriteTime.dwHighDateTime) { |
- return a.ftLastWriteTime.dwLowDateTime > b.ftLastWriteTime.dwLowDateTime; |
+ if (a.info.ftLastWriteTime.dwHighDateTime == |
+ b.info.ftLastWriteTime.dwHighDateTime) { |
+ return a.info.ftLastWriteTime.dwLowDateTime > |
+ b.info.ftLastWriteTime.dwLowDateTime; |
} else { |
- return a.ftLastWriteTime.dwHighDateTime > b.ftLastWriteTime.dwHighDateTime; |
+ return a.info.ftLastWriteTime.dwHighDateTime > |
+ b.info.ftLastWriteTime.dwHighDateTime; |
} |
#endif |
} |
+// Comparator for sorting find result by paths. This uses the locale-aware |
+// comparison function on the filenames for sorting in the user's locale. |
+// Static. |
+bool DirectoryLister::CompareFullPath(const DirectoryListerData& a, |
+ const DirectoryListerData& b) { |
+ return file_util::LocaleAwareCompareFilenames(a.path, b.path); |
+} |
DirectoryLister::DirectoryLister(const FilePath& dir, |
DirectoryListerDelegate* delegate) |
: dir_(dir), |
+ recursive_(false), |
delegate_(delegate), |
- sort_(DEFAULT), |
+ sort_(ALPHA_DIRS_FIRST), |
message_loop_(NULL), |
thread_(kNullThreadHandle) { |
DCHECK(!dir.value().empty()); |
} |
DirectoryLister::DirectoryLister(const FilePath& dir, |
+ bool recursive, |
SORT_TYPE sort, |
DirectoryListerDelegate* delegate) |
: dir_(dir), |
+ recursive_(false), |
delegate_(delegate), |
sort_(sort), |
message_loop_(NULL), |
@@ -145,16 +161,22 @@ |
Release(); |
return; |
} |
- file_util::FileEnumerator file_enum(dir_, false, |
- static_cast<file_util::FileEnumerator::FILE_TYPE>( |
- file_util::FileEnumerator::FILES | |
- file_util::FileEnumerator::DIRECTORIES | |
- file_util::FileEnumerator::INCLUDE_DOT_DOT)); |
- while (!canceled_.IsSet() && !(file_enum.Next().value().empty())) { |
- e->data.push_back(file_util::FileEnumerator::FindInfo()); |
- file_enum.GetFindInfo(&e->data[e->data.size() - 1]); |
+ int types = file_util::FileEnumerator::FILES | |
+ file_util::FileEnumerator::DIRECTORIES; |
+ if (!recursive_) |
+ types |= file_util::FileEnumerator::INCLUDE_DOT_DOT; |
+ file_util::FileEnumerator file_enum(dir_, recursive_, |
+ static_cast<file_util::FileEnumerator::FILE_TYPE>(types)); |
+ |
+ FilePath path; |
+ while (!canceled_.IsSet() && !(path = file_enum.Next()).empty()) { |
+ DirectoryListerData data; |
+ file_enum.GetFindInfo(&data.info); |
+ data.path = path; |
+ e->data.push_back(data); |
+ |
/* TODO(brettw) bug 24107: It would be nice to send incremental updates. |
We gather them all so they can be sorted, but eventually the sorting |
should be done from JS to give more flexibility in the page. When we do |
@@ -169,11 +191,14 @@ |
if (!e->data.empty()) { |
// Sort the results. See the TODO above (this sort should be removed and we |
// should do it from JS). |
- if (sort_ == DATE) { |
- std::sort(e->data.begin(), e->data.end(), CompareFindInfoDate); |
- } else { |
- std::sort(e->data.begin(), e->data.end(), CompareFindInfoAlpha); |
- } |
+ if (sort_ == DATE) |
+ std::sort(e->data.begin(), e->data.end(), CompareDate); |
+ else if (sort_ == FULL_PATH) |
+ std::sort(e->data.begin(), e->data.end(), CompareFullPath); |
+ else if (sort_ == ALPHA_DIRS_FIRST) |
+ std::sort(e->data.begin(), e->data.end(), CompareAlphaDirsFirst); |
+ else |
+ DCHECK_EQ(NO_SORT, sort_); |
message_loop_->PostTask(FROM_HERE, e); |
e = new DirectoryDataEvent(this); |
@@ -184,8 +209,8 @@ |
message_loop_->PostTask(FROM_HERE, e); |
} |
-void DirectoryLister::OnReceivedData( |
- const file_util::FileEnumerator::FindInfo* data, int count) { |
+void DirectoryLister::OnReceivedData(const DirectoryListerData* data, |
+ int count) { |
// Since the delegate can clear itself during the OnListFile callback, we |
// need to null check it during each iteration of the loop. Similarly, it is |
// necessary to check the canceled_ flag to avoid sending data to a delegate |