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