11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright (c) 2012 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/test_url_request_interceptor.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/threading/sequenced_worker_pool.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/threading/thread_restrictions.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request_file_job.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request_filter.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request_interceptor.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "testing/gtest/include/gtest/gtest.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace net { 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This class is needed because net::URLRequestFileJob always returns a -1 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// HTTP response status code. 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass TestURLRequestJob : public net::URLRequestFileJob { 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TestURLRequestJob(net::URLRequest* request, 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::NetworkDelegate* network_delegate, 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::FilePath& file_path, 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& worker_task_runner) 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : net::URLRequestFileJob(request, 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_delegate, 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_path, 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci worker_task_runner) {} 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual int GetResponseCode() const OVERRIDE { return 200; } 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~TestURLRequestJob() {} 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(TestURLRequestJob); 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This class handles the actual URL request interception. It may be constructed 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// on any thread, but all other methods are called on the |network_task_runner| 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// thread. It is destroyed by the net::URLRequestFilter singleton. 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass TestURLRequestInterceptor::Delegate : public net::URLRequestInterceptor { 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Delegate(const std::string& scheme, 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& hostname, 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& network_task_runner, 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& worker_task_runner) 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : scheme_(scheme), 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hostname_(hostname), 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner_(network_task_runner), 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci worker_task_runner_(worker_task_runner), 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hit_count_(0) {} 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~Delegate() {} 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void Register() { 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scheme_, hostname_, scoped_ptr<net::URLRequestInterceptor>(this)); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static void Unregister(const std::string& scheme, 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& hostname) { 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme, 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hostname); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // When requests for |url| arrive, respond with the contents of |path|. The 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // hostname and scheme of |url| must match the corresponding parameters 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // passed as constructor arguments. 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void SetResponse(const GURL& url, 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::FilePath& path, 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool ignore_query) { 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (ignore_query) { 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ignore_query_responses_[url] = path; 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci responses_[url] = path; 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns how many requests have been issued that have a stored reply. 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int GetHitCount() const { 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock auto_lock(hit_count_lock_); 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return hit_count_; 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci typedef std::map<GURL, base::FilePath> ResponseMap; 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // When computing matches, this ignores the query parameters of the url. 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual net::URLRequestJob* MaybeInterceptRequest( 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::URLRequest* request, 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::NetworkDelegate* network_delegate) const OVERRIDE { 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (request->url().scheme() != scheme_ || 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci request->url().host() != hostname_) { 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ResponseMap::const_iterator it = responses_.find(request->url()); 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (it == responses_.end()) { 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Search for this request's url, ignoring any query parameters. 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL url = request->url(); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (url.has_query()) { 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL::Replacements replacements; 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci replacements.ClearQuery(); 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url = url.ReplaceComponents(replacements); 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it = ignore_query_responses_.find(url); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (it == ignore_query_responses_.end()) 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock auto_lock(hit_count_lock_); 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++hit_count_; 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return new TestURLRequestJob( 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci request, network_delegate, it->second, worker_task_runner_); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string scheme_; 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string hostname_; 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner> network_task_runner_; 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner> worker_task_runner_; 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ResponseMap responses_; 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ResponseMap ignore_query_responses_; 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mutable base::Lock hit_count_lock_; 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mutable int hit_count_; 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(Delegate); 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTestURLRequestInterceptor::TestURLRequestInterceptor( 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& scheme, 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& hostname, 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& network_task_runner, 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& worker_task_runner) 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : scheme_(scheme), 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hostname_(hostname), 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner_(network_task_runner), 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delegate_(new Delegate(scheme, 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hostname, 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner_, 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci worker_task_runner)) { 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner_->PostTask( 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, base::Bind(&Delegate::Register, base::Unretained(delegate_))); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTestURLRequestInterceptor::~TestURLRequestInterceptor() { 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner_->PostTask( 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, base::Bind(&Delegate::Unregister, scheme_, hostname_)); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid TestURLRequestInterceptor::SetResponse(const GURL& url, 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::FilePath& path) { 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_EQ(scheme_, url.scheme()); 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_EQ(hostname_, url.host()); 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner_->PostTask(FROM_HERE, 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&Delegate::SetResponse, 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(delegate_), 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci path, 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci false)); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid TestURLRequestInterceptor::SetResponseIgnoreQuery( 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& url, 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::FilePath& path) { 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_EQ(scheme_, url.scheme()); 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_EQ(hostname_, url.host()); 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner_->PostTask(FROM_HERE, 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&Delegate::SetResponse, 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(delegate_), 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci path, 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true)); 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint TestURLRequestInterceptor::GetHitCount() { 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return delegate_->GetHitCount(); 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciLocalHostTestURLRequestInterceptor::LocalHostTestURLRequestInterceptor( 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& network_task_runner, 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& worker_task_runner) 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : TestURLRequestInterceptor("http", 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "localhost", 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci network_task_runner, 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci worker_task_runner) { 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace net 200