blob: bd4f5e187a36a1d54be6dcb4934acb5a56763f23 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/url_request/test_url_fetcher_factory.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/compiler_specific.h"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010011#include "base/file_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "base/memory/weak_ptr.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +010013#include "base/message_loop/message_loop.h"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010014#include "base/threading/thread_restrictions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000015#include "net/base/host_port_pair.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000016#include "net/base/io_buffer.h"
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000017#include "net/base/net_errors.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000018#include "net/http/http_response_headers.h"
19#include "net/url_request/url_fetcher_delegate.h"
20#include "net/url_request/url_fetcher_impl.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010021#include "net/url_request/url_fetcher_response_writer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000022#include "net/url_request/url_request_status.h"
23
24namespace net {
25
26ScopedURLFetcherFactory::ScopedURLFetcherFactory(
27 URLFetcherFactory* factory) {
28 DCHECK(!URLFetcherImpl::factory());
29 URLFetcherImpl::set_factory(factory);
30}
31
32ScopedURLFetcherFactory::~ScopedURLFetcherFactory() {
33 DCHECK(URLFetcherImpl::factory());
34 URLFetcherImpl::set_factory(NULL);
35}
36
37TestURLFetcher::TestURLFetcher(int id,
38 const GURL& url,
39 URLFetcherDelegate* d)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000040 : owner_(NULL),
41 id_(id),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000042 original_url_(url),
43 delegate_(d),
44 delegate_for_tests_(NULL),
45 did_receive_last_chunk_(false),
46 fake_load_flags_(0),
47 fake_response_code_(-1),
48 fake_response_destination_(STRING),
49 fake_was_fetched_via_proxy_(false),
50 fake_max_retries_(0) {
51}
52
53TestURLFetcher::~TestURLFetcher() {
54 if (delegate_for_tests_)
55 delegate_for_tests_->OnRequestEnd(id_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000056 if (owner_)
57 owner_->RemoveFetcherFromMap(id_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000058}
59
60void TestURLFetcher::SetUploadData(const std::string& upload_content_type,
61 const std::string& upload_content) {
62 upload_data_ = upload_content;
63}
64
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000065void TestURLFetcher::SetUploadFilePath(
66 const std::string& upload_content_type,
67 const base::FilePath& file_path,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010068 uint64 range_offset,
69 uint64 range_length,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000070 scoped_refptr<base::TaskRunner> file_task_runner) {
71 upload_file_path_ = file_path;
72}
73
Torne (Richard Coles)58218062012-11-14 11:43:16 +000074void TestURLFetcher::SetChunkedUpload(const std::string& upload_content_type) {
75}
76
77void TestURLFetcher::AppendChunkToUpload(const std::string& data,
78 bool is_last_chunk) {
79 DCHECK(!did_receive_last_chunk_);
80 did_receive_last_chunk_ = is_last_chunk;
81 chunks_.push_back(data);
82 if (delegate_for_tests_)
83 delegate_for_tests_->OnChunkUpload(id_);
84}
85
86void TestURLFetcher::SetLoadFlags(int load_flags) {
87 fake_load_flags_= load_flags;
88}
89
90int TestURLFetcher::GetLoadFlags() const {
91 return fake_load_flags_;
92}
93
94void TestURLFetcher::SetReferrer(const std::string& referrer) {
95}
96
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000097void TestURLFetcher::SetReferrerPolicy(
98 URLRequest::ReferrerPolicy referrer_policy) {
99}
100
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000101void TestURLFetcher::SetExtraRequestHeaders(
102 const std::string& extra_request_headers) {
103 fake_extra_request_headers_.Clear();
104 fake_extra_request_headers_.AddHeadersFromString(extra_request_headers);
105}
106
107void TestURLFetcher::AddExtraRequestHeader(const std::string& header_line) {
108 fake_extra_request_headers_.AddHeaderFromString(header_line);
109}
110
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000111void TestURLFetcher::SetRequestContext(
112 URLRequestContextGetter* request_context_getter) {
113}
114
115void TestURLFetcher::SetFirstPartyForCookies(
116 const GURL& first_party_for_cookies) {
117}
118
119void TestURLFetcher::SetURLRequestUserData(
120 const void* key,
121 const CreateDataCallback& create_data_callback) {
122}
123
124void TestURLFetcher::SetStopOnRedirect(bool stop_on_redirect) {
125}
126
127void TestURLFetcher::SetAutomaticallyRetryOn5xx(bool retry) {
128}
129
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000130void TestURLFetcher::SetMaxRetriesOn5xx(int max_retries) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000131 fake_max_retries_ = max_retries;
132}
133
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000134int TestURLFetcher::GetMaxRetriesOn5xx() const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000135 return fake_max_retries_;
136}
137
138base::TimeDelta TestURLFetcher::GetBackoffDelay() const {
139 return fake_backoff_delay_;
140}
141
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000142void TestURLFetcher::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
143}
144
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000145void TestURLFetcher::SaveResponseToFileAtPath(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000146 const base::FilePath& file_path,
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000147 scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100148 SetResponseFilePath(file_path);
149 // Asynchronous IO is not supported, so file_task_runner is ignored.
150 base::ThreadRestrictions::ScopedAllowIO allow_io;
151 const size_t written_bytes = base::WriteFile(
152 file_path, fake_response_string_.c_str(), fake_response_string_.size());
153 DCHECK_EQ(written_bytes, fake_response_string_.size());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000154}
155
156void TestURLFetcher::SaveResponseToTemporaryFile(
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000157 scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000158}
159
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100160void TestURLFetcher::SaveResponseWithWriter(
161 scoped_ptr<URLFetcherResponseWriter> response_writer) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100162 // In class URLFetcherCore this method is called by all three:
163 // GetResponseAsString() / SaveResponseToFileAtPath() /
164 // SaveResponseToTemporaryFile(). But here (in TestURLFetcher), this method
165 // is never used by any of these three methods. So, file writing is expected
166 // to be done in SaveResponseToFileAtPath(), and this method supports only
167 // URLFetcherStringWriter (for testing of this method only).
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000168 if (fake_response_destination_ == STRING) {
169 response_writer_ = response_writer.Pass();
170 int response = response_writer_->Initialize(CompletionCallback());
171 // The TestURLFetcher doesn't handle asynchronous writes.
172 DCHECK_EQ(OK, response);
173
174 scoped_refptr<IOBuffer> buffer(new StringIOBuffer(fake_response_string_));
175 response = response_writer_->Write(buffer.get(),
176 fake_response_string_.size(),
177 CompletionCallback());
178 DCHECK_EQ(static_cast<int>(fake_response_string_.size()), response);
179 response = response_writer_->Finish(CompletionCallback());
180 DCHECK_EQ(OK, response);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100181 } else if (fake_response_destination_ == TEMP_FILE) {
182 // SaveResponseToFileAtPath() should be called instead of this method to
183 // save file. Asynchronous file writing using URLFetcherFileWriter is not
184 // supported.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000185 NOTIMPLEMENTED();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100186 } else {
187 NOTREACHED();
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000188 }
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100189}
190
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000191HttpResponseHeaders* TestURLFetcher::GetResponseHeaders() const {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100192 return fake_response_headers_.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000193}
194
195HostPortPair TestURLFetcher::GetSocketAddress() const {
196 NOTIMPLEMENTED();
197 return HostPortPair();
198}
199
200bool TestURLFetcher::WasFetchedViaProxy() const {
201 return fake_was_fetched_via_proxy_;
202}
203
204void TestURLFetcher::Start() {
205 // Overriden to do nothing. It is assumed the caller will notify the delegate.
206 if (delegate_for_tests_)
207 delegate_for_tests_->OnRequestStart(id_);
208}
209
210const GURL& TestURLFetcher::GetOriginalURL() const {
211 return original_url_;
212}
213
214const GURL& TestURLFetcher::GetURL() const {
215 return fake_url_;
216}
217
218const URLRequestStatus& TestURLFetcher::GetStatus() const {
219 return fake_status_;
220}
221
222int TestURLFetcher::GetResponseCode() const {
223 return fake_response_code_;
224}
225
226const ResponseCookies& TestURLFetcher::GetCookies() const {
227 return fake_cookies_;
228}
229
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000230void TestURLFetcher::ReceivedContentWasMalformed() {
231}
232
233bool TestURLFetcher::GetResponseAsString(
234 std::string* out_response_string) const {
235 if (fake_response_destination_ != STRING)
236 return false;
237
238 *out_response_string = fake_response_string_;
239 return true;
240}
241
242bool TestURLFetcher::GetResponseAsFilePath(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000243 bool take_ownership, base::FilePath* out_response_path) const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000244 if (fake_response_destination_ != TEMP_FILE)
245 return false;
246
247 *out_response_path = fake_response_file_path_;
248 return true;
249}
250
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000251void TestURLFetcher::GetExtraRequestHeaders(
252 HttpRequestHeaders* headers) const {
253 *headers = fake_extra_request_headers_;
254}
255
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000256void TestURLFetcher::set_status(const URLRequestStatus& status) {
257 fake_status_ = status;
258}
259
260void TestURLFetcher::set_was_fetched_via_proxy(bool flag) {
261 fake_was_fetched_via_proxy_ = flag;
262}
263
264void TestURLFetcher::set_response_headers(
265 scoped_refptr<HttpResponseHeaders> headers) {
266 fake_response_headers_ = headers;
267}
268
269void TestURLFetcher::set_backoff_delay(base::TimeDelta backoff_delay) {
270 fake_backoff_delay_ = backoff_delay;
271}
272
273void TestURLFetcher::SetDelegateForTests(DelegateForTests* delegate_for_tests) {
274 delegate_for_tests_ = delegate_for_tests;
275}
276
277void TestURLFetcher::SetResponseString(const std::string& response) {
278 fake_response_destination_ = STRING;
279 fake_response_string_ = response;
280}
281
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000282void TestURLFetcher::SetResponseFilePath(const base::FilePath& path) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000283 fake_response_destination_ = TEMP_FILE;
284 fake_response_file_path_ = path;
285}
286
287TestURLFetcherFactory::TestURLFetcherFactory()
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100288 : ScopedURLFetcherFactory(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000289 delegate_for_tests_(NULL),
290 remove_fetcher_on_delete_(false) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000291}
292
293TestURLFetcherFactory::~TestURLFetcherFactory() {}
294
295URLFetcher* TestURLFetcherFactory::CreateURLFetcher(
296 int id,
297 const GURL& url,
298 URLFetcher::RequestType request_type,
299 URLFetcherDelegate* d) {
300 TestURLFetcher* fetcher = new TestURLFetcher(id, url, d);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000301 if (remove_fetcher_on_delete_)
302 fetcher->set_owner(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000303 fetcher->SetDelegateForTests(delegate_for_tests_);
304 fetchers_[id] = fetcher;
305 return fetcher;
306}
307
308TestURLFetcher* TestURLFetcherFactory::GetFetcherByID(int id) const {
309 Fetchers::const_iterator i = fetchers_.find(id);
310 return i == fetchers_.end() ? NULL : i->second;
311}
312
313void TestURLFetcherFactory::RemoveFetcherFromMap(int id) {
314 Fetchers::iterator i = fetchers_.find(id);
315 DCHECK(i != fetchers_.end());
316 fetchers_.erase(i);
317}
318
319void TestURLFetcherFactory::SetDelegateForTests(
320 TestURLFetcherDelegateForTests* delegate_for_tests) {
321 delegate_for_tests_ = delegate_for_tests;
322}
323
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000324FakeURLFetcher::FakeURLFetcher(const GURL& url,
325 URLFetcherDelegate* d,
326 const std::string& response_data,
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000327 HttpStatusCode response_code,
328 URLRequestStatus::Status status)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000329 : TestURLFetcher(0, url, d),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100330 weak_factory_(this) {
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000331 Error error = OK;
332 switch(status) {
333 case URLRequestStatus::SUCCESS:
334 // |error| is initialized to OK.
335 break;
336 case URLRequestStatus::IO_PENDING:
337 error = ERR_IO_PENDING;
338 break;
339 case URLRequestStatus::CANCELED:
340 error = ERR_ABORTED;
341 break;
342 case URLRequestStatus::FAILED:
343 error = ERR_FAILED;
344 break;
345 }
346 set_status(URLRequestStatus(status, error));
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000347 set_response_code(response_code);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000348 SetResponseString(response_data);
349}
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000350
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000351FakeURLFetcher::~FakeURLFetcher() {}
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000352
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000353void FakeURLFetcher::Start() {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100354 base::MessageLoop::current()->PostTask(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000355 FROM_HERE,
356 base::Bind(&FakeURLFetcher::RunDelegate, weak_factory_.GetWeakPtr()));
357}
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000358
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000359void FakeURLFetcher::RunDelegate() {
360 delegate()->OnURLFetchComplete(this);
361}
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000362
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000363const GURL& FakeURLFetcher::GetURL() const {
364 return TestURLFetcher::GetOriginalURL();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000365}
366
367FakeURLFetcherFactory::FakeURLFetcherFactory(
368 URLFetcherFactory* default_factory)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100369 : ScopedURLFetcherFactory(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000370 creator_(base::Bind(&DefaultFakeURLFetcherCreator)),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000371 default_factory_(default_factory) {
372}
373
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000374FakeURLFetcherFactory::FakeURLFetcherFactory(
375 URLFetcherFactory* default_factory,
376 const FakeURLFetcherCreator& creator)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100377 : ScopedURLFetcherFactory(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000378 creator_(creator),
379 default_factory_(default_factory) {
380}
381
382scoped_ptr<FakeURLFetcher> FakeURLFetcherFactory::DefaultFakeURLFetcherCreator(
383 const GURL& url,
384 URLFetcherDelegate* delegate,
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000385 const std::string& response_data,
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000386 HttpStatusCode response_code,
387 URLRequestStatus::Status status) {
388 return scoped_ptr<FakeURLFetcher>(
389 new FakeURLFetcher(url, delegate, response_data, response_code, status));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000390}
391
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000392FakeURLFetcherFactory::~FakeURLFetcherFactory() {}
393
394URLFetcher* FakeURLFetcherFactory::CreateURLFetcher(
395 int id,
396 const GURL& url,
397 URLFetcher::RequestType request_type,
398 URLFetcherDelegate* d) {
399 FakeResponseMap::const_iterator it = fake_responses_.find(url);
400 if (it == fake_responses_.end()) {
401 if (default_factory_ == NULL) {
402 // If we don't have a baked response for that URL we return NULL.
403 DLOG(ERROR) << "No baked response for URL: " << url.spec();
404 return NULL;
405 } else {
406 return default_factory_->CreateURLFetcher(id, url, request_type, d);
407 }
408 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000409
410 scoped_ptr<FakeURLFetcher> fake_fetcher =
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000411 creator_.Run(url, d, it->second.response_data,
412 it->second.response_code, it->second.status);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000413 // TODO: Make URLFetcherFactory::CreateURLFetcher return a scoped_ptr
414 return fake_fetcher.release();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000415}
416
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100417void FakeURLFetcherFactory::SetFakeResponse(
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100418 const GURL& url,
419 const std::string& response_data,
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000420 HttpStatusCode response_code,
421 URLRequestStatus::Status status) {
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100422 // Overwrite existing URL if it already exists.
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000423 FakeURLResponse response;
424 response.response_data = response_data;
425 response.response_code = response_code;
426 response.status = status;
427 fake_responses_[url] = response;
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100428}
429
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000430void FakeURLFetcherFactory::ClearFakeResponses() {
431 fake_responses_.clear();
432}
433
434URLFetcherImplFactory::URLFetcherImplFactory() {}
435
436URLFetcherImplFactory::~URLFetcherImplFactory() {}
437
438URLFetcher* URLFetcherImplFactory::CreateURLFetcher(
439 int id,
440 const GURL& url,
441 URLFetcher::RequestType request_type,
442 URLFetcherDelegate* d) {
443 return new URLFetcherImpl(url, request_type, d);
444}
445
446} // namespace net