1 // 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.
5 #include "net/url_request/test_url_fetcher_factory.h"
10 #include "base/compiler_specific.h"
11 #include "base/files/file_util.h"
12 #include "base/location.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "net/base/host_port_pair.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/upload_data_stream.h"
21 #include "net/http/http_response_headers.h"
22 #include "net/url_request/url_fetcher_delegate.h"
23 #include "net/url_request/url_fetcher_impl.h"
24 #include "net/url_request/url_fetcher_response_writer.h"
25 #include "net/url_request/url_request_status.h"
29 ScopedURLFetcherFactory::ScopedURLFetcherFactory(
30 URLFetcherFactory
* factory
) {
31 DCHECK(!URLFetcherImpl::factory());
32 URLFetcherImpl::set_factory(factory
);
35 ScopedURLFetcherFactory::~ScopedURLFetcherFactory() {
36 DCHECK(URLFetcherImpl::factory());
37 URLFetcherImpl::set_factory(NULL
);
40 TestURLFetcher::TestURLFetcher(int id
, const GURL
& url
, URLFetcherDelegate
* d
)
45 delegate_for_tests_(NULL
),
46 did_receive_last_chunk_(false),
48 fake_response_code_(-1),
49 fake_response_destination_(STRING
),
50 fake_was_fetched_via_proxy_(false),
51 fake_was_cached_(false),
52 fake_response_bytes_(0),
53 fake_max_retries_(0) {
54 CHECK(original_url_
.is_valid());
57 TestURLFetcher::~TestURLFetcher() {
58 if (delegate_for_tests_
)
59 delegate_for_tests_
->OnRequestEnd(id_
);
61 owner_
->RemoveFetcherFromMap(id_
);
64 void TestURLFetcher::SetUploadData(const std::string
& upload_content_type
,
65 const std::string
& upload_content
) {
66 upload_content_type_
= upload_content_type
;
67 upload_data_
= upload_content
;
70 void TestURLFetcher::SetUploadFilePath(
71 const std::string
& upload_content_type
,
72 const base::FilePath
& file_path
,
75 scoped_refptr
<base::TaskRunner
> file_task_runner
) {
76 upload_file_path_
= file_path
;
79 void TestURLFetcher::SetUploadStreamFactory(
80 const std::string
& upload_content_type
,
81 const CreateUploadStreamCallback
& factory
) {
84 void TestURLFetcher::SetChunkedUpload(const std::string
& upload_content_type
) {
87 void TestURLFetcher::AppendChunkToUpload(const std::string
& data
,
89 DCHECK(!did_receive_last_chunk_
);
90 did_receive_last_chunk_
= is_last_chunk
;
91 chunks_
.push_back(data
);
92 if (delegate_for_tests_
)
93 delegate_for_tests_
->OnChunkUpload(id_
);
96 void TestURLFetcher::SetLoadFlags(int load_flags
) {
97 fake_load_flags_
= load_flags
;
100 int TestURLFetcher::GetLoadFlags() const {
101 return fake_load_flags_
;
104 void TestURLFetcher::SetReferrer(const std::string
& referrer
) {
107 void TestURLFetcher::SetReferrerPolicy(
108 URLRequest::ReferrerPolicy referrer_policy
) {
111 void TestURLFetcher::SetExtraRequestHeaders(
112 const std::string
& extra_request_headers
) {
113 fake_extra_request_headers_
.Clear();
114 fake_extra_request_headers_
.AddHeadersFromString(extra_request_headers
);
117 void TestURLFetcher::AddExtraRequestHeader(const std::string
& header_line
) {
118 fake_extra_request_headers_
.AddHeaderFromString(header_line
);
121 void TestURLFetcher::SetRequestContext(
122 URLRequestContextGetter
* request_context_getter
) {
125 void TestURLFetcher::SetFirstPartyForCookies(
126 const GURL
& first_party_for_cookies
) {
129 void TestURLFetcher::SetURLRequestUserData(
131 const CreateDataCallback
& create_data_callback
) {
134 void TestURLFetcher::SetStopOnRedirect(bool stop_on_redirect
) {
137 void TestURLFetcher::SetAutomaticallyRetryOn5xx(bool retry
) {
140 void TestURLFetcher::SetMaxRetriesOn5xx(int max_retries
) {
141 fake_max_retries_
= max_retries
;
144 int TestURLFetcher::GetMaxRetriesOn5xx() const {
145 return fake_max_retries_
;
148 base::TimeDelta
TestURLFetcher::GetBackoffDelay() const {
149 return fake_backoff_delay_
;
152 void TestURLFetcher::SetAutomaticallyRetryOnNetworkChanges(int max_retries
) {
155 void TestURLFetcher::SaveResponseToFileAtPath(
156 const base::FilePath
& file_path
,
157 scoped_refptr
<base::SequencedTaskRunner
> file_task_runner
) {
158 SetResponseFilePath(file_path
);
159 // Asynchronous IO is not supported, so file_task_runner is ignored.
160 base::ThreadRestrictions::ScopedAllowIO allow_io
;
161 const size_t written_bytes
= base::WriteFile(
162 file_path
, fake_response_string_
.c_str(), fake_response_string_
.size());
163 DCHECK_EQ(written_bytes
, fake_response_string_
.size());
166 void TestURLFetcher::SaveResponseToTemporaryFile(
167 scoped_refptr
<base::SequencedTaskRunner
> file_task_runner
) {
170 void TestURLFetcher::SaveResponseWithWriter(
171 scoped_ptr
<URLFetcherResponseWriter
> response_writer
) {
172 // In class URLFetcherCore this method is called by all three:
173 // GetResponseAsString() / SaveResponseToFileAtPath() /
174 // SaveResponseToTemporaryFile(). But here (in TestURLFetcher), this method
175 // is never used by any of these three methods. So, file writing is expected
176 // to be done in SaveResponseToFileAtPath(), and this method supports only
177 // URLFetcherStringWriter (for testing of this method only).
178 if (fake_response_destination_
== STRING
) {
179 response_writer_
= response_writer
.Pass();
180 int response
= response_writer_
->Initialize(CompletionCallback());
181 // The TestURLFetcher doesn't handle asynchronous writes.
182 DCHECK_EQ(OK
, response
);
184 scoped_refptr
<IOBuffer
> buffer(new StringIOBuffer(fake_response_string_
));
185 response
= response_writer_
->Write(buffer
.get(),
186 fake_response_string_
.size(),
187 CompletionCallback());
188 DCHECK_EQ(static_cast<int>(fake_response_string_
.size()), response
);
189 response
= response_writer_
->Finish(CompletionCallback());
190 DCHECK_EQ(OK
, response
);
191 } else if (fake_response_destination_
== TEMP_FILE
) {
192 // SaveResponseToFileAtPath() should be called instead of this method to
193 // save file. Asynchronous file writing using URLFetcherFileWriter is not
201 HttpResponseHeaders
* TestURLFetcher::GetResponseHeaders() const {
202 return fake_response_headers_
.get();
205 HostPortPair
TestURLFetcher::GetSocketAddress() const {
207 return HostPortPair();
210 bool TestURLFetcher::WasFetchedViaProxy() const {
211 return fake_was_fetched_via_proxy_
;
214 bool TestURLFetcher::WasCached() const {
215 return fake_was_cached_
;
218 int64_t TestURLFetcher::GetReceivedResponseContentLength() const {
219 return fake_response_bytes_
;
222 int64_t TestURLFetcher::GetTotalReceivedBytes() const {
223 return fake_was_cached_
? 0 : fake_response_bytes_
;
226 void TestURLFetcher::Start() {
227 // Overriden to do nothing. It is assumed the caller will notify the delegate.
228 if (delegate_for_tests_
)
229 delegate_for_tests_
->OnRequestStart(id_
);
232 const GURL
& TestURLFetcher::GetOriginalURL() const {
233 return original_url_
;
236 const GURL
& TestURLFetcher::GetURL() const {
240 const URLRequestStatus
& TestURLFetcher::GetStatus() const {
244 int TestURLFetcher::GetResponseCode() const {
245 return fake_response_code_
;
248 const ResponseCookies
& TestURLFetcher::GetCookies() const {
249 return fake_cookies_
;
252 void TestURLFetcher::ReceivedContentWasMalformed() {
255 bool TestURLFetcher::GetResponseAsString(
256 std::string
* out_response_string
) const {
257 if (fake_response_destination_
!= STRING
)
260 *out_response_string
= fake_response_string_
;
264 bool TestURLFetcher::GetResponseAsFilePath(
265 bool take_ownership
, base::FilePath
* out_response_path
) const {
266 if (fake_response_destination_
!= TEMP_FILE
)
269 *out_response_path
= fake_response_file_path_
;
273 void TestURLFetcher::GetExtraRequestHeaders(
274 HttpRequestHeaders
* headers
) const {
275 *headers
= fake_extra_request_headers_
;
278 void TestURLFetcher::set_status(const URLRequestStatus
& status
) {
279 fake_status_
= status
;
282 void TestURLFetcher::set_was_fetched_via_proxy(bool flag
) {
283 fake_was_fetched_via_proxy_
= flag
;
286 void TestURLFetcher::set_was_cached(bool flag
) {
287 fake_was_cached_
= flag
;
290 void TestURLFetcher::set_response_headers(
291 scoped_refptr
<HttpResponseHeaders
> headers
) {
292 fake_response_headers_
= headers
;
295 void TestURLFetcher::set_backoff_delay(base::TimeDelta backoff_delay
) {
296 fake_backoff_delay_
= backoff_delay
;
299 void TestURLFetcher::SetDelegateForTests(DelegateForTests
* delegate_for_tests
) {
300 delegate_for_tests_
= delegate_for_tests
;
303 void TestURLFetcher::SetResponseString(const std::string
& response
) {
304 fake_response_destination_
= STRING
;
305 fake_response_string_
= response
;
306 fake_response_bytes_
= response
.size();
309 void TestURLFetcher::SetResponseFilePath(const base::FilePath
& path
) {
310 fake_response_destination_
= TEMP_FILE
;
311 fake_response_file_path_
= path
;
314 TestURLFetcherFactory::TestURLFetcherFactory()
315 : ScopedURLFetcherFactory(this),
316 delegate_for_tests_(NULL
),
317 remove_fetcher_on_delete_(false) {
320 TestURLFetcherFactory::~TestURLFetcherFactory() {}
322 scoped_ptr
<URLFetcher
> TestURLFetcherFactory::CreateURLFetcher(
325 URLFetcher::RequestType request_type
,
326 URLFetcherDelegate
* d
) {
327 TestURLFetcher
* fetcher
= new TestURLFetcher(id
, url
, d
);
328 if (remove_fetcher_on_delete_
)
329 fetcher
->set_owner(this);
330 fetcher
->SetDelegateForTests(delegate_for_tests_
);
331 fetchers_
[id
] = fetcher
;
332 return scoped_ptr
<URLFetcher
>(fetcher
);
335 TestURLFetcher
* TestURLFetcherFactory::GetFetcherByID(int id
) const {
336 Fetchers::const_iterator i
= fetchers_
.find(id
);
337 return i
== fetchers_
.end() ? NULL
: i
->second
;
340 void TestURLFetcherFactory::RemoveFetcherFromMap(int id
) {
341 Fetchers::iterator i
= fetchers_
.find(id
);
342 DCHECK(i
!= fetchers_
.end());
346 void TestURLFetcherFactory::SetDelegateForTests(
347 TestURLFetcherDelegateForTests
* delegate_for_tests
) {
348 delegate_for_tests_
= delegate_for_tests
;
351 FakeURLFetcher::FakeURLFetcher(const GURL
& url
,
352 URLFetcherDelegate
* d
,
353 const std::string
& response_data
,
354 HttpStatusCode response_code
,
355 URLRequestStatus::Status status
)
356 : TestURLFetcher(0, url
, d
),
357 weak_factory_(this) {
360 case URLRequestStatus::SUCCESS
:
361 // |error| is initialized to OK.
363 case URLRequestStatus::IO_PENDING
:
364 error
= ERR_IO_PENDING
;
366 case URLRequestStatus::CANCELED
:
369 case URLRequestStatus::FAILED
:
373 set_status(URLRequestStatus(status
, error
));
374 set_response_code(response_code
);
375 SetResponseString(response_data
);
376 response_bytes_
= response_data
.size();
379 FakeURLFetcher::~FakeURLFetcher() {}
381 void FakeURLFetcher::Start() {
382 base::ThreadTaskRunnerHandle::Get()->PostTask(
384 base::Bind(&FakeURLFetcher::RunDelegate
, weak_factory_
.GetWeakPtr()));
387 void FakeURLFetcher::RunDelegate() {
388 // OnURLFetchDownloadProgress may delete this URLFetcher. We keep track of
389 // this with a weak pointer, and only call OnURLFetchComplete if this still
391 auto weak_this
= weak_factory_
.GetWeakPtr();
392 delegate()->OnURLFetchDownloadProgress(this, response_bytes_
,
395 delegate()->OnURLFetchComplete(this);
398 const GURL
& FakeURLFetcher::GetURL() const {
399 return TestURLFetcher::GetOriginalURL();
402 FakeURLFetcherFactory::FakeURLFetcherFactory(
403 URLFetcherFactory
* default_factory
)
404 : ScopedURLFetcherFactory(this),
405 creator_(base::Bind(&DefaultFakeURLFetcherCreator
)),
406 default_factory_(default_factory
) {
409 FakeURLFetcherFactory::FakeURLFetcherFactory(
410 URLFetcherFactory
* default_factory
,
411 const FakeURLFetcherCreator
& creator
)
412 : ScopedURLFetcherFactory(this),
414 default_factory_(default_factory
) {
417 scoped_ptr
<FakeURLFetcher
> FakeURLFetcherFactory::DefaultFakeURLFetcherCreator(
419 URLFetcherDelegate
* delegate
,
420 const std::string
& response_data
,
421 HttpStatusCode response_code
,
422 URLRequestStatus::Status status
) {
423 return scoped_ptr
<FakeURLFetcher
>(
424 new FakeURLFetcher(url
, delegate
, response_data
, response_code
, status
));
427 FakeURLFetcherFactory::~FakeURLFetcherFactory() {}
429 scoped_ptr
<URLFetcher
> FakeURLFetcherFactory::CreateURLFetcher(
432 URLFetcher::RequestType request_type
,
433 URLFetcherDelegate
* d
) {
434 FakeResponseMap::const_iterator it
= fake_responses_
.find(url
);
435 if (it
== fake_responses_
.end()) {
436 if (default_factory_
== NULL
) {
437 // If we don't have a baked response for that URL we return NULL.
438 DLOG(ERROR
) << "No baked response for URL: " << url
.spec();
441 return default_factory_
->CreateURLFetcher(id
, url
, request_type
, d
);
445 scoped_ptr
<URLFetcher
> fake_fetcher
=
446 creator_
.Run(url
, d
, it
->second
.response_data
, it
->second
.response_code
,
451 void FakeURLFetcherFactory::SetFakeResponse(
453 const std::string
& response_data
,
454 HttpStatusCode response_code
,
455 URLRequestStatus::Status status
) {
456 // Overwrite existing URL if it already exists.
457 FakeURLResponse response
;
458 response
.response_data
= response_data
;
459 response
.response_code
= response_code
;
460 response
.status
= status
;
461 fake_responses_
[url
] = response
;
464 void FakeURLFetcherFactory::ClearFakeResponses() {
465 fake_responses_
.clear();
468 URLFetcherImplFactory::URLFetcherImplFactory() {}
470 URLFetcherImplFactory::~URLFetcherImplFactory() {}
472 scoped_ptr
<URLFetcher
> URLFetcherImplFactory::CreateURLFetcher(
475 URLFetcher::RequestType request_type
,
476 URLFetcherDelegate
* d
) {
477 return scoped_ptr
<URLFetcher
>(new URLFetcherImpl(url
, request_type
, d
));