diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-20 22:30:13 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-20 22:30:13 +0000 |
commit | 13ef7c08cafb5d39c17a3b3e32f0ecf3a1107e2b (patch) | |
tree | 6bab505d34a79ee6be99702c657364052a850b72 /net/base | |
parent | e4cdc665ff69c7ddff0ce5740592e735a108e0b7 (diff) | |
download | chromium_src-13ef7c08cafb5d39c17a3b3e32f0ecf3a1107e2b.zip chromium_src-13ef7c08cafb5d39c17a3b3e32f0ecf3a1107e2b.tar.gz chromium_src-13ef7c08cafb5d39c17a3b3e32f0ecf3a1107e2b.tar.bz2 |
Port directory lister to allow the linux and mac test shells to display file directories.
This is a revision of r5725. It doesn't break mac build.
Review URL: http://codereview.chromium.org/11507
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5792 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/directory_lister.cc | 112 | ||||
-rw-r--r-- | net/base/directory_lister.h | 30 | ||||
-rw-r--r-- | net/base/directory_lister_unittest.cc | 35 | ||||
-rw-r--r-- | net/base/net_util.cc | 29 | ||||
-rw-r--r-- | net/base/net_util.h | 11 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 19 |
6 files changed, 122 insertions, 114 deletions
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc index 0204ce4..a04aec2 100644 --- a/net/base/directory_lister.cc +++ b/net/base/directory_lister.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <process.h> - #include "net/base/directory_lister.h" +#include "base/file_util.h" #include "base/message_loop.h" +#include "base/platform_thread.h" +#include "net/base/net_errors.h" namespace net { @@ -27,65 +28,24 @@ class DirectoryDataEvent : public Task { } scoped_refptr<DirectoryLister> lister; - WIN32_FIND_DATA data[kFilesPerEvent]; - int count; - DWORD error; + file_util::FileEnumerator::FindInfo data[kFilesPerEvent]; + int count, error; }; -/*static*/ -unsigned __stdcall DirectoryLister::ThreadFunc(void* param) { - DirectoryLister* self = reinterpret_cast<DirectoryLister*>(param); - - std::wstring pattern = self->directory(); - if (pattern[pattern.size()-1] != '\\') { - pattern.append(L"\\*"); - } else { - pattern.append(L"*"); - } - - DirectoryDataEvent* e = new DirectoryDataEvent(self); - - HANDLE handle = FindFirstFile(pattern.c_str(), &e->data[e->count]); - if (handle == INVALID_HANDLE_VALUE) { - e->error = GetLastError(); - self->message_loop_->PostTask(FROM_HERE, e); - e = NULL; - } else { - do { - if (++e->count == kFilesPerEvent) { - self->message_loop_->PostTask(FROM_HERE, e); - e = new DirectoryDataEvent(self); - } - } while (!self->was_canceled() && FindNextFile(handle, &e->data[e->count])); - - FindClose(handle); - - if (e->count > 0) { - self->message_loop_->PostTask(FROM_HERE, e); - e = NULL; - } - - // Notify done - e = new DirectoryDataEvent(self); - self->message_loop_->PostTask(FROM_HERE, e); - } - - self->Release(); - return 0; -} - -DirectoryLister::DirectoryLister(const std::wstring& dir, Delegate* delegate) +DirectoryLister::DirectoryLister(const std::wstring& dir, + DirectoryListerDelegate* delegate) : dir_(dir), - message_loop_(NULL), delegate_(delegate), + message_loop_(NULL), thread_(NULL), canceled_(false) { DCHECK(!dir.empty()); } DirectoryLister::~DirectoryLister() { - if (thread_) - CloseHandle(thread_); + if (thread_) { + PlatformThread::Join(thread_); + } } bool DirectoryLister::Start() { @@ -97,12 +57,7 @@ bool DirectoryLister::Start() { AddRef(); // the thread will release us when it is done - unsigned thread_id; - thread_ = reinterpret_cast<HANDLE>( - _beginthreadex(NULL, 0, DirectoryLister::ThreadFunc, this, 0, - &thread_id)); - - if (!thread_) { + if (!PlatformThread::Create(0, this, &thread_)) { Release(); return false; } @@ -114,13 +69,48 @@ void DirectoryLister::Cancel() { canceled_ = true; if (thread_) { - WaitForSingleObject(thread_, INFINITE); - CloseHandle(thread_); + PlatformThread::Join(thread_); thread_ = NULL; } } -void DirectoryLister::OnReceivedData(const WIN32_FIND_DATA* data, int count) { +void DirectoryLister::ThreadMain() { + DirectoryDataEvent* e = new DirectoryDataEvent(this); + + if (!file_util::DirectoryExists(directory())) { + e->error = net::ERR_FILE_NOT_FOUND; + message_loop_->PostTask(FROM_HERE, e); + Release(); + return; + } + + file_util::FileEnumerator file_enum(directory(), false, + file_util::FileEnumerator::FILES_AND_DIRECTORIES); + + std::wstring filename; + while (!was_canceled() && !(filename = file_enum.Next()).empty()) { + file_enum.GetFindInfo(&e->data[e->count]); + + if (++e->count == kFilesPerEvent) { + message_loop_->PostTask(FROM_HERE, e); + e = new DirectoryDataEvent(this); + } + } + + if (e->count > 0) { + message_loop_->PostTask(FROM_HERE, e); + e = NULL; + } + + // Notify done + e = new DirectoryDataEvent(this); + message_loop_->PostTask(FROM_HERE, e); + + Release(); +} + +void DirectoryLister::OnReceivedData( + const file_util::FileEnumerator::FindInfo* 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 @@ -133,7 +123,7 @@ void DirectoryLister::OnDone(int error) { // If canceled, we need to report some kind of error, but don't overwrite the // error condition if it is already set. if (!error && canceled_) - error = ERROR_OPERATION_ABORTED; + error = net::ERR_ABORTED; if (delegate_) delegate_->OnListDone(error); diff --git a/net/base/directory_lister.h b/net/base/directory_lister.h index 5f826ce..06d1b37 100644 --- a/net/base/directory_lister.h +++ b/net/base/directory_lister.h @@ -5,9 +5,10 @@ #ifndef NET_BASE_DIRECTORY_LISTER_H__ #define NET_BASE_DIRECTORY_LISTER_H__ -#include <windows.h> #include <string> +#include "base/file_util.h" +#include "base/platform_thread.h" #include "base/ref_counted.h" class MessageLoop; @@ -21,16 +22,18 @@ namespace net { // structs over to the main application thread. The consumer of this class // is insulated from any of the multi-threading details. // -class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister> { +class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister>, + public PlatformThread::Delegate { public: // Implement this class to receive directory entries. - class Delegate { + class DirectoryListerDelegate { public: - virtual void OnListFile(const WIN32_FIND_DATA& data) = 0; + virtual void OnListFile( + const file_util::FileEnumerator::FindInfo& data) = 0; virtual void OnListDone(int error) = 0; }; - DirectoryLister(const std::wstring& dir, Delegate* delegate); + DirectoryLister(const std::wstring& dir, DirectoryListerDelegate* delegate); ~DirectoryLister(); // Call this method to start the directory enumeration thread. @@ -42,8 +45,8 @@ class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister> { void Cancel(); // The delegate pointer may be modified at any time. - Delegate* delegate() const { return delegate_; } - void set_delegate(Delegate* d) { delegate_ = d; } + DirectoryListerDelegate* delegate() const { return delegate_; } + void set_delegate(DirectoryListerDelegate* d) { delegate_ = d; } // Returns the directory being enumerated. const std::wstring& directory() const { return dir_; } @@ -51,18 +54,21 @@ class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister> { // Returns true if the directory enumeration was canceled. bool was_canceled() const { return canceled_; } + // PlatformThread::Delegate implementation + void ThreadMain(); + private: friend class DirectoryDataEvent; + friend class ThreadDelegate; - void OnReceivedData(const WIN32_FIND_DATA* data, int count); + void OnReceivedData(const file_util::FileEnumerator::FindInfo* data, + int count); void OnDone(int error); - static unsigned __stdcall ThreadFunc(void* param); - std::wstring dir_; - Delegate* delegate_; + DirectoryListerDelegate* delegate_; MessageLoop* message_loop_; - HANDLE thread_; + PlatformThreadHandle thread_; bool canceled_; }; diff --git a/net/base/directory_lister_unittest.cc b/net/base/directory_lister_unittest.cc index 03b23ba..8f80466 100644 --- a/net/base/directory_lister_unittest.cc +++ b/net/base/directory_lister_unittest.cc @@ -2,23 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/file_path.h" +#include "base/file_util.h" #include "base/message_loop.h" #include "base/path_service.h" #include "net/base/directory_lister.h" +#include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" namespace { - -class DirectoryListerTest : public testing::Test { -}; - +class DirectoryListerTest : public testing::Test {}; } -class DirectoryListerDelegate : public net::DirectoryLister::Delegate { +class ListerDelegate : public net::DirectoryLister::DirectoryListerDelegate { public: - DirectoryListerDelegate() : error_(-1) { + ListerDelegate() : error_(-1) { } - void OnListFile(const WIN32_FIND_DATA& data) { + void OnListFile(const file_util::FileEnumerator::FindInfo& data) { } void OnListDone(int error) { error_ = error; @@ -30,34 +30,33 @@ class DirectoryListerDelegate : public net::DirectoryLister::Delegate { }; TEST(DirectoryListerTest, BigDirTest) { - std::wstring windows_path; - ASSERT_TRUE(PathService::Get(base::DIR_WINDOWS, &windows_path)); + FilePath path; + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &path)); - DirectoryListerDelegate delegate; + ListerDelegate delegate; scoped_refptr<net::DirectoryLister> lister = - new net::DirectoryLister(windows_path, &delegate); + new net::DirectoryLister(path.ToWStringHack(), &delegate); lister->Start(); MessageLoop::current()->Run(); - EXPECT_EQ(delegate.error(), ERROR_SUCCESS); + EXPECT_EQ(delegate.error(), net::OK); } TEST(DirectoryListerTest, CancelTest) { - std::wstring windows_path; - ASSERT_TRUE(PathService::Get(base::DIR_WINDOWS, &windows_path)); + FilePath path; + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &path)); - DirectoryListerDelegate delegate; + ListerDelegate delegate; scoped_refptr<net::DirectoryLister> lister = - new net::DirectoryLister(windows_path, &delegate); + new net::DirectoryLister(path.ToWStringHack(), &delegate); lister->Start(); lister->Cancel(); MessageLoop::current()->Run(); - EXPECT_EQ(delegate.error(), ERROR_OPERATION_ABORTED); + EXPECT_EQ(delegate.error(), net::ERR_ABORTED); EXPECT_EQ(lister->was_canceled(), true); } - diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 1617d85..9636df5 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -23,6 +23,7 @@ #include "net/base/net_util.h" #include "base/basictypes.h" +#include "base/file_path.h" #include "base/file_util.h" #include "base/logging.h" #include "base/path_service.h" @@ -797,15 +798,25 @@ std::string CanonicalizeHost(const std::wstring& host, bool* is_ip_address) { WideToUTF8(host.c_str(), host.length(), &converted_host); return CanonicalizeHost(converted_host, is_ip_address); } - -#ifdef OS_WIN + std::string GetDirectoryListingHeader(const std::string& title) { +#if defined(OS_WIN) static const StringPiece header(NetModule::GetResource(IDR_DIR_HEADER_HTML)); if (header.empty()) { NOTREACHED() << "expected resource not found"; } - std::string result(header.data(), header.size()); +#elif defined(OS_POSIX) + // TODO(estade): Temporary hack. Remove these platform #ifdefs when we + // have implemented resources for non-Windows platforms. + LOG(INFO) << "FIXME: hacked resource loading"; + FilePath path; + PathService::Get(base::DIR_EXE, &path); + path = path.Append("../../net/base/dir_header.html"); + std::string result; + file_util::ReadFileToString(path.ToWStringHack(), &result); +#endif + result.append("<script>start("); string_escape::JavascriptDoubleQuote(title, true, &result); result.append(");</script>\n"); @@ -814,16 +825,16 @@ std::string GetDirectoryListingHeader(const std::string& title) { } std::string GetDirectoryListingEntry(const std::string& name, - DWORD attrib, + bool is_dir, int64 size, - const FILETIME* modified) { + const Time& modified) { std::string result; result.append("<script>addRow("); string_escape::JavascriptDoubleQuote(name, true, &result); result.append(","); string_escape::JavascriptDoubleQuote( EscapePath(name), true, &result); - if (attrib & FILE_ATTRIBUTE_DIRECTORY) { + if (is_dir) { result.append(",1,"); } else { result.append(",0,"); @@ -836,9 +847,8 @@ std::string GetDirectoryListingEntry(const std::string& name, std::wstring modified_str; // |modified| can be NULL in FTP listings. - if (modified) { - Time time(Time::FromFileTime(*modified)); - modified_str = base::TimeFormatShortDateAndTime(time); + if (!modified.is_null()) { + modified_str = base::TimeFormatShortDateAndTime(modified); } string_escape::JavascriptDoubleQuote(modified_str, true, &result); @@ -846,7 +856,6 @@ std::string GetDirectoryListingEntry(const std::string& name, return result; } -#endif std::wstring StripWWW(const std::wstring& text) { const std::wstring www(L"www."); diff --git a/net/base/net_util.h b/net/base/net_util.h index 7adfc57..f8f49b8 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -19,6 +19,10 @@ class GURL; +namespace base { +class Time; +} + namespace net { // Given the full path to a file name, creates a file: URL. The returned URL @@ -95,15 +99,12 @@ void IDNToUnicode(const char* host, std::string CanonicalizeHost(const std::string& host, bool* is_ip_address); std::string CanonicalizeHost(const std::wstring& host, bool* is_ip_address); -#ifdef OS_WIN -// TODO: Port GetDirectoryListingEntry for OSX and linux. // Call these functions to get the html for a directory listing. // They will pass non-7bit-ascii characters unescaped, allowing // the browser to interpret the encoding (utf8, etc). std::string GetDirectoryListingHeader(const std::string& title); -std::string GetDirectoryListingEntry(const std::string& name, DWORD attrib, - int64 size, const FILETIME* modified); -#endif +std::string GetDirectoryListingEntry(const std::string& name, bool is_dir, + int64 size, const base::Time& modified); // If text starts with "www." it is removed, otherwise text is returned // unmodified. diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index 22fb7d4..d1def1c 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -5,6 +5,7 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/string_util.h" +#include "base/time.h" #include "googleurl/src/gurl.h" #include "net/base/net_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -704,9 +705,9 @@ namespace { struct GetDirectoryListingEntryCase { const char* name; - DWORD file_attrib; + bool is_dir; int64 filesize; - FILETIME* modified; + base::Time time; const char* expected; }; @@ -714,21 +715,23 @@ struct GetDirectoryListingEntryCase { TEST(NetUtilTest, GetDirectoryListingEntry) { const GetDirectoryListingEntryCase test_cases[] = { {"Foo", - 0, + false, 10000, - NULL, + base::Time(), "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"}, {"quo\"tes", - 0, + false, 10000, - NULL, + base::Time(), "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>\n"}, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { const std::string results = net::GetDirectoryListingEntry( - test_cases[i].name, test_cases[i].file_attrib, - test_cases[i].filesize, test_cases[i].modified); + test_cases[i].name, + test_cases[i].is_dir, + test_cases[i].filesize, + test_cases[i].time); EXPECT_EQ(test_cases[i].expected, results); } } |