summaryrefslogtreecommitdiffstats
path: root/net/url_request
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 17:01:17 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 17:01:17 +0000
commit581e0d06dc3599bec309d34203b6b5693446fe7f (patch)
treec8c11535827d0b5302d07b257c12d998f8a9edb3 /net/url_request
parenta63bd1137e938034873b318355731c656caf05fe (diff)
downloadchromium_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.cc172
-rw-r--r--net/url_request/url_request_new_ftp_job.h14
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