1// Copyright (c) 2011 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 "chrome/common/net/test_url_fetcher_factory.h"
6
7#include <string>
8
9#include "base/compiler_specific.h"
10#include "base/message_loop.h"
11#include "net/url_request/url_request_status.h"
12
13TestURLFetcher::TestURLFetcher(int id,
14                               const GURL& url,
15                               URLFetcher::RequestType request_type,
16                               URLFetcher::Delegate* d)
17    : URLFetcher(url, request_type, d),
18      id_(id),
19      original_url_(url),
20      did_receive_last_chunk_(false) {
21}
22
23TestURLFetcher::~TestURLFetcher() {
24}
25
26void TestURLFetcher::AppendChunkToUpload(const std::string& data,
27                                         bool is_last_chunk) {
28  DCHECK(!did_receive_last_chunk_);
29  did_receive_last_chunk_ = is_last_chunk;
30  chunks_.push_back(data);
31}
32
33TestURLFetcherFactory::TestURLFetcherFactory() {}
34
35TestURLFetcherFactory::~TestURLFetcherFactory() {}
36
37URLFetcher* TestURLFetcherFactory::CreateURLFetcher(
38    int id,
39    const GURL& url,
40    URLFetcher::RequestType request_type,
41    URLFetcher::Delegate* d) {
42  TestURLFetcher* fetcher = new TestURLFetcher(id, url, request_type, d);
43  fetchers_[id] = fetcher;
44  return fetcher;
45}
46
47TestURLFetcher* TestURLFetcherFactory::GetFetcherByID(int id) const {
48  Fetchers::const_iterator i = fetchers_.find(id);
49  return i == fetchers_.end() ? NULL : i->second;
50}
51
52void TestURLFetcherFactory::RemoveFetcherFromMap(int id) {
53  Fetchers::iterator i = fetchers_.find(id);
54  DCHECK(i != fetchers_.end());
55  fetchers_.erase(i);
56}
57
58// This class is used by the FakeURLFetcherFactory below.
59class FakeURLFetcher : public URLFetcher {
60 public:
61  // Normal URL fetcher constructor but also takes in a pre-baked response.
62  FakeURLFetcher(const GURL& url, RequestType request_type, Delegate* d,
63                 const std::string& response_data, bool success)
64    : URLFetcher(url, request_type, d),
65      url_(url),
66      response_data_(response_data),
67      success_(success),
68      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
69  }
70
71  // Start the request.  This will call the given delegate asynchronously
72  // with the pre-baked response as parameter.
73  virtual void Start() {
74    MessageLoop::current()->PostTask(
75        FROM_HERE,
76        method_factory_.NewRunnableMethod(&FakeURLFetcher::RunDelegate));
77  }
78
79 private:
80  virtual ~FakeURLFetcher() {
81  }
82
83  // This is the method which actually calls the delegate that is passed in the
84  // constructor.
85  void RunDelegate() {
86    net::URLRequestStatus status;
87    status.set_status(success_ ? net::URLRequestStatus::SUCCESS :
88                                 net::URLRequestStatus::FAILED);
89    delegate()->OnURLFetchComplete(this, url_, status, success_ ? 200 : 500,
90                                   ResponseCookies(), response_data_);
91  }
92
93  // Pre-baked response data and flag which indicates whether the request should
94  // be successful or not.
95  GURL url_;
96  std::string response_data_;
97  bool success_;
98
99  // Method factory used to run the delegate.
100  ScopedRunnableMethodFactory<FakeURLFetcher> method_factory_;
101
102  DISALLOW_COPY_AND_ASSIGN(FakeURLFetcher);
103};
104
105FakeURLFetcherFactory::FakeURLFetcherFactory() {}
106
107FakeURLFetcherFactory::~FakeURLFetcherFactory() {}
108
109URLFetcher* FakeURLFetcherFactory::CreateURLFetcher(
110    int id,
111    const GURL& url,
112    URLFetcher::RequestType request_type,
113    URLFetcher::Delegate* d) {
114  FakeResponseMap::const_iterator it = fake_responses_.find(url);
115  if (it == fake_responses_.end()) {
116    // If we don't have a baked response for that URL we return NULL.
117    DLOG(ERROR) << "No baked response for URL: " << url.spec();
118    return NULL;
119  }
120  return new FakeURLFetcher(url, request_type, d,
121                            it->second.first, it->second.second);
122}
123
124void FakeURLFetcherFactory::SetFakeResponse(const std::string& url,
125                                            const std::string& response_data,
126                                            bool success) {
127  // Overwrite existing URL if it already exists.
128  fake_responses_[GURL(url)] = std::make_pair(response_data, success);
129}
130
131void FakeURLFetcherFactory::ClearFakeReponses() {
132  fake_responses_.clear();
133}
134