diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-11 17:01:17 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-11 17:01:17 +0000 |
commit | 581e0d06dc3599bec309d34203b6b5693446fe7f (patch) | |
tree | c8c11535827d0b5302d07b257c12d998f8a9edb3 /net/url_request | |
parent | a63bd1137e938034873b318355731c656caf05fe (diff) | |
download | chromium_src-581e0d06dc3599bec309d34203b6b5693446fe7f.zip chromium_src-581e0d06dc3599bec309d34203b6b5693446fe7f.tar.gz chromium_src-581e0d06dc3599bec309d34203b6b5693446fe7f.tar.bz2 |
FTP Transaction code for new Portable FTP code.
The patch is contributed by Ibrar Ahmed <ibrar.ahmad@gmail.com>.
Original review: http://codereview.chromium.org/39130
R=wtc
http://crbug.com/4965
TEST=None. Work in progress.
Review URL: http://codereview.chromium.org/115137
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15760 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/url_request')
-rw-r--r-- | net/url_request/url_request_new_ftp_job.cc | 172 | ||||
-rw-r--r-- | net/url_request/url_request_new_ftp_job.h | 14 |
2 files changed, 153 insertions, 33 deletions
diff --git a/net/url_request/url_request_new_ftp_job.cc b/net/url_request/url_request_new_ftp_job.cc index be2f2c6..d6e0ada 100644 --- a/net/url_request/url_request_new_ftp_job.cc +++ b/net/url_request/url_request_new_ftp_job.cc @@ -5,12 +5,16 @@ #include "net/url_request/url_request_new_ftp_job.h" #include "base/file_version_info.h" +#include "base/message_loop.h" +#include "net/base/escape.h" #include "net/base/net_util.h" +#include "net/ftp/ftp_directory_parser.h" +#include "net/ftp/ftp_response_info.h" +#include "net/ftp/ftp_transaction_factory.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_error_job.h" - URLRequestNewFtpJob::URLRequestNewFtpJob(URLRequest* request) : URLRequestJob(request), server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH), @@ -40,51 +44,161 @@ URLRequestJob* URLRequestNewFtpJob::Factory(URLRequest* request, } void URLRequestNewFtpJob::Start() { - NOTIMPLEMENTED(); + DCHECK(!transaction_.get()); + request_info_.url = request_->url(); + StartTransaction(); } void URLRequestNewFtpJob::Kill() { - NOTIMPLEMENTED(); -} - -uint64 URLRequestNewFtpJob::GetUploadProgress() const { - NOTIMPLEMENTED(); - return 0; -} - -void URLRequestNewFtpJob::GetResponseInfo() { - NOTIMPLEMENTED(); -} - -int URLRequestNewFtpJob::GetResponseCode() const { - NOTIMPLEMENTED(); - return -1; -} - -bool URLRequestNewFtpJob::GetMoreData() { - NOTIMPLEMENTED(); - return false; + if (!transaction_.get()) + return; + DestroyTransaction(); + URLRequestJob::Kill(); } bool URLRequestNewFtpJob::ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read) { - NOTIMPLEMENTED(); + DCHECK_NE(buf_size, 0); + DCHECK(bytes_read); + DCHECK(!read_in_progress_); + if (response_info_ == NULL) { + response_info_ = transaction_->GetResponseInfo(); + if (response_info_->is_directory_listing) { + // Unescape the URL path and pass the raw 8bit directly to the browser. + directory_html_ = net::GetDirectoryListingHeader( + UnescapeURLComponent(request_->url().path(), + UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS)); + // 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) + directory_html_.append(net::GetDirectoryListingEntry("..", + false, + 0, + base::Time())); + } + } + if (!directory_html_.empty()) { + size_t bytes_to_copy = std::min(static_cast<size_t>(buf_size), + directory_html_.size()); + memcpy(buf->data(), directory_html_.c_str(), bytes_to_copy); + *bytes_read = bytes_to_copy; + directory_html_.erase(0, bytes_to_copy); + return true; + } + int rv = transaction_->Read(buf, buf_size, &read_callback_); + if (response_info_->is_directory_listing) { + std::string file_entry; + if (rv > 0) { + std::string line; + buf->data()[rv] = 0; + std::istringstream iss(buf->data()); + while (getline(iss, line)) { + struct net::ListState state; + struct net::ListResult result; + // TODO(ibrar): Use a more descriptive variable name than 'lt', which + // looks like 'it'. + net::LineType lt = ParseFTPLine(line.c_str(), &state, &result); + switch (lt) { + case net::FTP_TYPE_DIRECTORY: + file_entry.append(net::GetDirectoryListingEntry(result.fe_fname, + true, + rv, + base::Time())); + break; + case net::FTP_TYPE_FILE: + file_entry.append(net::GetDirectoryListingEntry(result.fe_fname, + false, + rv, + base::Time())); + break; + case net::FTP_TYPE_SYMLINK: + case net::FTP_TYPE_JUNK: + case net::FTP_TYPE_COMMENT: + break; + default: + break; + } + } + memcpy(buf->data(), file_entry.c_str(), file_entry.length()); + *bytes_read = file_entry.length(); + return true; + } + } else { + rv = transaction_->Read(buf, buf_size, &read_callback_); + } + if (rv >= 0) { + *bytes_read = rv; + return true; + } + if (rv == net::ERR_IO_PENDING) { + read_in_progress_ = true; + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + } else { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); + } return false; } void URLRequestNewFtpJob::OnStartCompleted(int result) { - NOTIMPLEMENTED(); + // If the request was destroyed, then there is no more work to do. + if (!request_ || !request_->delegate()) + return; + // If the transaction was destroyed, then the job was cancelled, and + // we can just ignore this notification. + if (!transaction_.get()) + return; + // Clear the IO_PENDING status + SetStatus(URLRequestStatus()); + if (result == net::OK) { + URLRequestJob::NotifyHeadersComplete(); + } else { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); + } } void URLRequestNewFtpJob::OnReadCompleted(int result) { - NOTIMPLEMENTED(); + read_in_progress_ = false; + if (result == 0) { + NotifyDone(URLRequestStatus()); + } else if (result < 0) { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); + } else { + // Clear the IO_PENDING status + SetStatus(URLRequestStatus()); + } + NotifyReadComplete(result); } -void URLRequestNewFtpJob::DestroyTransaction() { - NOTIMPLEMENTED(); +void URLRequestNewFtpJob::StartTransaction() { + // Create a transaction. + DCHECK(!transaction_.get()); + DCHECK(request_->context()); + DCHECK(request_->context()->ftp_transaction_factory()); + + transaction_.reset( + request_->context()->ftp_transaction_factory()->CreateTransaction()); + + // No matter what, we want to report our status as IO pending since we will + // be notifying our consumer asynchronously via OnStartCompleted. + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + int rv; + if (transaction_.get()) { + rv = transaction_->Start(&request_info_, &start_callback_); + if (rv == net::ERR_IO_PENDING) + return; + } else { + rv = net::ERR_FAILED; + } + // The transaction started synchronously, but we need to notify the + // URLRequest delegate via the message loop. + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( + this, &URLRequestNewFtpJob::OnStartCompleted, rv)); } -void URLRequestNewFtpJob::StartTransaction() { - NOTIMPLEMENTED(); +void URLRequestNewFtpJob::DestroyTransaction() { + DCHECK(transaction_.get()); + + transaction_.reset(); + response_info_ = NULL; } diff --git a/net/url_request/url_request_new_ftp_job.h b/net/url_request/url_request_new_ftp_job.h index 2d3f186..6c0a9fb 100644 --- a/net/url_request/url_request_new_ftp_job.h +++ b/net/url_request/url_request_new_ftp_job.h @@ -10,6 +10,8 @@ #include "net/base/auth.h" #include "net/base/completion_callback.h" +#include "net/ftp/ftp_request_info.h" +#include "net/ftp/ftp_transaction.h" #include "net/url_request/url_request_job.h" class URLRequestContext; @@ -29,10 +31,9 @@ class URLRequestNewFtpJob : public URLRequestJob { // URLRequestJob methods: virtual void Start(); virtual void Kill(); - virtual uint64 GetUploadProgress() const; - virtual void GetResponseInfo(); - virtual int GetResponseCode() const; - virtual bool GetMoreData(); + + // TODO(ibrar): Yet to give another look at this function. + virtual uint64 GetUploadProgress() const { return 0; } virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read); void NotifyHeadersComplete(); @@ -43,11 +44,16 @@ class URLRequestNewFtpJob : public URLRequestJob { void OnStartCompleted(int result); void OnReadCompleted(int result); + net::FtpRequestInfo request_info_; + scoped_ptr<net::FtpTransaction> transaction_; + const net::FtpResponseInfo* response_info_; + net::AuthState server_auth_state_; net::CompletionCallbackImpl<URLRequestNewFtpJob> start_callback_; net::CompletionCallbackImpl<URLRequestNewFtpJob> read_callback_; + std::string directory_html_; bool read_in_progress_; // Keep a reference to the url request context to be sure it's not deleted |