diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-30 15:48:53 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-30 15:48:53 +0000 |
commit | f732c1e252e6b9f4311671c994a1207658090f20 (patch) | |
tree | 98b71691f8ee9f39f732c7b521fc011123b71c9e /chrome/browser/net | |
parent | 9a7f317d31d4478fb129b1c422f7f2a2d326658d (diff) | |
download | chromium_src-f732c1e252e6b9f4311671c994a1207658090f20.zip chromium_src-f732c1e252e6b9f4311671c994a1207658090f20.tar.gz chromium_src-f732c1e252e6b9f4311671c994a1207658090f20.tar.bz2 |
Move mock url request classes to a location when browser tests will be able to use them too.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/160366
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22056 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/net')
-rw-r--r-- | chrome/browser/net/url_request_failed_dns_job.cc | 37 | ||||
-rw-r--r-- | chrome/browser/net/url_request_failed_dns_job.h | 32 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_http_job.cc | 100 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_http_job.h | 44 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_net_error_job.cc | 100 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_net_error_job.h | 70 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_util.cc | 64 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_util.h | 17 | ||||
-rw-r--r-- | chrome/browser/net/url_request_slow_download_job.cc | 172 | ||||
-rw-r--r-- | chrome/browser/net/url_request_slow_download_job.h | 59 | ||||
-rw-r--r-- | chrome/browser/net/url_request_slow_http_job.cc | 58 | ||||
-rw-r--r-- | chrome/browser/net/url_request_slow_http_job.h | 41 |
12 files changed, 794 insertions, 0 deletions
diff --git a/chrome/browser/net/url_request_failed_dns_job.cc b/chrome/browser/net/url_request_failed_dns_job.cc new file mode 100644 index 0000000..e436204 --- /dev/null +++ b/chrome/browser/net/url_request_failed_dns_job.cc @@ -0,0 +1,37 @@ +// 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 "chrome/browser/net/url_request_failed_dns_job.h" + +#include "base/message_loop.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_filter.h" + +const char URLRequestFailedDnsJob::kTestUrl[] = + "http://url.handled.by.fake.dns/"; + +void URLRequestFailedDnsJob::Start() { + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( + this, &URLRequestFailedDnsJob::StartAsync)); +} + +/* static */ +void URLRequestFailedDnsJob::AddUrlHandler() { + URLRequestFilter* filter = URLRequestFilter::GetInstance(); + filter->AddUrlHandler(GURL(kTestUrl), + &URLRequestFailedDnsJob::Factory); +} + +/*static */ +URLRequestJob* URLRequestFailedDnsJob::Factory(URLRequest* request, + const std::string& scheme) { + return new URLRequestFailedDnsJob(request); +} + +void URLRequestFailedDnsJob::StartAsync() { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, + net::ERR_NAME_NOT_RESOLVED)); +} diff --git a/chrome/browser/net/url_request_failed_dns_job.h b/chrome/browser/net/url_request_failed_dns_job.h new file mode 100644 index 0000000..b1abc87 --- /dev/null +++ b/chrome/browser/net/url_request_failed_dns_job.h @@ -0,0 +1,32 @@ +// 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. +// This class simulates what wininet does when a dns lookup fails. + +#ifndef CHROME_BROWSER_NET_URL_REQUEST_FAILED_DNS_JOB_H_ +#define CHROME_BROWSER_NET_URL_REQUEST_FAILED_DNS_JOB_H_ + +#include "net/url_request/url_request_job.h" + +class URLRequestFailedDnsJob : public URLRequestJob { + public: + URLRequestFailedDnsJob(URLRequest* request) + : URLRequestJob(request) { } + + virtual void Start(); + + static URLRequestJob* Factory(URLRequest* request, + const std::string& scheme); + + // A test URL that can be used in UI tests. + static const char kTestUrl[]; + + // Adds the testing URLs to the URLRequestFilter. + static void AddUrlHandler(); + + private: + // Simulate a DNS failure. + void StartAsync(); +}; + +#endif // CHROME_BROWSER_NET_URL_REQUEST_FAILED_DNS_JOB_H_ diff --git a/chrome/browser/net/url_request_mock_http_job.cc b/chrome/browser/net/url_request_mock_http_job.cc new file mode 100644 index 0000000..fc654be --- /dev/null +++ b/chrome/browser/net/url_request_mock_http_job.cc @@ -0,0 +1,100 @@ +// 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 "chrome/browser/net/url_request_mock_http_job.h" + +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "net/base/net_util.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_request_filter.h" + +static const char kMockHostname[] = "mock.http"; +static const wchar_t kMockHeaderFileSuffix[] = L".mock-http-headers"; + +std::wstring URLRequestMockHTTPJob::base_path_ = L""; + +/* static */ +URLRequestJob* URLRequestMockHTTPJob::Factory(URLRequest* request, + const std::string& scheme) { + return new URLRequestMockHTTPJob(request, + GetOnDiskPath(base_path_, request, scheme)); +} + +/* static */ +void URLRequestMockHTTPJob::AddUrlHandler(const std::wstring& base_path) { + base_path_ = base_path; + + // Add kMockHostname to URLRequestFilter. + URLRequestFilter* filter = URLRequestFilter::GetInstance(); + filter->AddHostnameHandler("http", kMockHostname, + URLRequestMockHTTPJob::Factory); +} + +/* static */ +GURL URLRequestMockHTTPJob::GetMockUrl(const std::wstring& path) { + std::string url = "http://"; + url.append(kMockHostname); + url.append("/"); + url.append(WideToUTF8(path)); + return GURL(url); +} + +/* static */ +FilePath URLRequestMockHTTPJob::GetOnDiskPath(const std::wstring& base_path, + URLRequest* request, + const std::string& scheme) { + std::wstring file_url(L"file:///"); + file_url += base_path; + const std::string& url = request->url().spec(); + // Fix up the url to be the file url we're loading from disk. + std::string host_prefix("http://"); + host_prefix.append(kMockHostname); + size_t host_prefix_len = host_prefix.length(); + if (url.compare(0, host_prefix_len, host_prefix.data(), + host_prefix_len) == 0) { + file_url += UTF8ToWide(url.substr(host_prefix_len)); + } + + // Convert the file:/// URL to a path on disk. + FilePath file_path; + net::FileURLToFilePath(GURL(WideToUTF8(file_url)), &file_path); + return file_path; +} + +URLRequestMockHTTPJob::URLRequestMockHTTPJob(URLRequest* request, + const FilePath& file_path) + : URLRequestFileJob(request, file_path) { } + +// Public virtual version. +void URLRequestMockHTTPJob::GetResponseInfo(net::HttpResponseInfo* info) { + // Forward to private const version. + GetResponseInfoConst(info); +} + +// Private const version. +void URLRequestMockHTTPJob::GetResponseInfoConst( + net::HttpResponseInfo* info) const { + std::wstring header_file = file_path_.ToWStringHack() + kMockHeaderFileSuffix; + std::string raw_headers; + if (!file_util::ReadFileToString(header_file, &raw_headers)) + return; + + // ParseRawHeaders expects \0 to end each header line. + ReplaceSubstringsAfterOffset(&raw_headers, 0, "\n", std::string("\0", 1)); + info->headers = new net::HttpResponseHeaders(raw_headers); +} + +bool URLRequestMockHTTPJob::GetMimeType(std::string* mime_type) const { + net::HttpResponseInfo info; + GetResponseInfoConst(&info); + return info.headers && info.headers->GetMimeType(mime_type); +} + +bool URLRequestMockHTTPJob::GetCharset(std::string* charset) { + net::HttpResponseInfo info; + GetResponseInfo(&info); + return info.headers && info.headers->GetCharset(charset); +} diff --git a/chrome/browser/net/url_request_mock_http_job.h b/chrome/browser/net/url_request_mock_http_job.h new file mode 100644 index 0000000..36e6acb --- /dev/null +++ b/chrome/browser/net/url_request_mock_http_job.h @@ -0,0 +1,44 @@ +// 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. +// +// A URLRequestJob class that pulls the content and http headers from disk. + +#ifndef CHROME_BROWSER_NET_URL_REQUEST_MOCK_HTTP_JOB_H_ +#define CHROME_BROWSER_NET_URL_REQUEST_MOCK_HTTP_JOB_H_ + +#include <string> + +#include "net/url_request/url_request_file_job.h" + +class URLRequestMockHTTPJob : public URLRequestFileJob { + public: + URLRequestMockHTTPJob(URLRequest* request, const FilePath& file_path); + virtual ~URLRequestMockHTTPJob() { } + + virtual bool GetMimeType(std::string* mime_type) const; + virtual bool GetCharset(std::string* charset); + virtual void GetResponseInfo(net::HttpResponseInfo* info); + + static URLRequest::ProtocolFactory Factory; + + // Adds the testing URLs to the URLRequestFilter. + static void AddUrlHandler(const std::wstring& base_path); + + // Given the path to a file relative to base_path_, construct a mock URL. + static GURL GetMockUrl(const std::wstring& path); + + protected: + static FilePath GetOnDiskPath(const std::wstring& base_path, + URLRequest* request, + const std::string& scheme); + + private: + void GetResponseInfoConst(net::HttpResponseInfo* info) const; + + // This is the file path leading to the root of the directory to use as the + // root of the http server. + static std::wstring base_path_; +}; + +# endif // CHROME_BROWSER_NET_URL_REQUEST_MOCK_HTTP_JOB_H_ diff --git a/chrome/browser/net/url_request_mock_net_error_job.cc b/chrome/browser/net/url_request_mock_net_error_job.cc new file mode 100644 index 0000000..8441f6a --- /dev/null +++ b/chrome/browser/net/url_request_mock_net_error_job.cc @@ -0,0 +1,100 @@ +// 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 "chrome/browser/net/url_request_mock_net_error_job.h" + +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "net/base/net_errors.h" +#include "net/base/net_util.h" +#include "net/url_request/url_request_filter.h" + +// static +URLRequestMockNetErrorJob::URLMockInfoMap + URLRequestMockNetErrorJob::url_mock_info_map_; + +// static +void URLRequestMockNetErrorJob::AddMockedURL(const GURL& url, + const std::wstring& base, + const std::vector<int>& errors, + net::X509Certificate* ssl_cert) { +#ifndef NDEBUG + URLMockInfoMap::const_iterator iter = url_mock_info_map_.find(url); + DCHECK(iter == url_mock_info_map_.end()); +#endif + + url_mock_info_map_[url] = MockInfo(base, errors, ssl_cert); + URLRequestFilter::GetInstance() + ->AddUrlHandler(url, &URLRequestMockNetErrorJob::Factory); +} + +// static +void URLRequestMockNetErrorJob::RemoveMockedURL(const GURL& url) { + URLMockInfoMap::iterator iter = url_mock_info_map_.find(url); + DCHECK(iter != url_mock_info_map_.end()); + url_mock_info_map_.erase(iter); + URLRequestFilter::GetInstance()->RemoveUrlHandler(url); +} + +// static +URLRequestJob* URLRequestMockNetErrorJob::Factory(URLRequest* request, + const std::string& scheme) { + GURL url = request->url(); + + URLMockInfoMap::const_iterator iter = url_mock_info_map_.find(url); + DCHECK(iter != url_mock_info_map_.end()); + + MockInfo mock_info = iter->second; + + // URLRequestMockNetErrorJob derives from URLRequestFileJob. We pass a + // FilePath so that the URLRequestFileJob methods will do the loading from + // the files. + std::wstring file_url(L"file:///"); + file_url.append(mock_info.base); + file_url.append(UTF8ToWide(url.path())); + // Convert the file:/// URL to a path on disk. + FilePath file_path; + net::FileURLToFilePath(GURL(WideToUTF8(file_url)), &file_path); + return new URLRequestMockNetErrorJob(request, mock_info.errors, + mock_info.ssl_cert, + file_path); +} + +URLRequestMockNetErrorJob::URLRequestMockNetErrorJob(URLRequest* request, + const std::vector<int>& errors, net::X509Certificate* cert, + const FilePath& file_path) + : URLRequestMockHTTPJob(request, file_path), + errors_(errors), + ssl_cert_(cert) { +} + +URLRequestMockNetErrorJob::~URLRequestMockNetErrorJob() { +} + +void URLRequestMockNetErrorJob::Start() { + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( + this, &URLRequestMockNetErrorJob::StartAsync)); +} + +void URLRequestMockNetErrorJob::StartAsync() { + if (errors_.empty()) { + URLRequestMockHTTPJob::Start(); + } else { + int error = errors_[0]; + errors_.erase(errors_.begin()); + + if (net::IsCertificateError(error)) { + DCHECK(ssl_cert_); + request_->delegate()->OnSSLCertificateError(request_, error, + ssl_cert_.get()); + } else { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error)); + } + } +} + +void URLRequestMockNetErrorJob::ContinueDespiteLastError() { + Start(); +} diff --git a/chrome/browser/net/url_request_mock_net_error_job.h b/chrome/browser/net/url_request_mock_net_error_job.h new file mode 100644 index 0000000..8a7c87c --- /dev/null +++ b/chrome/browser/net/url_request_mock_net_error_job.h @@ -0,0 +1,70 @@ +// 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. + +// A URLRequestJob class that simulates network errors (including https +// related). +// It is based on URLRequestMockHttpJob. + +#ifndef CHROME_BROWSER_NET_URL_REQUEST_MOCK_NET_ERROR_H_ +#define CHROME_BROWSER_NET_URL_REQUEST_MOCK_NET_ERROR_H_ + +#include "chrome/browser/net/url_request_mock_http_job.h" + +class URLRequestMockNetErrorJob : public URLRequestMockHTTPJob { + public: + URLRequestMockNetErrorJob(URLRequest* request, + const std::vector<int>& errors, + net::X509Certificate* ssl_cert, + const FilePath& file_path); + virtual ~URLRequestMockNetErrorJob(); + + virtual void Start(); + virtual void ContinueDespiteLastError(); + + // Add the specified URL to the list of URLs that should be mocked. When this + // URL is hit, the specified |errors| will be played. If any of these errors + // is a cert error, |ssl_cert| will be used as the ssl cert when notifying of + // the error. |ssl_cert| can be NULL if |errors| does not contain any cert + // errors. |base| is the location on disk where the file mocking the URL + // contents and http-headers should be retrieved from. + static void AddMockedURL(const GURL& url, + const std::wstring& base, + const std::vector<int>& errors, + net::X509Certificate* ssl_cert); + + // Removes the specified |url| from the list of mocked urls. + static void RemoveMockedURL(const GURL& url); + + private: + struct MockInfo { + MockInfo() : ssl_cert(NULL) { } + MockInfo(std::wstring base, + std::vector<int> errors, + net::X509Certificate* ssl_cert) + : base(base), + errors(errors), + ssl_cert(ssl_cert) { } + + std::wstring base; + std::vector<int> errors; + scoped_refptr<net::X509Certificate> ssl_cert; + }; + + static URLRequest::ProtocolFactory Factory; + + void StartAsync(); + + // The errors to simulate. + std::vector<int> errors_; + + // The certificate to use for SSL errors. + scoped_refptr<net::X509Certificate> ssl_cert_; + + typedef std::map<GURL, MockInfo> URLMockInfoMap; + static URLMockInfoMap url_mock_info_map_; + + DISALLOW_EVIL_CONSTRUCTORS(URLRequestMockNetErrorJob); +}; + +#endif // #define CHROME_BROWSER_NET_URL_REQUEST_MOCK_NET_ERROR_H_ diff --git a/chrome/browser/net/url_request_mock_util.cc b/chrome/browser/net/url_request_mock_util.cc new file mode 100644 index 0000000..ad0ed09 --- /dev/null +++ b/chrome/browser/net/url_request_mock_util.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2009 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 "chrome/browser/net/url_request_mock_util.h" + +#include <string> + +#include "base/message_loop.h" +#include "base/path_service.h" +#include "base/task.h" +#include "base/thread.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/net/url_request_failed_dns_job.h" +#include "chrome/browser/net/url_request_mock_http_job.h" +#include "chrome/browser/net/url_request_slow_download_job.h" +#include "chrome/browser/net/url_request_slow_http_job.h" +#include "chrome/common/chrome_paths.h" +#include "net/url_request/url_request_filter.h" + +namespace { + +// Helper class for making changes to the URLRequest ProtocolFactory on the +// IO thread. +class SetUrlRequestMocksEnabledTask : public Task { + public: + explicit SetUrlRequestMocksEnabledTask(bool enabled) : enabled_(enabled) { + } + + virtual void Run() { + if (enabled_) { + URLRequestFilter::GetInstance()->ClearHandlers(); + + URLRequestFailedDnsJob::AddUrlHandler(); + URLRequestSlowDownloadJob::AddUrlHandler(); + + std::wstring root_http; + PathService::Get(chrome::DIR_TEST_DATA, &root_http); + URLRequestMockHTTPJob::AddUrlHandler(root_http); + URLRequestSlowHTTPJob::AddUrlHandler(root_http); + } else { + // Revert to the default handlers. + URLRequestFilter::GetInstance()->ClearHandlers(); + } + } + + private: + bool enabled_; + + DISALLOW_COPY_AND_ASSIGN(SetUrlRequestMocksEnabledTask); +}; + +} // namespace + +namespace chrome_browser_net { + +void SetUrlRequestMocksEnabled(bool enabled) { + // Since this involves changing the URLRequest ProtocolFactory, we want to + // run on the IO thread. + g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, + new SetUrlRequestMocksEnabledTask(enabled)); +} + +} // namespace chrome_browser_net diff --git a/chrome/browser/net/url_request_mock_util.h b/chrome/browser/net/url_request_mock_util.h new file mode 100644 index 0000000..b3a81bb --- /dev/null +++ b/chrome/browser/net/url_request_mock_util.h @@ -0,0 +1,17 @@ +// Copyright (c) 2009 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 CHROME_BROWSER_NET_URL_REQUEST_MOCK_UTIL_H_ +#define CHROME_BROWSER_NET_URL_REQUEST_MOCK_UTIL_H_ + +// You should use routines in this file only for test code! + +namespace chrome_browser_net { + +// Enables or disables url request filters for mocked url requests. +void SetUrlRequestMocksEnabled(bool enabled); + +} // namespace chrome_browser_net + +#endif // CHROME_BROWSER_NET_URL_REQUEST_MOCK_UTIL_H_ diff --git a/chrome/browser/net/url_request_slow_download_job.cc b/chrome/browser/net/url_request_slow_download_job.cc new file mode 100644 index 0000000..93768ec --- /dev/null +++ b/chrome/browser/net/url_request_slow_download_job.cc @@ -0,0 +1,172 @@ +// 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 "chrome/browser/net/url_request_slow_download_job.h" + +#include "base/message_loop.h" +#include "base/string_util.h" +#include "googleurl/src/gurl.h" +#include "net/base/io_buffer.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_filter.h" + +const int kFirstDownloadSize = 1024 * 35; +const int kSecondDownloadSize = 1024 * 10; + +const char URLRequestSlowDownloadJob::kUnknownSizeUrl[] = + "http://url.handled.by.slow.download/download-unknown-size"; +const char URLRequestSlowDownloadJob::kKnownSizeUrl[] = + "http://url.handled.by.slow.download/download-known-size"; +const char URLRequestSlowDownloadJob::kFinishDownloadUrl[] = + "http://url.handled.by.slow.download/download-finish"; + +std::vector<URLRequestSlowDownloadJob*> + URLRequestSlowDownloadJob::kPendingRequests; + +void URLRequestSlowDownloadJob::Start() { + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this, + &URLRequestSlowDownloadJob::StartAsync)); +} + +/* static */ +void URLRequestSlowDownloadJob::AddUrlHandler() { + URLRequestFilter* filter = URLRequestFilter::GetInstance(); + filter->AddUrlHandler(GURL(kUnknownSizeUrl), + &URLRequestSlowDownloadJob::Factory); + filter->AddUrlHandler(GURL(kKnownSizeUrl), + &URLRequestSlowDownloadJob::Factory); + filter->AddUrlHandler(GURL(kFinishDownloadUrl), + &URLRequestSlowDownloadJob::Factory); +} + +/*static */ +URLRequestJob* URLRequestSlowDownloadJob::Factory(URLRequest* request, + const std::string& scheme) { + URLRequestSlowDownloadJob* job = new URLRequestSlowDownloadJob(request); + if (request->url().spec() != kFinishDownloadUrl) + URLRequestSlowDownloadJob::kPendingRequests.push_back(job); + return job; +} + +/* static */ +void URLRequestSlowDownloadJob::FinishPendingRequests() { + typedef std::vector<URLRequestSlowDownloadJob*> JobList; + for (JobList::iterator it = kPendingRequests.begin(); it != + kPendingRequests.end(); ++it) { + (*it)->set_should_finish_download(); + } + kPendingRequests.clear(); +} + +URLRequestSlowDownloadJob::URLRequestSlowDownloadJob(URLRequest* request) + : URLRequestJob(request), + first_download_size_remaining_(kFirstDownloadSize), + should_finish_download_(false), + should_send_second_chunk_(false) { +} + +void URLRequestSlowDownloadJob::StartAsync() { + if (LowerCaseEqualsASCII(kFinishDownloadUrl, request_->url().spec().c_str())) + URLRequestSlowDownloadJob::FinishPendingRequests(); + + NotifyHeadersComplete(); +} + +bool URLRequestSlowDownloadJob::ReadRawData(net::IOBuffer* buf, int buf_size, + int *bytes_read) { + if (LowerCaseEqualsASCII(kFinishDownloadUrl, + request_->url().spec().c_str())) { + *bytes_read = 0; + return true; + } + + if (should_send_second_chunk_) { + DCHECK(buf_size > kSecondDownloadSize); + for (int i = 0; i < kSecondDownloadSize; ++i) { + buf->data()[i] = '*'; + } + *bytes_read = kSecondDownloadSize; + should_send_second_chunk_ = false; + return true; + } + + if (first_download_size_remaining_ > 0) { + int send_size = std::min(first_download_size_remaining_, buf_size); + for (int i = 0; i < send_size; ++i) { + buf->data()[i] = '*'; + } + *bytes_read = send_size; + first_download_size_remaining_ -= send_size; + + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + DCHECK(!is_done()); + return true; + } + + if (should_finish_download_) { + *bytes_read = 0; + return true; + } + + // If we make it here, the first chunk has been sent and we need to wait + // until a request is made for kFinishDownloadUrl. + MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( + this, &URLRequestSlowDownloadJob::CheckDoneStatus), 100); + AddRef(); + + // Return false to signal there is pending data. + return false; +} + +void URLRequestSlowDownloadJob::CheckDoneStatus() { + if (should_finish_download_) { + should_send_second_chunk_ = true; + SetStatus(URLRequestStatus()); + NotifyReadComplete(kSecondDownloadSize); + Release(); + } else { + MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( + this, &URLRequestSlowDownloadJob::CheckDoneStatus), 100); + } +} + +// Public virtual version. +void URLRequestSlowDownloadJob::GetResponseInfo(net::HttpResponseInfo* info) { + // Forward to private const version. + GetResponseInfoConst(info); +} + +// Private const version. +void URLRequestSlowDownloadJob::GetResponseInfoConst( + net::HttpResponseInfo* info) const { + // Send back mock headers. + std::string raw_headers; + if (LowerCaseEqualsASCII(kFinishDownloadUrl, + request_->url().spec().c_str())) { + raw_headers.append( + "HTTP/1.1 200 OK\n" + "Content-type: text/plain\n"); + } else { + raw_headers.append( + "HTTP/1.1 200 OK\n" + "Content-type: application/octet-stream\n" + "Cache-Control: max-age=0\n"); + + if (LowerCaseEqualsASCII(kKnownSizeUrl, request_->url().spec().c_str())) { + raw_headers.append(StringPrintf("Content-Length: %d\n", + kFirstDownloadSize + kSecondDownloadSize)); + } + } + + // ParseRawHeaders expects \0 to end each header line. + ReplaceSubstringsAfterOffset(&raw_headers, 0, "\n", std::string("\0", 1)); + info->headers = new net::HttpResponseHeaders(raw_headers); +} + +bool URLRequestSlowDownloadJob::GetMimeType(std::string* mime_type) const { + net::HttpResponseInfo info; + GetResponseInfoConst(&info); + return info.headers && info.headers->GetMimeType(mime_type); +} diff --git a/chrome/browser/net/url_request_slow_download_job.h b/chrome/browser/net/url_request_slow_download_job.h new file mode 100644 index 0000000..49785a8 --- /dev/null +++ b/chrome/browser/net/url_request_slow_download_job.h @@ -0,0 +1,59 @@ +// 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. +// This class simulates a slow download. This used in a UI test to test the +// download manager. Requests to |kUnknownSizeUrl| and |kKnownSizeUrl| start +// downloads that pause after the first + +#ifndef CHROME_BROWSER_NET_URL_REQUEST_SLOW_DOWNLOAD_JOB_H_ +#define CHROME_BROWSER_NET_URL_REQUEST_SLOW_DOWNLOAD_JOB_H_ + +#include <string> +#include <vector> + +#include "net/url_request/url_request_job.h" + +class URLRequestSlowDownloadJob : public URLRequestJob { + public: + explicit URLRequestSlowDownloadJob(URLRequest* request); + virtual ~URLRequestSlowDownloadJob() { } + + // Timer callback, used to check to see if we should finish our download and + // send the second chunk. + void CheckDoneStatus(); + + // URLRequestJob methods + virtual void Start(); + virtual bool GetMimeType(std::string* mime_type) const; + virtual void GetResponseInfo(net::HttpResponseInfo* info); + virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read); + + static URLRequestJob* Factory(URLRequest* request, + const std::string& scheme); + + // Test URLs. + static const char kUnknownSizeUrl[]; + static const char kKnownSizeUrl[]; + static const char kFinishDownloadUrl[]; + + // Adds the testing URLs to the URLRequestFilter. + static void AddUrlHandler(); + + private: + void GetResponseInfoConst(net::HttpResponseInfo* info) const; + + // Mark all pending requests to be finished. We keep track of pending + // requests in |kPendingRequests|. + static void FinishPendingRequests(); + static std::vector<URLRequestSlowDownloadJob*> kPendingRequests; + + void StartAsync(); + + void set_should_finish_download() { should_finish_download_ = true; } + + int first_download_size_remaining_; + bool should_finish_download_; + bool should_send_second_chunk_; +}; + +#endif // CHROME_BROWSER_NET_URL_REQUEST_SLOW_DOWNLOAD_JOB_H_ diff --git a/chrome/browser/net/url_request_slow_http_job.cc b/chrome/browser/net/url_request_slow_http_job.cc new file mode 100644 index 0000000..02a3b2b --- /dev/null +++ b/chrome/browser/net/url_request_slow_http_job.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2009 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 "chrome/browser/net/url_request_slow_http_job.h" + +#include "base/platform_thread.h" +#include "base/string_util.h" +#include "base/time.h" +#include "net/url_request/url_request_filter.h" + +static const char kMockHostname[] = "mock.slow.http"; + +std::wstring URLRequestSlowHTTPJob::base_path_ = L""; + +// static +const int URLRequestSlowHTTPJob::kDelayMs = 1000; + +using base::TimeDelta; + +/* static */ +URLRequestJob* URLRequestSlowHTTPJob::Factory(URLRequest* request, + const std::string& scheme) { + return new URLRequestSlowHTTPJob(request, + GetOnDiskPath(base_path_, request, scheme)); +} + +/* static */ +void URLRequestSlowHTTPJob::AddUrlHandler(const std::wstring& base_path) { + base_path_ = base_path; + + // Add kMockHostname to URLRequestFilter. + URLRequestFilter* filter = URLRequestFilter::GetInstance(); + filter->AddHostnameHandler("http", kMockHostname, + URLRequestSlowHTTPJob::Factory); +} + +/* static */ +GURL URLRequestSlowHTTPJob::GetMockUrl(const std::wstring& path) { + std::string url = "http://"; + url.append(kMockHostname); + url.append("/"); + url.append(WideToUTF8(path)); + return GURL(url); +} + +URLRequestSlowHTTPJob::URLRequestSlowHTTPJob(URLRequest* request, + const FilePath& file_path) + : URLRequestMockHTTPJob(request, file_path) { } + +void URLRequestSlowHTTPJob::Start() { + delay_timer_.Start(TimeDelta::FromMilliseconds(kDelayMs), this, + &URLRequestSlowHTTPJob::RealStart); +} + +void URLRequestSlowHTTPJob::RealStart() { + URLRequestMockHTTPJob::Start(); +} diff --git a/chrome/browser/net/url_request_slow_http_job.h b/chrome/browser/net/url_request_slow_http_job.h new file mode 100644 index 0000000..d51e2d2 --- /dev/null +++ b/chrome/browser/net/url_request_slow_http_job.h @@ -0,0 +1,41 @@ +// Copyright (c) 2009 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. +// +// A URLRequestMockHTTPJob class that inserts a time delay in processing. + +#ifndef CHROME_BROWSER_NET_URL_REQUEST_SLOW_HTTP_JOB_H_ +#define CHROME_BROWSER_NET_URL_REQUEST_SLOW_HTTP_JOB_H_ + +#include <string> + +#include "base/timer.h" +#include "chrome/browser/net/url_request_mock_http_job.h" + +class URLRequestSlowHTTPJob : public URLRequestMockHTTPJob { + public: + URLRequestSlowHTTPJob(URLRequest* request, const FilePath& file_path); + + static const int kDelayMs; + + static URLRequest::ProtocolFactory Factory; + + // Adds the testing URLs to the URLRequestFilter. + static void AddUrlHandler(const std::wstring& base_path); + + // Given the path to a file relative to base_path_, construct a mock URL. + static GURL GetMockUrl(const std::wstring& path); + + virtual void Start(); + + private: + void RealStart(); + + base::OneShotTimer<URLRequestSlowHTTPJob> delay_timer_; + + // This is the file path leading to the root of the directory to use as the + // root of the http server. + static std::wstring base_path_; +}; + +# endif // CHROME_BROWSER_NET_URL_REQUEST_SLOW_HTTP_JOB_H_ |