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

Side by Side Diff: net/base/directory_lister.cc

Issue 11437: Port directory lister so test shell can view file directories. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 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 | Annotate | Revision Log
« no previous file with comments | « net/base/directory_lister.h ('k') | net/base/net_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 <process.h>
6
7 #include "net/base/directory_lister.h" 5 #include "net/base/directory_lister.h"
8 6
7 #include "base/file_util.h"
9 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/platform_thread.h"
10 #include "net/base/net_errors.h"
10 11
11 namespace net { 12 namespace net {
12 13
13 static const int kFilesPerEvent = 8; 14 static const int kFilesPerEvent = 8;
14 15
15 class DirectoryDataEvent : public Task { 16 class DirectoryDataEvent : public Task {
16 public: 17 public:
17 explicit DirectoryDataEvent(DirectoryLister* d) 18 explicit DirectoryDataEvent(DirectoryLister* d)
18 : lister(d), count(0), error(0) { 19 : lister(d), count(0), error(0) {
19 } 20 }
20 21
21 void Run() { 22 void Run() {
22 if (count) { 23 if (count) {
23 lister->OnReceivedData(data, count); 24 lister->OnReceivedData(data, count);
24 } else { 25 } else {
25 lister->OnDone(error); 26 lister->OnDone(error);
26 } 27 }
27 } 28 }
28 29
29 scoped_refptr<DirectoryLister> lister; 30 scoped_refptr<DirectoryLister> lister;
30 WIN32_FIND_DATA data[kFilesPerEvent]; 31 file_util::FileEnumerator::FindInfo data[kFilesPerEvent];
31 int count; 32 int count, error;
32 DWORD error;
33 }; 33 };
34 34
35 /*static*/ 35 DirectoryLister::DirectoryLister(const std::wstring& dir,
36 unsigned __stdcall DirectoryLister::ThreadFunc(void* param) { 36 DirectoryListerDelegate* delegate)
37 DirectoryLister* self = reinterpret_cast<DirectoryLister*>(param);
38
39 std::wstring pattern = self->directory();
40 if (pattern[pattern.size()-1] != '\\') {
41 pattern.append(L"\\*");
42 } else {
43 pattern.append(L"*");
44 }
45
46 DirectoryDataEvent* e = new DirectoryDataEvent(self);
47
48 HANDLE handle = FindFirstFile(pattern.c_str(), &e->data[e->count]);
49 if (handle == INVALID_HANDLE_VALUE) {
50 e->error = GetLastError();
51 self->message_loop_->PostTask(FROM_HERE, e);
52 e = NULL;
53 } else {
54 do {
55 if (++e->count == kFilesPerEvent) {
56 self->message_loop_->PostTask(FROM_HERE, e);
57 e = new DirectoryDataEvent(self);
58 }
59 } while (!self->was_canceled() && FindNextFile(handle, &e->data[e->count]));
60
61 FindClose(handle);
62
63 if (e->count > 0) {
64 self->message_loop_->PostTask(FROM_HERE, e);
65 e = NULL;
66 }
67
68 // Notify done
69 e = new DirectoryDataEvent(self);
70 self->message_loop_->PostTask(FROM_HERE, e);
71 }
72
73 self->Release();
74 return 0;
75 }
76
77 DirectoryLister::DirectoryLister(const std::wstring& dir, Delegate* delegate)
78 : dir_(dir), 37 : dir_(dir),
38 delegate_(delegate),
79 message_loop_(NULL), 39 message_loop_(NULL),
80 delegate_(delegate),
81 thread_(NULL), 40 thread_(NULL),
82 canceled_(false) { 41 canceled_(false) {
83 DCHECK(!dir.empty()); 42 DCHECK(!dir.empty());
84 } 43 }
85 44
86 DirectoryLister::~DirectoryLister() { 45 DirectoryLister::~DirectoryLister() {
87 if (thread_) 46 if (thread_) {
88 CloseHandle(thread_); 47 PlatformThread::Join(thread_);
48 }
89 } 49 }
90 50
91 bool DirectoryLister::Start() { 51 bool DirectoryLister::Start() {
92 // spawn a thread to enumerate the specified directory 52 // spawn a thread to enumerate the specified directory
93 53
94 // pass events back to the current thread 54 // pass events back to the current thread
95 message_loop_ = MessageLoop::current(); 55 message_loop_ = MessageLoop::current();
96 DCHECK(message_loop_) << "calling thread must have a message loop"; 56 DCHECK(message_loop_) << "calling thread must have a message loop";
97 57
98 AddRef(); // the thread will release us when it is done 58 AddRef(); // the thread will release us when it is done
99 59
100 unsigned thread_id; 60 if (!PlatformThread::Create(0, this, &thread_)) {
101 thread_ = reinterpret_cast<HANDLE>(
102 _beginthreadex(NULL, 0, DirectoryLister::ThreadFunc, this, 0,
103 &thread_id));
104
105 if (!thread_) {
106 Release(); 61 Release();
107 return false; 62 return false;
108 } 63 }
109 64
110 return true; 65 return true;
111 } 66 }
112 67
113 void DirectoryLister::Cancel() { 68 void DirectoryLister::Cancel() {
114 canceled_ = true; 69 canceled_ = true;
115 70
116 if (thread_) { 71 if (thread_) {
117 WaitForSingleObject(thread_, INFINITE); 72 PlatformThread::Join(thread_);
118 CloseHandle(thread_);
119 thread_ = NULL; 73 thread_ = NULL;
120 } 74 }
121 } 75 }
122 76
123 void DirectoryLister::OnReceivedData(const WIN32_FIND_DATA* data, int count) { 77 void DirectoryLister::ThreadMain() {
78 DirectoryDataEvent* e = new DirectoryDataEvent(this);
79
80 if (!file_util::DirectoryExists(directory())) {
81 e->error = net::ERR_FILE_NOT_FOUND;
82 message_loop_->PostTask(FROM_HERE, e);
83 Release();
84 return;
85 }
86
87 file_util::FileEnumerator file_enum(directory(), false,
88 file_util::FileEnumerator::FILES_AND_DIRECTORIES);
89
90 std::wstring filename;
91 while (!was_canceled() && !(filename = file_enum.Next()).empty()) {
92 file_enum.GetFindInfo(&e->data[e->count]);
93
94 if (++e->count == kFilesPerEvent) {
95 message_loop_->PostTask(FROM_HERE, e);
96 e = new DirectoryDataEvent(this);
97 }
98 }
99
100 if (e->count > 0) {
101 message_loop_->PostTask(FROM_HERE, e);
102 e = NULL;
103 }
104
105 // Notify done
106 e = new DirectoryDataEvent(this);
107 message_loop_->PostTask(FROM_HERE, e);
108
109 Release();
110 }
111
112 void DirectoryLister::OnReceivedData(
113 const file_util::FileEnumerator::FindInfo* data, int count) {
124 // Since the delegate can clear itself during the OnListFile callback, we 114 // Since the delegate can clear itself during the OnListFile callback, we
125 // need to null check it during each iteration of the loop. Similarly, it is 115 // need to null check it during each iteration of the loop. Similarly, it is
126 // necessary to check the canceled_ flag to avoid sending data to a delegate 116 // necessary to check the canceled_ flag to avoid sending data to a delegate
127 // who doesn't want anymore. 117 // who doesn't want anymore.
128 for (int i = 0; !canceled_ && delegate_ && i < count; ++i) 118 for (int i = 0; !canceled_ && delegate_ && i < count; ++i)
129 delegate_->OnListFile(data[i]); 119 delegate_->OnListFile(data[i]);
130 } 120 }
131 121
132 void DirectoryLister::OnDone(int error) { 122 void DirectoryLister::OnDone(int error) {
133 // If canceled, we need to report some kind of error, but don't overwrite the 123 // If canceled, we need to report some kind of error, but don't overwrite the
134 // error condition if it is already set. 124 // error condition if it is already set.
135 if (!error && canceled_) 125 if (!error && canceled_)
136 error = ERROR_OPERATION_ABORTED; 126 error = net::ERR_ABORTED;
137 127
138 if (delegate_) 128 if (delegate_)
139 delegate_->OnListDone(error); 129 delegate_->OnListDone(error);
140 } 130 }
141 131
142 } // namespace net 132 } // namespace net
143 133
OLDNEW
« no previous file with comments | « net/base/directory_lister.h ('k') | net/base/net_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698