Index: net/ftp/ftp_network_transaction.cc |
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc |
index 2b308c7eed4cddf225b90b270d4554a89bd03f8e..ef6adb8bf759124f1bb14462ded90c72dd1de596 100644 |
--- a/net/ftp/ftp_network_transaction.cc |
+++ b/net/ftp/ftp_network_transaction.cc |
@@ -239,11 +239,6 @@ int FtpNetworkTransaction::Stop(int error) { |
return OK; |
} |
-int FtpNetworkTransaction::RestartIgnoringLastError( |
- const CompletionCallback& callback) { |
- return ERR_NOT_IMPLEMENTED; |
-} |
- |
int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info, |
const CompletionCallback& callback, |
const BoundNetLog& net_log) { |
@@ -1033,16 +1028,18 @@ int FtpNetworkTransaction::DoCtrlWriteRETR() { |
int FtpNetworkTransaction::ProcessResponseRETR( |
const FtpCtrlResponse& response) { |
+ // Resource type should be either filled in by DetectTypecode() or |
+ // detected with CWD. RETR is sent only when the resource is a file. |
+ DCHECK_EQ(RESOURCE_TYPE_FILE, resource_type_); |
+ |
switch (GetErrorClass(response.status_code)) { |
case ERROR_CLASS_INITIATED: |
// We want the client to start reading the response at this point. |
// It got here either through Start or RestartWithAuth. We want that |
// method to complete. Not setting next state here will make DoLoop exit |
// and in turn make Start/RestartWithAuth complete. |
- resource_type_ = RESOURCE_TYPE_FILE; |
break; |
case ERROR_CLASS_OK: |
- resource_type_ = RESOURCE_TYPE_FILE; |
next_state_ = STATE_CTRL_WRITE_QUIT; |
break; |
case ERROR_CLASS_INFO_NEEDED: |
@@ -1056,10 +1053,6 @@ int FtpNetworkTransaction::ProcessResponseRETR( |
return Stop(ERR_UNEXPECTED); |
} |
- // We should be sure about our resource type now. Otherwise we risk |
- // an infinite loop (RETR can later send CWD, and CWD can later send RETR). |
- DCHECK_NE(RESOURCE_TYPE_UNKNOWN, resource_type_); |
- |
return OK; |
} |
@@ -1095,6 +1088,7 @@ int FtpNetworkTransaction::ProcessResponseSIZE( |
break; |
case ERROR_CLASS_PERMANENT_ERROR: |
// It's possible that SIZE failed because the path is a directory. |
+ // TODO(xunjieli): Add a test for this case. |
if (resource_type_ == RESOURCE_TYPE_UNKNOWN && |
response.status_code != 550) { |
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
@@ -1104,6 +1098,9 @@ int FtpNetworkTransaction::ProcessResponseSIZE( |
NOTREACHED(); |
return Stop(ERR_UNEXPECTED); |
} |
+ |
+ // If the resource is known beforehand to be a file, RETR should be issued, |
+ // otherwise do CWD which will detect the resource type. |
if (resource_type_ == RESOURCE_TYPE_FILE) |
EstablishDataConnection(STATE_CTRL_WRITE_RETR); |
else |
@@ -1119,13 +1116,14 @@ int FtpNetworkTransaction::DoCtrlWriteCWD() { |
} |
int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { |
- // We should never issue CWD if we know the target resource is a file. |
+ // CWD should be invoked only when the resource is not a file. |
DCHECK_NE(RESOURCE_TYPE_FILE, resource_type_); |
switch (GetErrorClass(response.status_code)) { |
case ERROR_CLASS_INITIATED: |
return Stop(ERR_INVALID_RESPONSE); |
case ERROR_CLASS_OK: |
+ resource_type_ = RESOURCE_TYPE_DIRECTORY; |
EstablishDataConnection(STATE_CTRL_WRITE_LIST); |
break; |
case ERROR_CLASS_INFO_NEEDED: |
@@ -1158,9 +1156,7 @@ int FtpNetworkTransaction::ProcessResponseCWDNotADirectory() { |
return Stop(ERR_FILE_NOT_FOUND); |
} |
- // We are here because SIZE failed and we are not sure what the resource |
- // type is. It could still be file, and SIZE could fail because of |
- // an access error (http://crbug.com/56734). Try RETR just to be sure. |
+ // If it is not a directory, it is probably a file. |
resource_type_ = RESOURCE_TYPE_FILE; |
EstablishDataConnection(STATE_CTRL_WRITE_RETR); |
@@ -1182,6 +1178,10 @@ int FtpNetworkTransaction::DoCtrlWriteLIST() { |
int FtpNetworkTransaction::ProcessResponseLIST( |
const FtpCtrlResponse& response) { |
+ // Resource type should be either filled in by DetectTypecode() or |
+ // detected with CWD. LIST is sent only when the resource is a directory. |
+ DCHECK_EQ(RESOURCE_TYPE_DIRECTORY, resource_type_); |
+ |
switch (GetErrorClass(response.status_code)) { |
case ERROR_CLASS_INITIATED: |
// We want the client to start reading the response at this point. |