diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-19 23:04:29 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-19 23:04:29 +0000 |
commit | 721c3f17a7fb36edaa17f607a11db9c82ba720ca (patch) | |
tree | c78e993a5474acdb2751c222db8787d7aa482301 /net | |
parent | f785ad125747f9125c952c7e74f2154098ee15a9 (diff) | |
download | chromium_src-721c3f17a7fb36edaa17f607a11db9c82ba720ca.zip chromium_src-721c3f17a7fb36edaa17f607a11db9c82ba720ca.tar.gz chromium_src-721c3f17a7fb36edaa17f607a11db9c82ba720ca.tar.bz2 |
Port directory lister so test shell can view file directories.
Review URL: http://codereview.chromium.org/11437
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5725 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/directory_lister.cc | 112 | ||||
-rw-r--r-- | net/base/directory_lister.h | 30 | ||||
-rw-r--r-- | net/base/net_util.cc | 25 | ||||
-rw-r--r-- | net/base/net_util.h | 11 | ||||
-rw-r--r-- | net/net_lib.scons | 2 | ||||
-rw-r--r-- | net/url_request/url_request_file_dir_job.cc | 42 | ||||
-rw-r--r-- | net/url_request/url_request_file_dir_job.h | 10 | ||||
-rw-r--r-- | net/url_request/url_request_file_job.cc | 4 | ||||
-rw-r--r-- | net/url_request/url_request_ftp_job.cc | 7 |
9 files changed, 130 insertions, 113 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/net_util.cc b/net/base/net_util.cc index 05419fb..3946c6b 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" @@ -798,12 +799,22 @@ std::string CanonicalizeHost(const std::wstring& host, bool* is_ip_address) { return CanonicalizeHost(converted_host, is_ip_address); } -#ifdef OS_WIN std::string GetDirectoryListingHeader(const std::string& title) { +#if defined(OS_WIN) std::string result = NetModule::GetResource(IDR_DIR_HEADER_HTML); if (result.empty()) { NOTREACHED() << "expected resource not found"; } +#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); @@ -813,16 +824,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,"); @@ -835,9 +846,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); @@ -845,7 +855,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/net_lib.scons b/net/net_lib.scons index 707216f..0e0b329 100644 --- a/net/net_lib.scons +++ b/net/net_lib.scons @@ -110,11 +110,9 @@ if env['PLATFORM'] in ('posix', 'darwin'): # Remove files that still need to be ported from the input_files list. # TODO(port): delete files from this list as they get ported. to_be_ported_files = [ - 'base/directory_lister.cc', 'base/ssl_config_service.cc', 'http/http_transaction_winhttp.cc', 'http/winhttp_request_throttle.cc', - 'url_request/url_request_file_dir_job.cc', 'url_request/url_request_ftp_job.cc', ] for remove in to_be_ported_files: diff --git a/net/url_request/url_request_file_dir_job.cc b/net/url_request/url_request_file_dir_job.cc index 731d741..3685107 100644 --- a/net/url_request/url_request_file_dir_job.cc +++ b/net/url_request/url_request_file_dir_job.cc @@ -7,16 +7,18 @@ #include "base/file_util.h" #include "base/message_loop.h" #include "base/string_util.h" +#include "base/time.h" #include "googleurl/src/gurl.h" #include "net/base/net_util.h" -#include "net/base/wininet_util.h" #include "net/url_request/url_request.h" +#if defined(OS_POSIX) +#include <sys/stat.h> +#endif + using std::string; using std::wstring; -using net::WinInetUtil; - URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request, const wstring& dir_path) : URLRequestJob(request), @@ -97,12 +99,8 @@ bool URLRequestFileDirJob::GetCharset(string* charset) { return true; } -void URLRequestFileDirJob::OnListFile(const WIN32_FIND_DATA& data) { - FILETIME local_time; - FileTimeToLocalFileTime(&data.ftLastWriteTime, &local_time); - int64 size = (static_cast<unsigned __int64>(data.nFileSizeHigh) << 32) | - data.nFileSizeLow; - +void URLRequestFileDirJob::OnListFile( + const file_util::FileEnumerator::FindInfo& data) { // We wait to write out the header until we get the first file, so that we // can catch errors from DirectoryLister and show an error page. if (!wrote_header_) { @@ -110,11 +108,27 @@ void URLRequestFileDirJob::OnListFile(const WIN32_FIND_DATA& data) { wrote_header_ = true; } +#if defined(OS_WIN) + FILETIME local_time; + ::FileTimeToLocalFileTime(&data.ftLastWriteTime, &local_time); + int64 size = (static_cast<unsigned __int64>(data.nFileSizeHigh) << 32) | + data.nFileSizeLow; + data_.append(net::GetDirectoryListingEntry( - WideToUTF8(data.cFileName), data.dwFileAttributes, size, &local_time)); + WideToUTF8(data.cFileName), + (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false, + size, + base::Time::FromFileTime(local_time))); - // TODO(darin): coalesce more? +#elif defined(OS_POSIX) + data_.append(net::GetDirectoryListingEntry( + data.filename.c_str(), + S_ISDIR(data.stat.st_mode), + data.stat.st_size, + base::Time::FromTimeT(data.stat.st_mtime))); +#endif + // TODO(darin): coalesce more? CompleteRead(); } @@ -123,8 +137,7 @@ void URLRequestFileDirJob::OnListDone(int error) { if (error) { read_pending_ = false; - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - WinInetUtil::OSErrorToNetError(error))); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, error)); } else if (canceled_) { read_pending_ = false; NotifyCanceled(); @@ -176,7 +189,8 @@ void URLRequestFileDirJob::CompleteRead() { NotifyReadComplete(bytes_read); } else { NOTREACHED(); - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0)); // TODO: Better error code. + // TODO: Better error code. + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0)); } } } diff --git a/net/url_request/url_request_file_dir_job.h b/net/url_request/url_request_file_dir_job.h index d8e7d43..afbb56b 100644 --- a/net/url_request/url_request_file_dir_job.h +++ b/net/url_request/url_request_file_dir_job.h @@ -5,11 +5,13 @@ #ifndef NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__ #define NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__ +#include "base/file_util.h" #include "net/base/directory_lister.h" #include "net/url_request/url_request_job.h" -class URLRequestFileDirJob : public URLRequestJob, - public net::DirectoryLister::Delegate { +class URLRequestFileDirJob + : public URLRequestJob, + public net::DirectoryLister::DirectoryListerDelegate { public: URLRequestFileDirJob(URLRequest* request, const std::wstring& dir_path); virtual ~URLRequestFileDirJob(); @@ -22,8 +24,8 @@ class URLRequestFileDirJob : public URLRequestJob, virtual bool GetMimeType(std::string* mime_type); virtual bool GetCharset(std::string* charset); - // DirectoryLister::Delegate methods: - virtual void OnListFile(const WIN32_FIND_DATA& data); + // DirectoryLister::DirectoryListerDelegate methods: + virtual void OnListFile(const file_util::FileEnumerator::FindInfo& data); virtual void OnListDone(int error); private: diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc index 608dc64..5c823d8 100644 --- a/net/url_request/url_request_file_job.cc +++ b/net/url_request/url_request_file_job.cc @@ -28,9 +28,7 @@ #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/url_request/url_request.h" -#if defined(OS_WIN) #include "net/url_request/url_request_file_dir_job.h" -#endif #if defined(OS_WIN) class URLRequestFileJob::AsyncResolver : @@ -76,10 +74,8 @@ URLRequestJob* URLRequestFileJob::Factory( std::wstring file_path; if (net::FileURLToFilePath(request->url(), &file_path)) { if (file_path[file_path.size() - 1] == file_util::kPathSeparator) { -#if defined(OS_WIN) // Only directories have trailing slashes. return new URLRequestFileDirJob(request, file_path); -#endif } } diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc index 9cd7ca9..7b72118 100644 --- a/net/url_request/url_request_ftp_job.cc +++ b/net/url_request/url_request_ftp_job.cc @@ -9,6 +9,7 @@ #include "base/message_loop.h" #include "base/string_util.h" +#include "base/time.h" #include "net/base/auth.h" #include "net/base/load_flags.h" #include "net/base/net_util.h" @@ -378,8 +379,8 @@ void URLRequestFtpJob::OnFindFile(DWORD last_error) { // We don't know the encoding, and can't assume utf8, so pass the 8bit // directly to the browser for it to decide. string file_entry = net::GetDirectoryListingEntry( - find_data_.cFileName, find_data_.dwFileAttributes, size, - &find_data_.ftLastWriteTime); + find_data_.cFileName, false, size, + base::Time::FromFileTime(find_data_.ftLastWriteTime)); WriteData(&file_entry, true); FindNextFile(); @@ -401,7 +402,7 @@ void URLRequestFtpJob::OnStartDirectoryTraversal() { // If this isn't top level directory (i.e. the path isn't "/",) add a link to // the parent directory. if (request_->url().path().length() > 1) - html.append(net::GetDirectoryListingEntry("..", 0, 0, NULL)); + html.append(net::GetDirectoryListingEntry("..", false, 0, base::Time())); WriteData(&html, true); |