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 24 namespace net { 25 26 ScopedURLFetcherFactory::ScopedURLFetcherFactory( 27 URLFetcherFactory* factory) { 28 DCHECK(!URLFetcherImpl::factory()); 29 URLFetcherImpl::set_factory(factory); 30 } 31 32 ScopedURLFetcherFactory::~ScopedURLFetcherFactory() { 33 DCHECK(URLFetcherImpl::factory()); 34 URLFetcherImpl::set_factory(NULL); 35 } 36 37 TestURLFetcher::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 53 TestURLFetcher::~TestURLFetcher() { 54 if (delegate_for_tests_) 55 delegate_for_tests_->OnRequestEnd(id_); 56 if (owner_) 57 owner_->RemoveFetcherFromMap(id_); 58 } 59 60 void TestURLFetcher::SetUploadData(const std::string& upload_content_type, 61 const std::string& upload_content) { 62 upload_data_ = upload_content; 63 } 64 65 void 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 74 void TestURLFetcher::SetChunkedUpload(const std::string& upload_content_type) { 75 } 76 77 void 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 86 void TestURLFetcher::SetLoadFlags(int load_flags) { 87 fake_load_flags_= load_flags; 88 } 89 90 int TestURLFetcher::GetLoadFlags() const { 91 return fake_load_flags_; 92 } 93 94 void TestURLFetcher::SetReferrer(const std::string& referrer) { 95 } 96 97 void TestURLFetcher::SetReferrerPolicy( 98 URLRequest::ReferrerPolicy referrer_policy) { 99 } 100 101 void 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 107 void TestURLFetcher::AddExtraRequestHeader(const std::string& header_line) { 108 fake_extra_request_headers_.AddHeaderFromString(header_line); 109 } 110 111 void TestURLFetcher::SetRequestContext( 112 URLRequestContextGetter* request_context_getter) { 113 } 114 115 void TestURLFetcher::SetFirstPartyForCookies( 116 const GURL& first_party_for_cookies) { 117 } 118 119 void TestURLFetcher::SetURLRequestUserData( 120 const void* key, 121 const CreateDataCallback& create_data_callback) { 122 } 123 124 void TestURLFetcher::SetStopOnRedirect(bool stop_on_redirect) { 125 } 126 127 void TestURLFetcher::SetAutomaticallyRetryOn5xx(bool retry) { 128 } 129 130 void TestURLFetcher::SetMaxRetriesOn5xx(int max_retries) { 131 fake_max_retries_ = max_retries; 132 } 133 134 int TestURLFetcher::GetMaxRetriesOn5xx() const { 135 return fake_max_retries_; 136 } 137 138 base::TimeDelta TestURLFetcher::GetBackoffDelay() const { 139 return fake_backoff_delay_; 140 } 141 142 void TestURLFetcher::SetAutomaticallyRetryOnNetworkChanges(int max_retries) { 143 } 144 145 void 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 156 void TestURLFetcher::SaveResponseToTemporaryFile( 157 scoped_refptr<base::SequencedTaskRunner> file_task_runner) { 158 } 159 160 void 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 191 HttpResponseHeaders* TestURLFetcher::GetResponseHeaders() const { 192 return fake_response_headers_.get(); 193 } 194 195 HostPortPair TestURLFetcher::GetSocketAddress() const { 196 NOTIMPLEMENTED(); 197 return HostPortPair(); 198 } 199 200 bool TestURLFetcher::WasFetchedViaProxy() const { 201 return fake_was_fetched_via_proxy_; 202 } 203 204 void 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 210 const GURL& TestURLFetcher::GetOriginalURL() const { 211 return original_url_; 212 } 213 214 const GURL& TestURLFetcher::GetURL() const { 215 return fake_url_; 216 } 217 218 const URLRequestStatus& TestURLFetcher::GetStatus() const { 219 return fake_status_; 220 } 221 222 int TestURLFetcher::GetResponseCode() const { 223 return fake_response_code_; 224 } 225 226 const ResponseCookies& TestURLFetcher::GetCookies() const { 227 return fake_cookies_; 228 } 229 230 void TestURLFetcher::ReceivedContentWasMalformed() { 231 } 232 233 bool 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 242 bool 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 251 void TestURLFetcher::GetExtraRequestHeaders( 252 HttpRequestHeaders* headers) const { 253 *headers = fake_extra_request_headers_; 254 } 255 256 void TestURLFetcher::set_status(const URLRequestStatus& status) { 257 fake_status_ = status; 258 } 259 260 void TestURLFetcher::set_was_fetched_via_proxy(bool flag) { 261 fake_was_fetched_via_proxy_ = flag; 262 } 263 264 void TestURLFetcher::set_response_headers( 265 scoped_refptr<HttpResponseHeaders> headers) { 266 fake_response_headers_ = headers; 267 } 268 269 void TestURLFetcher::set_backoff_delay(base::TimeDelta backoff_delay) { 270 fake_backoff_delay_ = backoff_delay; 271 } 272 273 void TestURLFetcher::SetDelegateForTests(DelegateForTests* delegate_for_tests) { 274 delegate_for_tests_ = delegate_for_tests; 275 } 276 277 void TestURLFetcher::SetResponseString(const std::string& response) { 278 fake_response_destination_ = STRING; 279 fake_response_string_ = response; 280 } 281 282 void TestURLFetcher::SetResponseFilePath(const base::FilePath& path) { 283 fake_response_destination_ = TEMP_FILE; 284 fake_response_file_path_ = path; 285 } 286 287 TestURLFetcherFactory::TestURLFetcherFactory() 288 : ScopedURLFetcherFactory(this), 289 delegate_for_tests_(NULL), 290 remove_fetcher_on_delete_(false) { 291 } 292 293 TestURLFetcherFactory::~TestURLFetcherFactory() {} 294 295 URLFetcher* 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 308 TestURLFetcher* TestURLFetcherFactory::GetFetcherByID(int id) const { 309 Fetchers::const_iterator i = fetchers_.find(id); 310 return i == fetchers_.end() ? NULL : i->second; 311 } 312 313 void TestURLFetcherFactory::RemoveFetcherFromMap(int id) { 314 Fetchers::iterator i = fetchers_.find(id); 315 DCHECK(i != fetchers_.end()); 316 fetchers_.erase(i); 317 } 318 319 void TestURLFetcherFactory::SetDelegateForTests( 320 TestURLFetcherDelegateForTests* delegate_for_tests) { 321 delegate_for_tests_ = delegate_for_tests; 322 } 323 324 FakeURLFetcher::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 351 FakeURLFetcher::~FakeURLFetcher() {} 352 353 void FakeURLFetcher::Start() { 354 base::MessageLoop::current()->PostTask( 355 FROM_HERE, 356 base::Bind(&FakeURLFetcher::RunDelegate, weak_factory_.GetWeakPtr())); 357 } 358 359 void FakeURLFetcher::RunDelegate() { 360 delegate()->OnURLFetchComplete(this); 361 } 362 363 const GURL& FakeURLFetcher::GetURL() const { 364 return TestURLFetcher::GetOriginalURL(); 365 } 366 367 FakeURLFetcherFactory::FakeURLFetcherFactory( 368 URLFetcherFactory* default_factory) 369 : ScopedURLFetcherFactory(this), 370 creator_(base::Bind(&DefaultFakeURLFetcherCreator)), 371 default_factory_(default_factory) { 372 } 373 374 FakeURLFetcherFactory::FakeURLFetcherFactory( 375 URLFetcherFactory* default_factory, 376 const FakeURLFetcherCreator& creator) 377 : ScopedURLFetcherFactory(this), 378 creator_(creator), 379 default_factory_(default_factory) { 380 } 381 382 scoped_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 392 FakeURLFetcherFactory::~FakeURLFetcherFactory() {} 393 394 URLFetcher* 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 417 void 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 430 void FakeURLFetcherFactory::ClearFakeResponses() { 431 fake_responses_.clear(); 432 } 433 434 URLFetcherImplFactory::URLFetcherImplFactory() {} 435 436 URLFetcherImplFactory::~URLFetcherImplFactory() {} 437 438 URLFetcher* 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