0

Port directory lister to posix.

Fix of issue 11437.

Review URL: http://codereview.chromium.org/11293

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5730 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
estade@chromium.org
2008-11-19 23:52:02 +00:00
parent e4bac199fa
commit 5dce90240e
12 changed files with 182 additions and 132 deletions

@@ -14,6 +14,7 @@
#include <windows.h> #include <windows.h>
#elif defined(OS_POSIX) #elif defined(OS_POSIX)
#include <fts.h> #include <fts.h>
#include <sys/stat.h>
#endif #endif
#include <stdio.h> #include <stdio.h>
@@ -323,6 +324,15 @@ bool SetCurrentDirectory(const std::wstring& current_directory);
// program where latency does not matter. This class is blocking. // program where latency does not matter. This class is blocking.
class FileEnumerator { class FileEnumerator {
public: public:
#if defined(OS_WIN)
typedef WIN32_FIND_DATA FindInfo;
#elif defined(OS_POSIX)
typedef struct {
struct stat stat;
std::string filename;
} FindInfo;
#endif
enum FILE_TYPE { enum FILE_TYPE {
FILES = 0x1, FILES = 0x1,
DIRECTORIES = 0x2, DIRECTORIES = 0x2,
@@ -361,6 +371,9 @@ class FileEnumerator {
// Returns an empty string if there are no more results. // Returns an empty string if there are no more results.
std::wstring Next(); std::wstring Next();
// Write the file info into |info|.
void GetFindInfo(FindInfo* info);
private: private:
std::wstring root_path_; std::wstring root_path_;
bool recursive_; bool recursive_;
@@ -380,6 +393,7 @@ class FileEnumerator {
HANDLE find_handle_; HANDLE find_handle_;
#elif defined(OS_POSIX) #elif defined(OS_POSIX)
FTS* fts_; FTS* fts_;
FTSENT* fts_ent_;
#endif #endif
DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator); DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator);

@@ -409,6 +409,16 @@ FileEnumerator::~FileEnumerator() {
fts_close(fts_); fts_close(fts_);
} }
void FileEnumerator::GetFindInfo(FindInfo* info) {
DCHECK(info);
if (!is_in_find_op_)
return;
memcpy(&(info->stat), fts_ent_->fts_statp, sizeof(info->stat));
info->filename.assign(fts_ent_->fts_name);
}
// As it stands, this method calls itself recursively when the next item of // As it stands, this method calls itself recursively when the next item of
// the fts enumeration doesn't match (type, pattern, etc.). In the case of // the fts enumeration doesn't match (type, pattern, etc.). In the case of
// large directories with many files this can be quite deep. // large directories with many files this can be quite deep.
@@ -417,12 +427,12 @@ std::wstring FileEnumerator::Next() {
if (!is_in_find_op_) { if (!is_in_find_op_) {
if (pending_paths_.empty()) if (pending_paths_.empty())
return std::wstring(); return std::wstring();
// The last find FindFirstFile operation is done, prepare a new one. // The last find FindFirstFile operation is done, prepare a new one.
root_path_ = pending_paths_.top(); root_path_ = pending_paths_.top();
TrimTrailingSeparator(&root_path_); TrimTrailingSeparator(&root_path_);
pending_paths_.pop(); pending_paths_.pop();
// Start a new find operation. // Start a new find operation.
int ftsflags = FTS_LOGICAL; int ftsflags = FTS_LOGICAL;
char top_dir[PATH_MAX]; char top_dir[PATH_MAX];
@@ -433,41 +443,41 @@ std::wstring FileEnumerator::Next() {
return Next(); return Next();
is_in_find_op_ = true; is_in_find_op_ = true;
} }
FTSENT* fts_ent = fts_read(fts_); fts_ent_ = fts_read(fts_);
if (fts_ent == NULL) { if (fts_ent_ == NULL) {
fts_close(fts_); fts_close(fts_);
fts_ = NULL; fts_ = NULL;
is_in_find_op_ = false; is_in_find_op_ = false;
return Next(); return Next();
} }
// Level 0 is the top, which is always skipped. // Level 0 is the top, which is always skipped.
if (fts_ent->fts_level == 0) if (fts_ent_->fts_level == 0)
return Next(); return Next();
// Patterns are only matched on the items in the top-most directory. // Patterns are only matched on the items in the top-most directory.
// (see Windows implementation) // (see Windows implementation)
if (fts_ent->fts_level == 1 && pattern_.length() > 0) { if (fts_ent_->fts_level == 1 && pattern_.length() > 0) {
if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent->fts_path, 0) != 0) { if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent_->fts_path, 0) != 0) {
if (fts_ent->fts_info == FTS_D) if (fts_ent_->fts_info == FTS_D)
fts_set(fts_, fts_ent, FTS_SKIP); fts_set(fts_, fts_ent_, FTS_SKIP);
return Next(); return Next();
} }
} }
std::wstring cur_file(UTF8ToWide(fts_ent->fts_path)); std::wstring cur_file(UTF8ToWide(fts_ent_->fts_path));
if (fts_ent->fts_info == FTS_D) { if (fts_ent_->fts_info == FTS_D) {
// If not recursive, then prune children. // If not recursive, then prune children.
if (!recursive_) if (!recursive_)
fts_set(fts_, fts_ent, FTS_SKIP); fts_set(fts_, fts_ent_, FTS_SKIP);
return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next();
} else if (fts_ent->fts_info == FTS_F) { } else if (fts_ent_->fts_info == FTS_F) {
return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); return (file_type_ & FileEnumerator::FILES) ? cur_file : Next();
} }
// TODO(erikkay) - verify that the other fts_info types aren't interesting // TODO(erikkay) - verify that the other fts_info types aren't interesting
return Next(); return Next();
} }
} // namespace file_util } // namespace file_util

@@ -625,6 +625,15 @@ FileEnumerator::~FileEnumerator() {
FindClose(find_handle_); FindClose(find_handle_);
} }
void FileEnumerator::GetFindInfo(FindInfo* info) {
DCHECK(info);
if (!is_in_find_op_)
return;
memcpy(info, &find_data_, sizeof(*info));
}
std::wstring FileEnumerator::Next() { std::wstring FileEnumerator::Next() {
if (!is_in_find_op_) { if (!is_in_find_op_) {
if (pending_paths_.empty()) if (pending_paths_.empty())

@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <process.h>
#include "net/base/directory_lister.h" #include "net/base/directory_lister.h"
#include "base/file_util.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/platform_thread.h"
#include "net/base/net_errors.h"
namespace net { namespace net {
@@ -27,65 +28,24 @@ class DirectoryDataEvent : public Task {
} }
scoped_refptr<DirectoryLister> lister; scoped_refptr<DirectoryLister> lister;
WIN32_FIND_DATA data[kFilesPerEvent]; file_util::FileEnumerator::FindInfo data[kFilesPerEvent];
int count; int count, error;
DWORD error;
}; };
/*static*/ DirectoryLister::DirectoryLister(const std::wstring& dir,
unsigned __stdcall DirectoryLister::ThreadFunc(void* param) { DirectoryListerDelegate* delegate)
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)
: dir_(dir), : dir_(dir),
message_loop_(NULL),
delegate_(delegate), delegate_(delegate),
message_loop_(NULL),
thread_(NULL), thread_(NULL),
canceled_(false) { canceled_(false) {
DCHECK(!dir.empty()); DCHECK(!dir.empty());
} }
DirectoryLister::~DirectoryLister() { DirectoryLister::~DirectoryLister() {
if (thread_) if (thread_) {
CloseHandle(thread_); PlatformThread::Join(thread_);
}
} }
bool DirectoryLister::Start() { bool DirectoryLister::Start() {
@@ -97,12 +57,7 @@ bool DirectoryLister::Start() {
AddRef(); // the thread will release us when it is done AddRef(); // the thread will release us when it is done
unsigned thread_id; if (!PlatformThread::Create(0, this, &thread_)) {
thread_ = reinterpret_cast<HANDLE>(
_beginthreadex(NULL, 0, DirectoryLister::ThreadFunc, this, 0,
&thread_id));
if (!thread_) {
Release(); Release();
return false; return false;
} }
@@ -114,13 +69,48 @@ void DirectoryLister::Cancel() {
canceled_ = true; canceled_ = true;
if (thread_) { if (thread_) {
WaitForSingleObject(thread_, INFINITE); PlatformThread::Join(thread_);
CloseHandle(thread_);
thread_ = NULL; 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 // 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 // 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 // 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 // If canceled, we need to report some kind of error, but don't overwrite the
// error condition if it is already set. // error condition if it is already set.
if (!error && canceled_) if (!error && canceled_)
error = ERROR_OPERATION_ABORTED; error = net::ERR_ABORTED;
if (delegate_) if (delegate_)
delegate_->OnListDone(error); delegate_->OnListDone(error);

@@ -5,9 +5,10 @@
#ifndef NET_BASE_DIRECTORY_LISTER_H__ #ifndef NET_BASE_DIRECTORY_LISTER_H__
#define NET_BASE_DIRECTORY_LISTER_H__ #define NET_BASE_DIRECTORY_LISTER_H__
#include <windows.h>
#include <string> #include <string>
#include "base/file_util.h"
#include "base/platform_thread.h"
#include "base/ref_counted.h" #include "base/ref_counted.h"
class MessageLoop; class MessageLoop;
@@ -21,16 +22,18 @@ namespace net {
// structs over to the main application thread. The consumer of this class // structs over to the main application thread. The consumer of this class
// is insulated from any of the multi-threading details. // 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: public:
// Implement this class to receive directory entries. // Implement this class to receive directory entries.
class Delegate { class DirectoryListerDelegate {
public: 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; virtual void OnListDone(int error) = 0;
}; };
DirectoryLister(const std::wstring& dir, Delegate* delegate); DirectoryLister(const std::wstring& dir, DirectoryListerDelegate* delegate);
~DirectoryLister(); ~DirectoryLister();
// Call this method to start the directory enumeration thread. // Call this method to start the directory enumeration thread.
@@ -42,8 +45,8 @@ class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister> {
void Cancel(); void Cancel();
// The delegate pointer may be modified at any time. // The delegate pointer may be modified at any time.
Delegate* delegate() const { return delegate_; } DirectoryListerDelegate* delegate() const { return delegate_; }
void set_delegate(Delegate* d) { delegate_ = d; } void set_delegate(DirectoryListerDelegate* d) { delegate_ = d; }
// Returns the directory being enumerated. // Returns the directory being enumerated.
const std::wstring& directory() const { return dir_; } 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. // Returns true if the directory enumeration was canceled.
bool was_canceled() const { return canceled_; } bool was_canceled() const { return canceled_; }
// PlatformThread::Delegate implementation
void ThreadMain();
private: private:
friend class DirectoryDataEvent; 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); void OnDone(int error);
static unsigned __stdcall ThreadFunc(void* param);
std::wstring dir_; std::wstring dir_;
Delegate* delegate_; DirectoryListerDelegate* delegate_;
MessageLoop* message_loop_; MessageLoop* message_loop_;
HANDLE thread_; PlatformThreadHandle thread_;
bool canceled_; bool canceled_;
}; };

@@ -23,6 +23,7 @@
#include "net/base/net_util.h" #include "net/base/net_util.h"
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/file_path.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/path_service.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); return CanonicalizeHost(converted_host, is_ip_address);
} }
#ifdef OS_WIN
std::string GetDirectoryListingHeader(const std::string& title) { std::string GetDirectoryListingHeader(const std::string& title) {
#if defined(OS_WIN)
std::string result = NetModule::GetResource(IDR_DIR_HEADER_HTML); std::string result = NetModule::GetResource(IDR_DIR_HEADER_HTML);
if (result.empty()) { if (result.empty()) {
NOTREACHED() << "expected resource not found"; 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("); result.append("<script>start(");
string_escape::JavascriptDoubleQuote(title, true, &result); string_escape::JavascriptDoubleQuote(title, true, &result);
@@ -813,16 +824,16 @@ std::string GetDirectoryListingHeader(const std::string& title) {
} }
std::string GetDirectoryListingEntry(const std::string& name, std::string GetDirectoryListingEntry(const std::string& name,
DWORD attrib, bool is_dir,
int64 size, int64 size,
const FILETIME* modified) { const Time& modified) {
std::string result; std::string result;
result.append("<script>addRow("); result.append("<script>addRow(");
string_escape::JavascriptDoubleQuote(name, true, &result); string_escape::JavascriptDoubleQuote(name, true, &result);
result.append(","); result.append(",");
string_escape::JavascriptDoubleQuote( string_escape::JavascriptDoubleQuote(
EscapePath(name), true, &result); EscapePath(name), true, &result);
if (attrib & FILE_ATTRIBUTE_DIRECTORY) { if (is_dir) {
result.append(",1,"); result.append(",1,");
} else { } else {
result.append(",0,"); result.append(",0,");
@@ -835,9 +846,8 @@ std::string GetDirectoryListingEntry(const std::string& name,
std::wstring modified_str; std::wstring modified_str;
// |modified| can be NULL in FTP listings. // |modified| can be NULL in FTP listings.
if (modified) { if (!modified.is_null()) {
Time time(Time::FromFileTime(*modified)); modified_str = base::TimeFormatShortDateAndTime(modified);
modified_str = base::TimeFormatShortDateAndTime(time);
} }
string_escape::JavascriptDoubleQuote(modified_str, true, &result); string_escape::JavascriptDoubleQuote(modified_str, true, &result);
@@ -845,7 +855,6 @@ std::string GetDirectoryListingEntry(const std::string& name,
return result; return result;
} }
#endif
std::wstring StripWWW(const std::wstring& text) { std::wstring StripWWW(const std::wstring& text) {
const std::wstring www(L"www."); const std::wstring www(L"www.");

@@ -19,6 +19,10 @@
class GURL; class GURL;
namespace base {
class Time;
}
namespace net { namespace net {
// Given the full path to a file name, creates a file: URL. The returned URL // 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::string& host, bool* is_ip_address);
std::string CanonicalizeHost(const std::wstring& 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. // Call these functions to get the html for a directory listing.
// They will pass non-7bit-ascii characters unescaped, allowing // They will pass non-7bit-ascii characters unescaped, allowing
// the browser to interpret the encoding (utf8, etc). // the browser to interpret the encoding (utf8, etc).
std::string GetDirectoryListingHeader(const std::string& title); std::string GetDirectoryListingHeader(const std::string& title);
std::string GetDirectoryListingEntry(const std::string& name, DWORD attrib, std::string GetDirectoryListingEntry(const std::string& name, bool is_dir,
int64 size, const FILETIME* modified); int64 size, const base::Time& modified);
#endif
// If text starts with "www." it is removed, otherwise text is returned // If text starts with "www." it is removed, otherwise text is returned
// unmodified. // unmodified.

@@ -110,11 +110,9 @@ if env['PLATFORM'] in ('posix', 'darwin'):
# Remove files that still need to be ported from the input_files list. # Remove files that still need to be ported from the input_files list.
# TODO(port): delete files from this list as they get ported. # TODO(port): delete files from this list as they get ported.
to_be_ported_files = [ to_be_ported_files = [
'base/directory_lister.cc',
'base/ssl_config_service.cc', 'base/ssl_config_service.cc',
'http/http_transaction_winhttp.cc', 'http/http_transaction_winhttp.cc',
'http/winhttp_request_throttle.cc', 'http/winhttp_request_throttle.cc',
'url_request/url_request_file_dir_job.cc',
'url_request/url_request_ftp_job.cc', 'url_request/url_request_ftp_job.cc',
] ]
for remove in to_be_ported_files: for remove in to_be_ported_files:

@@ -7,16 +7,18 @@
#include "base/file_util.h" #include "base/file_util.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/string_util.h" #include "base/string_util.h"
#include "base/time.h"
#include "googleurl/src/gurl.h" #include "googleurl/src/gurl.h"
#include "net/base/net_util.h" #include "net/base/net_util.h"
#include "net/base/wininet_util.h"
#include "net/url_request/url_request.h" #include "net/url_request/url_request.h"
#if defined(OS_POSIX)
#include <sys/stat.h>
#endif
using std::string; using std::string;
using std::wstring; using std::wstring;
using net::WinInetUtil;
URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request, URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request,
const wstring& dir_path) const wstring& dir_path)
: URLRequestJob(request), : URLRequestJob(request),
@@ -97,12 +99,8 @@ bool URLRequestFileDirJob::GetCharset(string* charset) {
return true; return true;
} }
void URLRequestFileDirJob::OnListFile(const WIN32_FIND_DATA& data) { void URLRequestFileDirJob::OnListFile(
FILETIME local_time; const file_util::FileEnumerator::FindInfo& data) {
FileTimeToLocalFileTime(&data.ftLastWriteTime, &local_time);
int64 size = (static_cast<unsigned __int64>(data.nFileSizeHigh) << 32) |
data.nFileSizeLow;
// We wait to write out the header until we get the first file, so that we // 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. // can catch errors from DirectoryLister and show an error page.
if (!wrote_header_) { if (!wrote_header_) {
@@ -110,11 +108,27 @@ void URLRequestFileDirJob::OnListFile(const WIN32_FIND_DATA& data) {
wrote_header_ = true; 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( 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)));
#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? // TODO(darin): coalesce more?
CompleteRead(); CompleteRead();
} }
@@ -123,8 +137,7 @@ void URLRequestFileDirJob::OnListDone(int error) {
if (error) { if (error) {
read_pending_ = false; read_pending_ = false;
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, error));
WinInetUtil::OSErrorToNetError(error)));
} else if (canceled_) { } else if (canceled_) {
read_pending_ = false; read_pending_ = false;
NotifyCanceled(); NotifyCanceled();
@@ -176,7 +189,8 @@ void URLRequestFileDirJob::CompleteRead() {
NotifyReadComplete(bytes_read); NotifyReadComplete(bytes_read);
} else { } else {
NOTREACHED(); NOTREACHED();
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0)); // TODO: Better error code. // TODO: Better error code.
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0));
} }
} }
} }

@@ -5,11 +5,13 @@
#ifndef NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__ #ifndef NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__
#define 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/base/directory_lister.h"
#include "net/url_request/url_request_job.h" #include "net/url_request/url_request_job.h"
class URLRequestFileDirJob : public URLRequestJob, class URLRequestFileDirJob
public net::DirectoryLister::Delegate { : public URLRequestJob,
public net::DirectoryLister::DirectoryListerDelegate {
public: public:
URLRequestFileDirJob(URLRequest* request, const std::wstring& dir_path); URLRequestFileDirJob(URLRequest* request, const std::wstring& dir_path);
virtual ~URLRequestFileDirJob(); virtual ~URLRequestFileDirJob();
@@ -22,8 +24,8 @@ class URLRequestFileDirJob : public URLRequestJob,
virtual bool GetMimeType(std::string* mime_type); virtual bool GetMimeType(std::string* mime_type);
virtual bool GetCharset(std::string* charset); virtual bool GetCharset(std::string* charset);
// DirectoryLister::Delegate methods: // DirectoryLister::DirectoryListerDelegate methods:
virtual void OnListFile(const WIN32_FIND_DATA& data); virtual void OnListFile(const file_util::FileEnumerator::FindInfo& data);
virtual void OnListDone(int error); virtual void OnListDone(int error);
private: private:

@@ -28,9 +28,7 @@
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/base/net_util.h" #include "net/base/net_util.h"
#include "net/url_request/url_request.h" #include "net/url_request/url_request.h"
#if defined(OS_WIN)
#include "net/url_request/url_request_file_dir_job.h" #include "net/url_request/url_request_file_dir_job.h"
#endif
#if defined(OS_WIN) #if defined(OS_WIN)
class URLRequestFileJob::AsyncResolver : class URLRequestFileJob::AsyncResolver :
@@ -76,10 +74,8 @@ URLRequestJob* URLRequestFileJob::Factory(
std::wstring file_path; std::wstring file_path;
if (net::FileURLToFilePath(request->url(), &file_path)) { if (net::FileURLToFilePath(request->url(), &file_path)) {
if (file_path[file_path.size() - 1] == file_util::kPathSeparator) { if (file_path[file_path.size() - 1] == file_util::kPathSeparator) {
#if defined(OS_WIN)
// Only directories have trailing slashes. // Only directories have trailing slashes.
return new URLRequestFileDirJob(request, file_path); return new URLRequestFileDirJob(request, file_path);
#endif
} }
} }

@@ -9,6 +9,7 @@
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/string_util.h" #include "base/string_util.h"
#include "base/time.h"
#include "net/base/auth.h" #include "net/base/auth.h"
#include "net/base/load_flags.h" #include "net/base/load_flags.h"
#include "net/base/net_util.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 // We don't know the encoding, and can't assume utf8, so pass the 8bit
// directly to the browser for it to decide. // directly to the browser for it to decide.
string file_entry = net::GetDirectoryListingEntry( string file_entry = net::GetDirectoryListingEntry(
find_data_.cFileName, find_data_.dwFileAttributes, size, find_data_.cFileName, false, size,
&find_data_.ftLastWriteTime); base::Time::FromFileTime(find_data_.ftLastWriteTime));
WriteData(&file_entry, true); WriteData(&file_entry, true);
FindNextFile(); 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 // If this isn't top level directory (i.e. the path isn't "/",) add a link to
// the parent directory. // the parent directory.
if (request_->url().path().length() > 1) if (request_->url().path().length() > 1)
html.append(net::GetDirectoryListingEntry("..", 0, 0, NULL)); html.append(net::GetDirectoryListingEntry("..", false, 0, base::Time()));
WriteData(&html, true); WriteData(&html, true);