OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "net/base/directory_lister.h" | 5 #include "net/base/directory_lister.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 #include <vector> |
| 9 |
7 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/i18n/file_util_icu.h" |
8 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
9 #include "base/platform_thread.h" | 13 #include "base/platform_thread.h" |
10 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
11 | 15 |
12 namespace net { | 16 namespace net { |
13 | 17 |
14 static const int kFilesPerEvent = 8; | 18 static const int kFilesPerEvent = 8; |
15 | 19 |
16 class DirectoryDataEvent : public Task { | 20 class DirectoryDataEvent : public Task { |
17 public: | 21 public: |
18 explicit DirectoryDataEvent(DirectoryLister* d) | 22 explicit DirectoryDataEvent(DirectoryLister* d) : lister(d), error(0) { |
19 : lister(d), count(0), error(0) { | 23 // Allocations of the FindInfo aren't super cheap, so reserve space. |
| 24 data.reserve(64); |
20 } | 25 } |
21 | 26 |
22 void Run() { | 27 void Run() { |
23 if (count) { | 28 if (data.empty()) { |
24 lister->OnReceivedData(data, count); | |
25 } else { | |
26 lister->OnDone(error); | 29 lister->OnDone(error); |
| 30 return; |
27 } | 31 } |
| 32 lister->OnReceivedData(&data[0], static_cast<int>(data.size())); |
28 } | 33 } |
29 | 34 |
30 scoped_refptr<DirectoryLister> lister; | 35 scoped_refptr<DirectoryLister> lister; |
31 file_util::FileEnumerator::FindInfo data[kFilesPerEvent]; | 36 std::vector<file_util::FileEnumerator::FindInfo> data; |
32 int count, error; | 37 int error; |
33 }; | 38 }; |
34 | 39 |
| 40 // Comparator for sorting FindInfo's. This uses the locale aware filename |
| 41 // comparison function on the filenames for sorting in the user's locale. |
| 42 static bool CompareFindInfo(const file_util::FileEnumerator::FindInfo& a, |
| 43 const file_util::FileEnumerator::FindInfo& b) { |
| 44 #if defined(OS_WIN) |
| 45 return file_util::LocaleAwareCompareFilenames(FilePath(a.cFileName), |
| 46 FilePath(b.cFileName)); |
| 47 #elif defined(OS_POSIX) |
| 48 return file_util::LocaleAwareCompareFilenames(FilePath(a.filename), |
| 49 FilePath(b.filename)); |
| 50 #endif |
| 51 } |
| 52 |
35 DirectoryLister::DirectoryLister(const FilePath& dir, | 53 DirectoryLister::DirectoryLister(const FilePath& dir, |
36 DirectoryListerDelegate* delegate) | 54 DirectoryListerDelegate* delegate) |
37 : dir_(dir), | 55 : dir_(dir), |
38 delegate_(delegate), | 56 delegate_(delegate), |
39 message_loop_(NULL), | 57 message_loop_(NULL), |
40 thread_(NULL), | 58 thread_(NULL), |
41 canceled_(false) { | 59 canceled_(false) { |
42 DCHECK(!dir.value().empty()); | 60 DCHECK(!dir.value().empty()); |
43 } | 61 } |
44 | 62 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 return; | 102 return; |
85 } | 103 } |
86 | 104 |
87 file_util::FileEnumerator file_enum(dir_, false, | 105 file_util::FileEnumerator file_enum(dir_, false, |
88 static_cast<file_util::FileEnumerator::FILE_TYPE>( | 106 static_cast<file_util::FileEnumerator::FILE_TYPE>( |
89 file_util::FileEnumerator::FILES | | 107 file_util::FileEnumerator::FILES | |
90 file_util::FileEnumerator::DIRECTORIES | | 108 file_util::FileEnumerator::DIRECTORIES | |
91 file_util::FileEnumerator::INCLUDE_DOT_DOT)); | 109 file_util::FileEnumerator::INCLUDE_DOT_DOT)); |
92 | 110 |
93 while (!canceled_ && !(file_enum.Next().value().empty())) { | 111 while (!canceled_ && !(file_enum.Next().value().empty())) { |
94 file_enum.GetFindInfo(&e->data[e->count]); | 112 e->data.push_back(file_util::FileEnumerator::FindInfo()); |
| 113 file_enum.GetFindInfo(&e->data[e->data.size() - 1]); |
95 | 114 |
| 115 /* TODO(brettw) bug 24107: It would be nice to send incremental updates. |
| 116 We gather them all so they can be sorted, but eventually the sorting |
| 117 should be done from JS to give more flexibility in the page. When we do |
| 118 that, we can uncomment this to send incremental updates to the page. |
96 if (++e->count == kFilesPerEvent) { | 119 if (++e->count == kFilesPerEvent) { |
97 message_loop_->PostTask(FROM_HERE, e); | 120 message_loop_->PostTask(FROM_HERE, e); |
98 e = new DirectoryDataEvent(this); | 121 e = new DirectoryDataEvent(this); |
99 } | 122 } |
| 123 */ |
100 } | 124 } |
101 | 125 |
102 if (e->count > 0) { | 126 if (!e->data.empty()) { |
| 127 // Sort the results. See the TODO above (this sort should be removed and we |
| 128 // should do it from JS). |
| 129 std::sort(e->data.begin(), e->data.end(), CompareFindInfo); |
| 130 |
103 message_loop_->PostTask(FROM_HERE, e); | 131 message_loop_->PostTask(FROM_HERE, e); |
104 e = new DirectoryDataEvent(this); | 132 e = new DirectoryDataEvent(this); |
105 } | 133 } |
106 | 134 |
107 // Notify done | 135 // Notify done |
108 Release(); | 136 Release(); |
109 message_loop_->PostTask(FROM_HERE, e); | 137 message_loop_->PostTask(FROM_HERE, e); |
110 } | 138 } |
111 | 139 |
112 void DirectoryLister::OnReceivedData( | 140 void DirectoryLister::OnReceivedData( |
(...skipping 10 matching lines...) Expand all Loading... |
123 // If canceled, we need to report some kind of error, but don't overwrite the | 151 // If canceled, we need to report some kind of error, but don't overwrite the |
124 // error condition if it is already set. | 152 // error condition if it is already set. |
125 if (!error && canceled_) | 153 if (!error && canceled_) |
126 error = net::ERR_ABORTED; | 154 error = net::ERR_ABORTED; |
127 | 155 |
128 if (delegate_) | 156 if (delegate_) |
129 delegate_->OnListDone(error); | 157 delegate_->OnListDone(error); |
130 } | 158 } |
131 | 159 |
132 } // namespace net | 160 } // namespace net |
OLD | NEW |