summaryrefslogtreecommitdiffstats
path: root/chrome/browser/net
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-30 15:48:53 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-30 15:48:53 +0000
commitf732c1e252e6b9f4311671c994a1207658090f20 (patch)
tree98b71691f8ee9f39f732c7b521fc011123b71c9e /chrome/browser/net
parent9a7f317d31d4478fb129b1c422f7f2a2d326658d (diff)
downloadchromium_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.cc37
-rw-r--r--chrome/browser/net/url_request_failed_dns_job.h32
-rw-r--r--chrome/browser/net/url_request_mock_http_job.cc100
-rw-r--r--chrome/browser/net/url_request_mock_http_job.h44
-rw-r--r--chrome/browser/net/url_request_mock_net_error_job.cc100
-rw-r--r--chrome/browser/net/url_request_mock_net_error_job.h70
-rw-r--r--chrome/browser/net/url_request_mock_util.cc64
-rw-r--r--chrome/browser/net/url_request_mock_util.h17
-rw-r--r--chrome/browser/net/url_request_slow_download_job.cc172
-rw-r--r--chrome/browser/net/url_request_slow_download_job.h59
-rw-r--r--chrome/browser/net/url_request_slow_http_job.cc58
-rw-r--r--chrome/browser/net/url_request_slow_http_job.h41
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_