test_url_fetcher_factory.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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.
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"
11#include "base/file_util.h"
12#include "base/memory/weak_ptr.h"
13#include "base/message_loop/message_loop.h"
14#include "base/threading/thread_restrictions.h"
15#include "net/base/host_port_pair.h"
16#include "net/base/io_buffer.h"
17#include "net/base/net_errors.h"
18#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"
21#include "net/url_request/url_fetcher_response_writer.h"
22#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)
40    : owner_(NULL),
41      id_(id),
42      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_);
56  if (owner_)
57    owner_->RemoveFetcherFromMap(id_);
58}
59
60void TestURLFetcher::SetUploadData(const std::string& upload_content_type,
61                                   const std::string& upload_content) {
62  upload_data_ = upload_content;
63}
64
65void TestURLFetcher::SetUploadFilePath(
66    const std::string& upload_content_type,
67    const base::FilePath& file_path,
68    uint64 range_offset,
69    uint64 range_length,
70    scoped_refptr<base::TaskRunner> file_task_runner) {
71  upload_file_path_ = file_path;
72}
73
74void 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
97void TestURLFetcher::SetReferrerPolicy(
98    URLRequest::ReferrerPolicy referrer_policy) {
99}
100
101void 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
111void 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
130void TestURLFetcher::SetMaxRetriesOn5xx(int max_retries) {
131  fake_max_retries_ = max_retries;
132}
133
134int TestURLFetcher::GetMaxRetriesOn5xx() const {
135  return fake_max_retries_;
136}
137
138base::TimeDelta TestURLFetcher::GetBackoffDelay() const {
139  return fake_backoff_delay_;
140}
141
142void TestURLFetcher::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
143}
144
145void TestURLFetcher::SaveResponseToFileAtPath(
146    const base::FilePath& file_path,
147    scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
148  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());
154}
155
156void TestURLFetcher::SaveResponseToTemporaryFile(
157    scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
158}
159
160void TestURLFetcher::SaveResponseWithWriter(
161    scoped_ptr<URLFetcherResponseWriter> response_writer) {
162  // 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).
168  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);
181  } 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.
185    NOTIMPLEMENTED();
186  } else {
187    NOTREACHED();
188  }
189}
190
191HttpResponseHeaders* TestURLFetcher::GetResponseHeaders() const {
192  return fake_response_headers_.get();
193}
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
230void 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(
243    bool take_ownership, base::FilePath* out_response_path) const {
244  if (fake_response_destination_ != TEMP_FILE)
245    return false;
246
247  *out_response_path = fake_response_file_path_;
248  return true;
249}
250
251void TestURLFetcher::GetExtraRequestHeaders(
252    HttpRequestHeaders* headers) const {
253  *headers = fake_extra_request_headers_;
254}
255
256void 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
282void TestURLFetcher::SetResponseFilePath(const base::FilePath& path) {
283  fake_response_destination_ = TEMP_FILE;
284  fake_response_file_path_ = path;
285}
286
287TestURLFetcherFactory::TestURLFetcherFactory()
288    : ScopedURLFetcherFactory(this),
289      delegate_for_tests_(NULL),
290      remove_fetcher_on_delete_(false) {
291}
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);
301  if (remove_fetcher_on_delete_)
302    fetcher->set_owner(this);
303  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
324FakeURLFetcher::FakeURLFetcher(const GURL& url,
325                               URLFetcherDelegate* d,
326                               const std::string& response_data,
327                               HttpStatusCode response_code,
328                               URLRequestStatus::Status status)
329    : TestURLFetcher(0, url, d),
330      weak_factory_(this) {
331  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));
347  set_response_code(response_code);
348  SetResponseString(response_data);
349}
350
351FakeURLFetcher::~FakeURLFetcher() {}
352
353void FakeURLFetcher::Start() {
354  base::MessageLoop::current()->PostTask(
355      FROM_HERE,
356      base::Bind(&FakeURLFetcher::RunDelegate, weak_factory_.GetWeakPtr()));
357}
358
359void FakeURLFetcher::RunDelegate() {
360  delegate()->OnURLFetchComplete(this);
361}
362
363const GURL& FakeURLFetcher::GetURL() const {
364  return TestURLFetcher::GetOriginalURL();
365}
366
367FakeURLFetcherFactory::FakeURLFetcherFactory(
368    URLFetcherFactory* default_factory)
369    : ScopedURLFetcherFactory(this),
370      creator_(base::Bind(&DefaultFakeURLFetcherCreator)),
371      default_factory_(default_factory) {
372}
373
374FakeURLFetcherFactory::FakeURLFetcherFactory(
375    URLFetcherFactory* default_factory,
376    const FakeURLFetcherCreator& creator)
377    : ScopedURLFetcherFactory(this),
378      creator_(creator),
379      default_factory_(default_factory) {
380}
381
382scoped_ptr<FakeURLFetcher> FakeURLFetcherFactory::DefaultFakeURLFetcherCreator(
383      const GURL& url,
384      URLFetcherDelegate* delegate,
385      const std::string& response_data,
386      HttpStatusCode response_code,
387      URLRequestStatus::Status status) {
388  return scoped_ptr<FakeURLFetcher>(
389      new FakeURLFetcher(url, delegate, response_data, response_code, status));
390}
391
392FakeURLFetcherFactory::~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  }
409
410  scoped_ptr<FakeURLFetcher> fake_fetcher =
411      creator_.Run(url, d, it->second.response_data,
412                   it->second.response_code, it->second.status);
413  // TODO: Make URLFetcherFactory::CreateURLFetcher return a scoped_ptr
414  return fake_fetcher.release();
415}
416
417void FakeURLFetcherFactory::SetFakeResponse(
418    const GURL& url,
419    const std::string& response_data,
420    HttpStatusCode response_code,
421    URLRequestStatus::Status status) {
422  // Overwrite existing URL if it already exists.
423  FakeURLResponse response;
424  response.response_data = response_data;
425  response.response_code = response_code;
426  response.status = status;
427  fake_responses_[url] = response;
428}
429
430void 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
447