summaryrefslogtreecommitdiffstats
path: root/net/url_request
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-05 08:56:21 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-05 08:56:21 +0000
commit29c494224c84b5393dbd9de92994dbb2b763ca15 (patch)
tree1989d9a10a1cc4a5cc4334cc8c7e1d5054345022 /net/url_request
parentaca4eca3f4fc0da7a4bfe8c57815b5a746c4782f (diff)
downloadchromium_src-29c494224c84b5393dbd9de92994dbb2b763ca15.zip
chromium_src-29c494224c84b5393dbd9de92994dbb2b763ca15.tar.gz
chromium_src-29c494224c84b5393dbd9de92994dbb2b763ca15.tar.bz2
Remove WinInet FTP code.
TEST=none BUG=25520 Review URL: http://codereview.chromium.org/523034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35524 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/url_request')
-rw-r--r--net/url_request/url_request_ftp_job.cc562
-rw-r--r--net/url_request/url_request_ftp_job.h116
-rw-r--r--net/url_request/url_request_inet_job.cc371
-rw-r--r--net/url_request/url_request_inet_job.h159
-rw-r--r--net/url_request/url_request_job_manager.cc8
5 files changed, 0 insertions, 1216 deletions
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index bc7f085..e69de29 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -1,562 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/url_request/url_request_ftp_job.h"
-
-#include <windows.h>
-#include <wininet.h>
-
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "base/time.h"
-#include "net/base/auth.h"
-#include "net/base/escape.h"
-#include "net/base/load_flags.h"
-#include "net/base/net_errors.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_context.h"
-#include "net/url_request/url_request_error_job.h"
-#include "net/url_request/url_request_new_ftp_job.h"
-
-using std::string;
-
-using net::WinInetUtil;
-
-// When building the directory listing, the period to wait before notifying
-// the parent class that we wrote the data.
-#define kFtpBufferTimeMs 50
-
-static bool UnescapeAndValidatePath(const URLRequest* request,
- std::string* unescaped_path) {
- // Path in GURL is %-encoded UTF-8. FTP servers do not
- // understand %-escaped path so that we have to unescape leading to an
- // unescaped UTF-8 path. Then, the presence of NULL, CR and LF is checked
- // because they're not allowed in FTP.
- // TODO(jungshik) Even though RFC 2640 specifies that UTF-8 be used.
- // There are many FTP servers that use legacy encodings. For them,
- // we need to identify the encoding and convert to that encoding.
- static const std::string kInvalidChars("\x00\x0d\x0a", 3);
- *unescaped_path = UnescapeURLComponent(request->url().path(),
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
- if (unescaped_path->find_first_of(kInvalidChars) != std::string::npos) {
- SetLastError(ERROR_INTERNET_INVALID_URL);
- // GURL path should not contain '%00' which is NULL(0x00) when unescaped.
- // URLRequestFtpJob should not have been invoked for an invalid GURL.
- DCHECK(unescaped_path->find(std::string("\x00", 1)) == std::string::npos) <<
- "Path should not contain %00.";
- return false;
- }
- return true;
-}
-
-// static
-URLRequestJob* URLRequestFtpJob::Factory(URLRequest* request,
- const std::string &scheme) {
- // Checking whether we are using new or old FTP implementation.
- if (request->context() && request->context()->ftp_transaction_factory())
- return URLRequestNewFtpJob::Factory(request, scheme);
-
- DCHECK(scheme == "ftp");
-
- int port = request->url().IntPort();
-
- if (request->url().has_port() &&
- !net::IsPortAllowedByFtp(port) && !net::IsPortAllowedByOverride(port))
- return new URLRequestErrorJob(request, net::ERR_UNSAFE_PORT);
-
- return new URLRequestFtpJob(request);
-}
-
-URLRequestFtpJob::URLRequestFtpJob(URLRequest* request)
- : URLRequestInetJob(request), state_(START), is_directory_(false),
- dest_(NULL), dest_size_(0) {
-}
-
-URLRequestFtpJob::~URLRequestFtpJob() {
-}
-
-void URLRequestFtpJob::Start() {
- GURL parts(request_->url());
- const std::string& scheme = parts.scheme();
-
- // We should only be dealing with FTP at this point:
- DCHECK(LowerCaseEqualsASCII(scheme, "ftp"));
-
- SendRequest();
-}
-
-bool URLRequestFtpJob::GetMimeType(std::string* mime_type) const {
- if (!is_directory_)
- return false;
-
- mime_type->assign("text/html");
- return true;
-}
-
-void URLRequestFtpJob::OnCancelAuth() {
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFtpJob::ContinueNotifyHeadersComplete));
-}
-
-void URLRequestFtpJob::OnSetAuth() {
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFtpJob::SendRequest));
-}
-
-void URLRequestFtpJob::SendRequest() {
- state_ = CONNECTING;
-
- DWORD flags =
- INTERNET_FLAG_KEEP_CONNECTION |
- INTERNET_FLAG_EXISTING_CONNECT |
- INTERNET_FLAG_PASSIVE |
- INTERNET_FLAG_RAW_DATA;
-
- // It doesn't make sense to ask for both a cache validation and a
- // reload at the same time.
- DCHECK(!((request_->load_flags() & net::LOAD_VALIDATE_CACHE) &&
- (request_->load_flags() & net::LOAD_BYPASS_CACHE)));
-
- if (request_->load_flags() & net::LOAD_BYPASS_CACHE)
- flags |= INTERNET_FLAG_RELOAD;
-
- // Apply authentication if we have any, otherwise authenticate
- // according to FTP defaults. (See InternetConnect documentation.)
- // First, check if we have auth in cache, then check URL.
- // That way a user can re-enter credentials, and we'll try with their
- // latest input rather than always trying what they specified
- // in the url (if anything).
- string username, password;
- bool have_auth = false;
- if (server_auth_ && server_auth_->state == net::AUTH_STATE_HAVE_AUTH) {
- // Add auth info to cache
- have_auth = true;
- username = WideToUTF8(server_auth_->username);
- password = WideToUTF8(server_auth_->password);
- request_->context()->ftp_auth_cache()->Add(request_->url().GetOrigin(),
- server_auth_->username,
- server_auth_->password);
- } else {
- if (request_->url().has_username()) {
- username = request_->url().username();
- password = request_->url().has_password() ? request_->url().password() :
- "";
- have_auth = true;
- }
- }
-
- int port = request_->url().has_port() ?
- request_->url().IntPort() : INTERNET_DEFAULT_FTP_PORT;
-
- connection_handle_ = InternetConnectA(
- GetTheInternet(),
- request_->url().HostNoBrackets().c_str(),
- port,
- have_auth ? username.c_str() : NULL,
- have_auth ? password.c_str() : NULL,
- INTERNET_SERVICE_FTP, flags,
- reinterpret_cast<DWORD_PTR>(this));
-
- if (connection_handle_) {
- OnConnect();
- } else {
- ProcessRequestError(GetLastError());
- }
-}
-
-void URLRequestFtpJob::OnIOComplete(const AsyncResult& result) {
- if (state_ == CONNECTING) {
- switch (result.dwError) {
- case ERROR_NO_MORE_FILES:
- // url is an empty directory
- OnStartDirectoryTraversal();
- OnFinishDirectoryTraversal();
- return;
- case ERROR_INTERNET_LOGIN_FAILURE:
- // fall through
- case ERROR_INTERNET_INCORRECT_USER_NAME:
- // fall through
- case ERROR_INTERNET_INCORRECT_PASSWORD: {
- GURL origin = request_->url().GetOrigin();
- if (server_auth_ != NULL &&
- server_auth_->state == net::AUTH_STATE_HAVE_AUTH) {
- request_->context()->ftp_auth_cache()->Remove(origin,
- server_auth_->username,
- server_auth_->password);
- } else {
- server_auth_ = new net::AuthData();
- }
- server_auth_->state = net::AUTH_STATE_NEED_AUTH;
-
- net::FtpAuthCache::Entry* cached_auth =
- request_->context()->ftp_auth_cache()->Lookup(origin);
-
- if (cached_auth) {
- // Retry using cached auth data.
- SetAuth(cached_auth->username, cached_auth->password);
- } else {
- // The io completed fine, the error was due to invalid auth.
- SetStatus(URLRequestStatus());
-
- // Prompt for a username/password.
- NotifyHeadersComplete();
- }
- return;
- }
- case ERROR_SUCCESS:
- connection_handle_ = (HINTERNET)result.dwResult;
- OnConnect();
- return;
- case ERROR_INTERNET_EXTENDED_ERROR: {
- DWORD extended_err(ERROR_SUCCESS);
- DWORD size = 1;
- char buffer[1];
- if (!InternetGetLastResponseInfoA(&extended_err, buffer, &size))
- // We don't care about the error text here, so the only acceptable
- // error is one regarding insufficient buffer length.
- DCHECK(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
- if (extended_err != ERROR_SUCCESS) {
- CleanupConnection();
- NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
- WinInetUtil::OSErrorToNetError(extended_err)));
- return;
- }
- // Fall through in the case we saw ERROR_INTERNET_EXTENDED_ERROR but
- // InternetGetLastResponseInfo gave us no additional information.
- }
- default:
- CleanupConnection();
- NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
- WinInetUtil::OSErrorToNetError(result.dwError)));
- return;
- }
- } else if (state_ == SETTING_CUR_DIRECTORY) {
- OnSetCurrentDirectory(result.dwError);
- } else if (state_ == FINDING_FIRST_FILE) {
- // We don't fail here if result.dwError != ERROR_SUCCESS because
- // getting an error here doesn't always mean the file is not found.
- // FindFirstFileA() issue a LIST command and may fail on some
- // ftp server when the requested object is a file. So ERROR_NO_MORE_FILES
- // from FindFirstFileA() is not a reliable criteria for valid path
- // or not, we should proceed optimistically by getting the file handle.
- if (result.dwError != ERROR_SUCCESS &&
- result.dwError != ERROR_NO_MORE_FILES) {
- DWORD result_error = result.dwError;
- CleanupConnection();
- NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
- WinInetUtil::OSErrorToNetError(result_error)));
- return;
- }
- request_handle_ = (HINTERNET)result.dwResult;
- OnFindFirstFile(result.dwError);
- } else if (state_ == GETTING_DIRECTORY) {
- OnFindFile(result.dwError);
- } else if (state_ == GETTING_FILE_HANDLE) {
- if (result.dwError != ERROR_SUCCESS) {
- CleanupConnection();
- NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
- WinInetUtil::OSErrorToNetError(result.dwError)));
- return;
- }
- // start reading file contents
- state_ = GETTING_FILE;
- request_handle_ = (HINTERNET)result.dwResult;
- NotifyHeadersComplete();
- } else {
- // we don't have IO outstanding. Pass to our base class.
- URLRequestInetJob::OnIOComplete(result);
- }
-}
-
-bool URLRequestFtpJob::NeedsAuth() {
- // Note that we only have to worry about cases where an actual FTP server
- // requires auth (and not a proxy), because connecting to FTP via proxy
- // effectively means the browser communicates via HTTP, and uses HTTP's
- // Proxy-Authenticate protocol when proxy servers require auth.
- return server_auth_ && server_auth_->state == net::AUTH_STATE_NEED_AUTH;
-}
-
-void URLRequestFtpJob::GetAuthChallengeInfo(
- scoped_refptr<net::AuthChallengeInfo>* result) {
- DCHECK((server_auth_ != NULL) &&
- (server_auth_->state == net::AUTH_STATE_NEED_AUTH));
- scoped_refptr<net::AuthChallengeInfo> auth_info = new net::AuthChallengeInfo;
- auth_info->is_proxy = false;
- auth_info->host_and_port = ASCIIToWide(
- net::GetHostAndPort(request_->url()));
- auth_info->scheme = L"";
- auth_info->realm = L"";
- result->swap(auth_info);
-}
-
-void URLRequestFtpJob::OnConnect() {
- DCHECK_EQ(state_, CONNECTING);
-
- state_ = SETTING_CUR_DIRECTORY;
- // Setting the directory lets us determine if the URL is a file,
- // and also keeps the working directory for the FTP session in sync
- // with what is being displayed in the browser.
- if (request_->url().has_path()) {
- std::string unescaped_path;
- if (UnescapeAndValidatePath(request_, &unescaped_path) &&
- FtpSetCurrentDirectoryA(connection_handle_,
- unescaped_path.c_str())) {
- OnSetCurrentDirectory(ERROR_SUCCESS);
- } else {
- ProcessRequestError(GetLastError());
- }
- }
-}
-
-void URLRequestFtpJob::OnSetCurrentDirectory(DWORD last_error) {
- DCHECK_EQ(state_, SETTING_CUR_DIRECTORY);
-
- is_directory_ = (last_error == ERROR_SUCCESS);
- // if last_error is not ERROR_SUCCESS, the requested url is either
- // a file or an invalid path. We optimistically try to read as a file,
- // and if it fails, we fail.
- state_ = FINDING_FIRST_FILE;
-
- std::string unescaped_path;
- bool is_path_valid = true;
- if (request_->url().has_path()) {
- is_path_valid = UnescapeAndValidatePath(request_, &unescaped_path);
- }
- if (is_path_valid &&
- (request_handle_ = FtpFindFirstFileA(connection_handle_,
- unescaped_path.c_str(),
- &find_data_, 0,
- reinterpret_cast<DWORD_PTR>(this)))) {
- OnFindFirstFile(GetLastError());
- } else {
- ProcessRequestError(GetLastError());
- }
-}
-
-void URLRequestFtpJob::FindNextFile() {
- DWORD last_error;
- if (InternetFindNextFileA(request_handle_, &find_data_)) {
- last_error = ERROR_SUCCESS;
- } else {
- last_error = GetLastError();
- // We'll get ERROR_NO_MORE_FILES if the directory is empty.
- if (last_error != ERROR_NO_MORE_FILES) {
- ProcessRequestError(last_error);
- return;
- }
- }
- // Use InvokeLater to call OnFindFile as it ends up calling us, so we don't
- // to blow the stack.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFtpJob::OnFindFile, last_error));
-}
-
-void URLRequestFtpJob::OnFindFirstFile(DWORD last_error) {
- DCHECK_EQ(state_, FINDING_FIRST_FILE);
- if (!is_directory_) {
- // Note that it is not enough to just check !is_directory_ and assume
- // the URL is a file, because is_directory_ is true iff we successfully
- // set current directory to the URL path. Therefore, the URL could just
- // be an invalid path. We proceed optimistically and fail in that case.
- state_ = GETTING_FILE_HANDLE;
- std::string unescaped_path;
- if (UnescapeAndValidatePath(request_, &unescaped_path) &&
- (request_handle_ = FtpOpenFileA(connection_handle_,
- unescaped_path.c_str(),
- GENERIC_READ,
- INTERNET_FLAG_TRANSFER_BINARY,
- reinterpret_cast<DWORD_PTR>(this)))) {
- // Start reading file contents
- state_ = GETTING_FILE;
- NotifyHeadersComplete();
- } else {
- ProcessRequestError(GetLastError());
- }
- } else {
- OnStartDirectoryTraversal();
- // If we redirect in OnStartDirectoryTraversal() then this request job
- // is cancelled.
- if (request_handle_)
- OnFindFile(last_error);
- }
-}
-
-void URLRequestFtpJob::OnFindFile(DWORD last_error) {
- DCHECK_EQ(state_, GETTING_DIRECTORY);
-
- if (last_error == ERROR_SUCCESS) {
- // TODO(jabdelmalek): need to add icons for files/folders.
- int64 size =
- (static_cast<unsigned __int64>(find_data_.nFileSizeHigh) << 32) |
- find_data_.nFileSizeLow;
-
- // We don't know the encoding used on an FTP server, but we
- // use FtpFindFirstFileA, which I guess does NOT preserve
- // the raw byte sequence because it's implemented in terms
- // of FtpFindFirstFileW. Without the raw byte sequence, we
- // can't apply the encoding detection or other heuristics
- // to determine/guess the encoding. Neither can we use UTF-8
- // used by a RFC-2640-compliant FTP server. In some cases (e.g.
- // the default code page is an SBCS with almost all bytes assigned.
- // In lucky cases, it's even possible with a DBCS), it's possible
- // to recover the raw byte sequence in most cases. We can do
- // some more here, but it's not worth the effort because we're
- // going to replace this class with URLRequestNewFtpJob.
- string file_entry = net::GetDirectoryListingEntry(
- base::SysNativeMBToWide(find_data_.cFileName), std::string(),
- false, size, base::Time::FromFileTime(find_data_.ftLastWriteTime));
- WriteData(&file_entry, true);
-
- FindNextFile();
- return;
- }
-
- DCHECK(last_error == ERROR_NO_MORE_FILES);
- OnFinishDirectoryTraversal();
-}
-
-void URLRequestFtpJob::OnStartDirectoryTraversal() {
- state_ = GETTING_DIRECTORY;
-
- // Unescape the URL path and pass the raw 8bit directly to the browser.
- //
- // Here we can try to detect the encoding although it may not be very
- // reliable because it's not likely to be long enough. Because this class
- // will be replaced by URLRequestNewFtpJob and is used only on Windows,
- // we use SysNativeMBToWide as a stopgap measure.
- string html = net::GetDirectoryListingHeader(
- base::SysNativeMBToWide(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)
- html.append(net::GetDirectoryListingEntry(L"..", std::string(),
- false, 0, base::Time()));
-
- WriteData(&html, true);
-
- NotifyHeadersComplete();
-}
-
-void URLRequestFtpJob::OnFinishDirectoryTraversal() {
- state_ = DONE;
-}
-
-int URLRequestFtpJob::WriteData(const std::string* data,
- bool call_io_complete) {
- int written = 0;
-
- if (data && data->length())
- directory_html_.append(*data);
-
- if (dest_) {
- size_t bytes_to_copy = std::min(static_cast<size_t>(dest_size_),
- directory_html_.length());
- if (bytes_to_copy) {
- memcpy(dest_, directory_html_.c_str(), bytes_to_copy);
- directory_html_.erase(0, bytes_to_copy);
- dest_ = NULL;
- dest_size_ = NULL;
- written = static_cast<int>(bytes_to_copy);
-
- if (call_io_complete) {
- // Wait a little bit before telling the parent class that we wrote
- // data. This avoids excessive cycles of us getting one file entry and
- // telling the parent class to Read().
- MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFtpJob::ContinueIOComplete, written),
- kFtpBufferTimeMs);
- }
- }
- }
-
- return written;
-}
-
-void URLRequestFtpJob::ContinueIOComplete(int bytes_written) {
- AsyncResult result;
- result.dwResult = bytes_written;
- result.dwError = ERROR_SUCCESS;
- URLRequestInetJob::OnIOComplete(result);
-}
-
-void URLRequestFtpJob::ContinueNotifyHeadersComplete() {
- NotifyHeadersComplete();
-}
-
-int URLRequestFtpJob::CallInternetRead(char* dest, int dest_size,
- int *bytes_read) {
- int result;
-
- if (is_directory_) {
- // Copy the html that we created from the directory listing that we got
- // from InternetFindNextFile.
- DCHECK(dest_ == NULL);
- dest_ = dest;
- dest_size_ = dest_size;
-
- DCHECK(state_ == GETTING_DIRECTORY || state_ == DONE);
- int written = WriteData(NULL, false);
- if (written) {
- *bytes_read = written;
- result = ERROR_SUCCESS;
- } else {
- result = state_ == GETTING_DIRECTORY ? ERROR_IO_PENDING : ERROR_SUCCESS;
- }
- } else {
- DWORD bytes_to_read = dest_size;
- bytes_read_ = 0;
- // InternetReadFileEx doesn't work for asynchronous FTP, InternetReadFile
- // must be used instead.
- if (!InternetReadFile(request_handle_, dest, bytes_to_read, &bytes_read_))
- return GetLastError();
-
- *bytes_read = static_cast<int>(bytes_read_);
- result = ERROR_SUCCESS;
- }
-
- return result;
-}
-
-bool URLRequestFtpJob::GetReadBytes(const AsyncResult& result,
- int* bytes_read) {
- if (is_directory_) {
- *bytes_read = static_cast<int>(result.dwResult);
- } else {
- if (!result.dwResult)
- return false;
-
- // IE5 and later return the number of read bytes in the
- // INTERNET_ASYNC_RESULT structure. IE4 holds on to the pointer passed in
- // to InternetReadFile and store it there.
- *bytes_read = bytes_read_;
-
- if (!*bytes_read)
- *bytes_read = result.dwError;
- }
-
- return true;
-}
-
-bool URLRequestFtpJob::IsRedirectResponse(GURL* location,
- int* http_status_code) {
- if (is_directory_) {
- std::string ftp_path = request_->url().path();
- if (!ftp_path.empty() && ('/' != ftp_path[ftp_path.length() - 1])) {
- ftp_path.push_back('/');
- GURL::Replacements replacements;
- replacements.SetPathStr(ftp_path);
-
- *location = request_->url().ReplaceComponents(replacements);
- *http_status_code = 301; // simulate a permanent redirect
- return true;
- }
- }
-
- return false;
-}
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h
index a2b2aea..e69de29 100644
--- a/net/url_request/url_request_ftp_job.h
+++ b/net/url_request/url_request_ftp_job.h
@@ -1,116 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_URL_REQUEST_URL_REQUEST_FTP_JOB_H_
-#define NET_URL_REQUEST_URL_REQUEST_FTP_JOB_H_
-
-#include <string>
-
-#include "net/url_request/url_request_inet_job.h"
-
-// A basic FTP job that handles download files and showing directory listings.
-class URLRequestFtpJob : public URLRequestInetJob {
- public:
- static URLRequestJob* Factory(URLRequest* request, const std::string& scheme);
-
- // URLRequestJob methods:
- virtual void Start();
- virtual bool GetMimeType(std::string* mime_type) const;
-
- // URLRequestInetJob methods:
- virtual void OnIOComplete(const AsyncResult& result);
-
- protected:
- explicit URLRequestFtpJob(URLRequest* request);
-
- // Starts the WinInet request.
- virtual void SendRequest();
-
- virtual int CallInternetRead(char* dest, int dest_size, int *bytes_read);
- virtual bool GetReadBytes(const AsyncResult& result, int* bytes_read);
- virtual void OnCancelAuth();
- virtual void OnSetAuth();
- virtual bool NeedsAuth();
- virtual void GetAuthChallengeInfo(scoped_refptr<net::AuthChallengeInfo>*);
- virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
-
- private:
- virtual ~URLRequestFtpJob();
-
- // Called after InternetConnect successfully connects to server.
- void OnConnect();
-
- // Called after FtpSetCurrentDirectory attempts to change current dir.
- void OnSetCurrentDirectory(DWORD last_error);
-
- // Requests the next file in the directory listing from WinInet.
- void FindNextFile();
-
- // Called when the first file in a directory listing is available.
- void OnFindFirstFile(DWORD last_error);
-
- // Called when a file in a directory listing is available.
- void OnFindFile(DWORD last_error);
-
- // Call this when starting a directory listing to setup the html.
- void OnStartDirectoryTraversal();
-
- // Call this at the end of a directory listing to complete the html.
- void OnFinishDirectoryTraversal();
-
- // If given data, writes it to the directory listing html. If
- // call_io_complete is true, will also notify the parent class that we wrote
- // data in the given buffer.
- int WriteData(const std::string* data, bool call_io_complete);
-
- // Continuation function for calling OnIOComplete through the message loop.
- virtual void ContinueIOComplete(int bytes_written);
-
- // Continuation function for calling NotifyHeadersComplete through the message
- // loop.
- virtual void ContinueNotifyHeadersComplete();
-
- typedef enum {
- // Initial state of the ftp job.
- START = 0x200,
- // Opening the url.
- CONNECTING,
- // Attempting to change current dir to match request.
- SETTING_CUR_DIRECTORY,
- // Retrieving first file information in cur dir (by FtpFindFirstFile).
- FINDING_FIRST_FILE,
- // Retrieving the directory listing (if directory).
- GETTING_DIRECTORY,
- // Initiate access to file by call to FtpOpenFile (if file).
- GETTING_FILE_HANDLE,
- // Retrieving the file (if file).
- GETTING_FILE,
- // URLRequestInetJob is reading the response now.
- DONE
- } FtpJobState;
-
- // The FtpJob has several asynchronous operations which happen
- // in sequence. The state keeps track of which asynchronous IO
- // is pending at any given point in time.
- FtpJobState state_;
-
- // In IE 4 and before, this pointer passed to asynchronous InternetReadFile
- // calls is where the number of read bytes is written to.
- DWORD bytes_read_;
-
- bool is_directory_; // does the url point to a file or directory
- WIN32_FIND_DATAA find_data_;
- std::string directory_html_; // if url is directory holds html
-
- // When building a directory listing, we need to temporarily hold on to the
- // buffer in between the time a Read() call comes in and we get the file
- // entry from WinInet.
- char* dest_;
- int dest_size_;
-
-
- DISALLOW_EVIL_CONSTRUCTORS(URLRequestFtpJob);
-};
-
-#endif // NET_URL_REQUEST_URL_REQUEST_FTP_JOB_H_
diff --git a/net/url_request/url_request_inet_job.cc b/net/url_request/url_request_inet_job.cc
index 9791fcd8..e69de29 100644
--- a/net/url_request/url_request_inet_job.cc
+++ b/net/url_request/url_request_inet_job.cc
@@ -1,371 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/url_request/url_request_inet_job.h"
-
-#include <algorithm>
-
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/auth.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/base/wininet_util.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_error_job.h"
-#include "net/url_request/url_request_ftp_job.h"
-#include "net/url_request/url_request_job_metrics.h"
-#include "net/url_request/url_request_job_tracker.h"
-
-using net::WinInetUtil;
-
-//
-// HOW ASYNC IO WORKS
-//
-// The URLRequestInet* classes are now fully asynchronous. This means that
-// all IO operations pass buffers into WinInet, and as WinInet completes those
-// IO requests, it will fill the buffer, and then callback to the client.
-// Asynchronous IO Operations include:
-// HttpSendRequestEx
-// InternetWriteFile
-// HttpEndRequest
-// InternetOpenUrl
-// InternetReadFile (for FTP)
-// InternetReadFileEx (for HTTP)
-// InternetCloseHandle
-//
-// To understand how this works, you need to understand the basic class
-// hierarchy for the URLRequestJob classes:
-//
-// URLRequestJob
-// |
-// +--------------+-------------------+
-// | |
-// (Other Job Types) URLRequestInetJob
-// e.g. | |
-// URLRequestFileJob URLRequestFtpJob URLRequestHttpJob
-// |
-// URLRequestHttpUploadJob
-//
-//
-// To make this work, each URLRequestInetJob has a virtual method called
-// OnIOComplete(). If a derived URLRequestInetJob class issues
-// an asynchronous IO, it must override the OnIOComplete method
-// to handle the IO completion. Once it has overridden this method,
-// *all* asynchronous IO completions will come to this method, even
-// those asynchronous IOs which may have been issued by a base class.
-// For example, URLRequestInetJob has methods which Read from the
-// connection asynchronously. Once URLRequestHttpJob overrides
-// OnIOComplete (so that it can receive its own async IO callbacks)
-// it will also receive the URLRequestInetJob async IO callbacks. To
-// make this work, the derived class must track its own state, and call
-// the base class' version of OnIOComplete if appropriate.
-//
-
-COMPILE_ASSERT(
- sizeof(URLRequestInetJob::AsyncResult) == sizeof(INTERNET_ASYNC_RESULT),
- async_result_inconsistent_size);
-
-HINTERNET URLRequestInetJob::the_internet_ = NULL;
-#ifndef NDEBUG
-MessageLoop* URLRequestInetJob::my_message_loop_ = NULL;
-#endif
-
-URLRequestInetJob::URLRequestInetJob(URLRequest* request)
- : URLRequestJob(request),
- connection_handle_(NULL),
- request_handle_(NULL),
- last_error_(ERROR_SUCCESS),
- is_waiting_(false),
- read_in_progress_(false),
- loop_(MessageLoop::current()) {
- // TODO(darin): we should re-create the internet if the UA string changes,
- // but we have to be careful about existing users of this internet.
- if (!the_internet_) {
- InitializeTheInternet(request->context() ?
- request->context()->GetUserAgent(GURL()) : std::string());
- }
-#ifndef NDEBUG
- DCHECK(MessageLoop::current() == my_message_loop_) <<
- "All URLRequests should happen on the same thread";
-#endif
-}
-
-URLRequestInetJob::~URLRequestInetJob() {
- DCHECK(!request_) << "request should be detached at this point";
-
- // The connections may have already been cleaned up. It is ok to call
- // CleanupConnection again to make sure the resource is properly released.
- // See bug 684997.
- CleanupConnection();
-}
-
-void URLRequestInetJob::Kill() {
- CleanupConnection();
-
- {
- AutoLock locked(loop_lock_);
- loop_ = NULL;
- }
-
- // Dispatch the NotifyDone message to the URLRequest
- URLRequestJob::Kill();
-}
-
-void URLRequestInetJob::SetAuth(const std::wstring& username,
- const std::wstring& password) {
- DCHECK((proxy_auth_ && proxy_auth_->state == net::AUTH_STATE_NEED_AUTH) ||
- (server_auth_ && server_auth_->state == net::AUTH_STATE_NEED_AUTH));
-
- // Proxy gets set first, then WWW.
- net::AuthData* auth =
- (proxy_auth_ && proxy_auth_->state == net::AUTH_STATE_NEED_AUTH ?
- proxy_auth_.get() : server_auth_.get());
-
- if (auth) {
- auth->state = net::AUTH_STATE_HAVE_AUTH;
- auth->username = username;
- auth->password = password;
- }
-
- // Resend the request with the new username and password.
- // Do this asynchronously in case we were called from within a
- // NotifyDataAvailable callback.
- // TODO(mpcomplete): hmm... is it possible 'this' gets deleted before the task
- // is run?
- OnSetAuth();
-}
-
-void URLRequestInetJob::CancelAuth() {
- DCHECK((proxy_auth_ && proxy_auth_->state == net::AUTH_STATE_NEED_AUTH) ||
- (server_auth_ && server_auth_->state == net::AUTH_STATE_NEED_AUTH));
-
- // Proxy gets set first, then WWW.
- net::AuthData* auth =
- (proxy_auth_ && proxy_auth_->state == net::AUTH_STATE_NEED_AUTH ?
- proxy_auth_.get() : server_auth_.get());
-
- if (auth) {
- auth->state = net::AUTH_STATE_CANCELED;
- }
-
- // Once the auth is cancelled, we proceed with the request as though
- // there were no auth. So, send the OnResponseStarted. Schedule this
- // for later so that we don't cause any recursing into the caller
- // as a result of this call.
- OnCancelAuth();
-}
-
-void URLRequestInetJob::OnIOComplete(const AsyncResult& result) {
- URLRequestStatus status;
-
- if (read_in_progress_) {
- read_in_progress_ = false;
- int bytes_read = 0;
- if (GetReadBytes(result, &bytes_read)) {
- SetStatus(status);
- if (bytes_read == 0) {
- NotifyDone(status);
- CleanupConnection();
- }
- } else {
- bytes_read = -1;
- URLRequestStatus status;
- status.set_status(URLRequestStatus::FAILED);
- status.set_os_error(WinInetUtil::OSErrorToNetError(result.dwError));
- NotifyDone(status);
- CleanupConnection();
- }
- NotifyReadComplete(bytes_read);
- } else {
- // If we get here, an IO is completing which we didn't
- // start or we lost track of our state.
- NOTREACHED();
- }
-}
-
-bool URLRequestInetJob::ReadRawData(net::IOBuffer* dest, int dest_size,
- int *bytes_read) {
- if (is_done())
- return 0;
-
- DCHECK_NE(dest_size, 0);
- DCHECK_NE(bytes_read, (int*)NULL);
- DCHECK(!read_in_progress_);
-
- *bytes_read = 0;
-
- int result = CallInternetRead(dest->data(), dest_size, bytes_read);
- if (result == ERROR_SUCCESS) {
- DLOG(INFO) << "read " << *bytes_read << " bytes";
- if (*bytes_read == 0)
- CleanupConnection(); // finished reading all the data
- return true;
- }
-
- if (ProcessRequestError(result))
- read_in_progress_ = true;
-
- // Whether we had an error or the request is pending.
- // Both of these cases return false.
- return false;
-}
-
-void URLRequestInetJob::CallOnIOComplete(const AsyncResult& result) {
- // It's important to clear this flag before calling OnIOComplete
- is_waiting_ = false;
-
- // the job could have completed with an error while the message was pending
- if (!is_done()) {
- // Verify that our status is currently set to IO_PENDING and
- // reset it on success.
- DCHECK(GetStatus().is_io_pending());
- if (result.dwResult && result.dwError == 0)
- SetStatus(URLRequestStatus());
-
- OnIOComplete(result);
- }
-
- Release(); // may destroy self if last reference
-}
-
-bool URLRequestInetJob::ProcessRequestError(int error) {
- if (error == ERROR_IO_PENDING) {
- DLOG(INFO) << "waiting for WinInet call to complete";
- AddRef(); // balanced in CallOnIOComplete
- is_waiting_ = true;
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
- return true;
- }
- DLOG(ERROR) << "WinInet call failed: " << error;
- CleanupConnection();
- NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
- WinInetUtil::OSErrorToNetError(error)));
- return false;
-}
-
-void URLRequestInetJob::CleanupConnection() {
- if (!request_handle_ && !connection_handle_)
- return; // nothing to clean up
-
- if (request_handle_) {
- CleanupHandle(request_handle_);
- request_handle_ = NULL;
- }
- if (connection_handle_) {
- CleanupHandle(connection_handle_);
- connection_handle_ = NULL;
- }
-}
-
-void URLRequestInetJob::CleanupHandle(HINTERNET handle) {
- // We no longer need notifications from this connection.
- InternetSetStatusCallback(handle, NULL);
-
- if (!InternetCloseHandle(handle)) {
- // InternetCloseHandle is evil. The documentation specifies that it
- // either succeeds immediately or returns ERROR_IO_PENDING if there is
- // something outstanding, in which case the close will happen automagically
- // later. In either of these cases, it will call us back with
- // INTERNET_STATUS_HANDLE_CLOSING (because we set up the async callbacks)
- // and we simply do nothing for the message.
- //
- // However, sometimes it also seems to fail with ERROR_INVALID_HANDLE.
- // This seems to happen when we cancel before it has called us back with
- // data. For example, if we cancel during DNS resolution or while waiting
- // for a slow server.
- //
- // Our speculation is that in these cases WinInet creates a handle for
- // us with an internal structure, but that the driver has not yet called
- // it back with a "real" handle (the driver level is probably what
- // generates IO_PENDING). The driver has not yet specified a handle, which
- // causes WinInet to barf.
- //
- // However, in this case, the cancel seems to work. The TCP connection is
- // closed and we still get a callback that the handle is being closed. Yay.
- //
- // We assert that the error is either of these two because we aren't sure
- // if any other error values could also indicate this bogus condition, and
- // we want to notice if we do something wrong that causes a real error.
- DWORD last_error = GetLastError();
- DCHECK(last_error == ERROR_INVALID_HANDLE) <<
- "Unknown error when closing handle, possibly leaking job";
- if (ERROR_IO_PENDING == last_error) {
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
- AsyncResult result;
- result.dwError = ERROR_INTERNET_CONNECTION_ABORTED;
- result.dwResult = reinterpret_cast<DWORD_PTR>(handle);
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestInetJob::CallOnIOComplete, result));
- }
- }
-}
-
-// static
-HINTERNET URLRequestInetJob::GetTheInternet() {
- return the_internet_;
-}
-
-// static
-void URLRequestInetJob::InitializeTheInternet(const std::string& user_agent) {
- // Hack attack. We are hitting a deadlock in wininet deinitialization.
- // What is happening is that when we deinitialize, FreeLibrary will be
- // called on wininet. The loader lock is held, and wininet!DllMain is
- // called. The problem is that wininet tries to do a bunch of cleanup
- // in their DllMain, including calling ICAsyncThread::~ICASyncThread.
- // This tries to shutdown the "select thread", and then does a
- // WaitForSingleObject on the thread with a 5 sec timeout. However the
- // thread they are waiting for cannot exit because the thread shutdown
- // routine (LdrShutdownThread) is trying to acquire the loader lock.
- // This causes chrome.exe to hang for 5 seconds on shutdown before the
- // process will exit. Making sure we close our wininet handles did not help.
- //
- // Since DLLs are reference counted, we inflate the reference count on
- // wininet so that it will never be deinitialized :)
- LoadLibraryA("wininet");
-
- the_internet_ = InternetOpenA(user_agent.c_str(),
- INTERNET_OPEN_TYPE_PRECONFIG,
- NULL, // no proxy override
- NULL, // no proxy bypass list
- INTERNET_FLAG_ASYNC);
- InternetSetStatusCallback(the_internet_, URLRequestStatusCallback);
-
- // Keep track of this message loop so we can catch callers who don't make
- // requests on the same thread. Only do this in debug mode; in release mode
- // my_message_loop_ doesn't exist.
-#ifndef NDEBUG
- DCHECK(!my_message_loop_) << "InitializeTheInternet() called twice";
- DCHECK(my_message_loop_ = MessageLoop::current());
-#endif
-}
-
-// static
-void CALLBACK URLRequestInetJob::URLRequestStatusCallback(
- HINTERNET handle, DWORD_PTR job_id, DWORD status, LPVOID status_info,
- DWORD status_info_len) {
- switch (status) {
- case INTERNET_STATUS_REQUEST_COMPLETE: {
- URLRequestInetJob* job = reinterpret_cast<URLRequestInetJob*>(job_id);
-
- DCHECK(status_info_len == sizeof(AsyncResult));
- AsyncResult* result = static_cast<AsyncResult*>(status_info);
-
- AutoLock locked(job->loop_lock_);
- if (job->loop_) {
- job->loop_->PostTask(FROM_HERE, NewRunnableMethod(
- job, &URLRequestInetJob::CallOnIOComplete, *result));
- }
- break;
- }
- case INTERNET_STATUS_USER_INPUT_REQUIRED:
- case INTERNET_STATUS_STATE_CHANGE:
- // TODO(darin): This is probably a security problem. Do something better.
- ResumeSuspendedDownload(handle, 0);
- break;
- }
-}
diff --git a/net/url_request/url_request_inet_job.h b/net/url_request/url_request_inet_job.h
index 60ffcd1..e69de29 100644
--- a/net/url_request/url_request_inet_job.h
+++ b/net/url_request/url_request_inet_job.h
@@ -1,159 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_URL_REQUEST_URL_REQUEST_INET_JOB_H__
-#define NET_URL_REQUEST_URL_REQUEST_INET_JOB_H__
-
-#include <windows.h>
-#include <wininet.h>
-
-#include "base/lock.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_job.h"
-
-namespace net {
-class AuthData;
-}
-
-class MessageLoop;
-
-// For all WinInet-based URL requests
-class URLRequestInetJob : public URLRequestJob {
- public:
- URLRequestInetJob(URLRequest* request);
-
- virtual void SetExtraRequestHeaders(const std::string& headers) {
- extra_request_headers_ = headers;
- }
-
- virtual void Kill();
- virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
-
- // URLRequestJob Authentication methods
- virtual void SetAuth(const std::wstring& username,
- const std::wstring& password);
- virtual void CancelAuth();
-
- // A structure holding the result and error code of an asynchronous IO.
- // This is a copy of INTERNET_ASYNC_RESULT.
- struct AsyncResult {
- DWORD_PTR dwResult;
- DWORD dwError;
- };
-
- // A virtual method to handle WinInet callbacks. If this class
- // issues asynchronous IO, it will need to override this method
- // to receive completions of those asynchronous IOs. The class
- // must track whether it has an async IO outstanding, and if it
- // does not it must call the base class' OnIOComplete.
- virtual void OnIOComplete(const AsyncResult& result) = 0;
-
- // Used internally to setup the OnIOComplete call. Public because this
- // is called from the Windows procedure, and we don't want to make it a
- // friend so we can avoid the Windows headers for this header file.
- void CallOnIOComplete(const AsyncResult& result);
-
- HINTERNET request_handle() const { return request_handle_; }
-
- protected:
- virtual ~URLRequestInetJob();
-
- // Called by this class and subclasses to send or resend this request.
- virtual void SendRequest() = 0;
-
- // Calls InternetReadFile(Ex) depending on the derived class.
- // Returns ERROR_SUCCESS on success, or else a standard Windows error code
- // on failure (from GetLastError()).
- virtual int CallInternetRead(char* dest, int dest_size, int *bytes_read) = 0;
-
- // After the base class calls CallInternetRead and the result is available,
- // it will call this method to get the number of received bytes.
- virtual bool GetReadBytes(const AsyncResult& result, int* bytes_read) = 0;
-
- // Called by this class and subclasses whenever a WinInet call fails. This
- // method returns true if the error just means that we have to wait for
- // OnIOComplete to be called.
- bool ProcessRequestError(int error);
-
- // Cleans up the connection, if necessary, and closes the connection and
- // request handles. May be called multiple times, it will be a NOP if
- // there is nothing to do.
- void CleanupConnection();
-
- // Closes the given handle.
- void CleanupHandle(HINTERNET handle);
-
- // Returns the global handle to the internet (NOT the same as the connection
- // or request handle below)
- static HINTERNET GetTheInternet();
-
- // Makes appropriate asynch call to re-send a request based on
- // dynamic scheme type and user action at authentication prompt
- //(OK or Cancel)
- virtual void OnCancelAuth() = 0;
- virtual void OnSetAuth() = 0;
-
- // Handle of the connection for this request. This handle is created
- // by subclasses that create the connection according to their requirements.
- // It will be automatically destroyed by this class when the connection is
- // being closed. See also 'request_handle_'
- HINTERNET connection_handle_;
-
- // Handle of the specific request created by subclasses to meet their own
- // requirements. This handle has a more narrow scope than the connection
- // handle. If non-null, it will be automatically destroyed by this class
- // when the connection is being closed. It will be destroyed before the
- // connection handle.
- HINTERNET request_handle_;
-
- // The last error that occurred. Used by ContinueDespiteLastError to adjust
- // the request's load_flags to ignore this error.
- DWORD last_error_;
-
- // Any extra request headers (\n-delimited) that should be included in the
- // request.
- std::string extra_request_headers_;
-
- // Authentication information.
- scoped_refptr<net::AuthData> proxy_auth_;
- scoped_refptr<net::AuthData> server_auth_;
-
- private:
-
- // One-time global state setup
- static void InitializeTheInternet(const std::string& user_agent);
-
- // Runs on some background thread (called by WinInet)
- static void CALLBACK URLRequestStatusCallback(HINTERNET handle,
- DWORD_PTR job_id,
- DWORD status,
- LPVOID status_info,
- DWORD status_info_len);
-
- static HINTERNET the_internet_;
-#ifndef NDEBUG
- static MessageLoop* my_message_loop_; // Used to sanity-check that all
- // requests are made on the same
- // thread
-#endif
-
- // true if waiting for OnIOComplete to be called
- bool is_waiting_;
-
- // debugging state - is there a read already in progress
- bool read_in_progress_;
-
- // The result and error code of asynchronous IO. It is modified by the
- // status callback functions on asynchronous IO completion and passed to
- // CallOnIOComplete. Since there is at most one pending IO, the object
- // can reuse the async_result_ member for all its asynchronous IOs.
- AsyncResult async_result_;
-
- Lock loop_lock_;
- MessageLoop* loop_;
-
- DISALLOW_EVIL_CONSTRUCTORS(URLRequestInetJob);
-};
-
-#endif // NET_URL_REQUEST_URL_REQUEST_INET_JOB_H__
diff --git a/net/url_request/url_request_job_manager.cc b/net/url_request/url_request_job_manager.cc
index 0b300d1..7cd934e 100644
--- a/net/url_request/url_request_job_manager.cc
+++ b/net/url_request/url_request_job_manager.cc
@@ -14,11 +14,7 @@
#include "net/url_request/url_request_data_job.h"
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_file_job.h"
-#if defined(OS_WIN)
-#include "net/url_request/url_request_ftp_job.h"
-#else
#include "net/url_request/url_request_new_ftp_job.h"
-#endif
#include "net/url_request/url_request_http_job.h"
// The built-in set of protocol factories
@@ -35,11 +31,7 @@ static const SchemeToFactory kBuiltinFactories[] = {
{ "http", URLRequestHttpJob::Factory },
{ "https", URLRequestHttpJob::Factory },
{ "file", URLRequestFileJob::Factory },
-#if defined(OS_WIN)
- { "ftp", URLRequestFtpJob::Factory },
-#else
{ "ftp", URLRequestNewFtpJob::Factory },
-#endif
{ "about", URLRequestAboutJob::Factory },
{ "data", URLRequestDataJob::Factory },
};