url_request_filter.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. #include "net/url_request/url_request_filter.h"
  5. #include "base/logging.h"
  6. #include "base/task/current_thread.h"
  7. #include "net/url_request/url_request.h"
  8. #include "net/url_request/url_request_job.h"
  9. #include "net/url_request/url_request_job_factory.h"
  10. namespace net {
  11. namespace {
  12. // When adding interceptors, DCHECK that this function returns true.
  13. bool OnMessageLoopForInterceptorAddition() {
  14. // Return true if called on a MessageLoopForIO or if there is no MessageLoop.
  15. // Checking for a MessageLoopForIO is a best effort at determining whether the
  16. // current thread is a networking thread. Allowing cases without a
  17. // MessageLoop is required for some tests where there is no chance to insert
  18. // an interceptor between a networking thread being started and a resource
  19. // request being issued.
  20. return base::CurrentIOThread::IsSet() || !base::CurrentThread::IsSet();
  21. }
  22. // When removing interceptors, DCHECK that this function returns true.
  23. bool OnMessageLoopForInterceptorRemoval() {
  24. // Checking for a CurrentIOThread is a best effort at determining
  25. // whether the current thread is a networking thread.
  26. return base::CurrentIOThread::IsSet();
  27. }
  28. } // namespace
  29. URLRequestFilter* URLRequestFilter::shared_instance_ = nullptr;
  30. // static
  31. URLRequestFilter* URLRequestFilter::GetInstance() {
  32. DCHECK(OnMessageLoopForInterceptorAddition());
  33. if (!shared_instance_)
  34. shared_instance_ = new URLRequestFilter;
  35. return shared_instance_;
  36. }
  37. void URLRequestFilter::AddHostnameInterceptor(
  38. const std::string& scheme,
  39. const std::string& hostname,
  40. std::unique_ptr<URLRequestInterceptor> interceptor) {
  41. DCHECK(OnMessageLoopForInterceptorAddition());
  42. DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname)));
  43. hostname_interceptor_map_[make_pair(scheme, hostname)] =
  44. std::move(interceptor);
  45. #ifndef NDEBUG
  46. // Check to see if we're masking URLs in the url_interceptor_map_.
  47. for (const auto& pair : url_interceptor_map_) {
  48. const GURL& url = GURL(pair.first);
  49. HostnameInterceptorMap::const_iterator host_it =
  50. hostname_interceptor_map_.find(make_pair(url.scheme(), url.host()));
  51. if (host_it != hostname_interceptor_map_.end())
  52. NOTREACHED();
  53. }
  54. #endif // !NDEBUG
  55. }
  56. void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
  57. const std::string& hostname) {
  58. DCHECK(OnMessageLoopForInterceptorRemoval());
  59. int removed = hostname_interceptor_map_.erase(make_pair(scheme, hostname));
  60. DCHECK(removed);
  61. }
  62. bool URLRequestFilter::AddUrlInterceptor(
  63. const GURL& url,
  64. std::unique_ptr<URLRequestInterceptor> interceptor) {
  65. DCHECK(OnMessageLoopForInterceptorAddition());
  66. if (!url.is_valid())
  67. return false;
  68. DCHECK_EQ(0u, url_interceptor_map_.count(url.spec()));
  69. url_interceptor_map_[url.spec()] = std::move(interceptor);
  70. // Check to see if this URL is masked by a hostname handler.
  71. DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(),
  72. url.host())));
  73. return true;
  74. }
  75. void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
  76. DCHECK(OnMessageLoopForInterceptorRemoval());
  77. size_t removed = url_interceptor_map_.erase(url.spec());
  78. DCHECK(removed);
  79. }
  80. void URLRequestFilter::ClearHandlers() {
  81. DCHECK(OnMessageLoopForInterceptorRemoval());
  82. url_interceptor_map_.clear();
  83. hostname_interceptor_map_.clear();
  84. hit_count_ = 0;
  85. }
  86. std::unique_ptr<URLRequestJob> URLRequestFilter::MaybeInterceptRequest(
  87. URLRequest* request) const {
  88. DCHECK(base::CurrentIOThread::Get());
  89. if (!request->url().is_valid())
  90. return nullptr;
  91. std::unique_ptr<URLRequestJob> job;
  92. // Check the hostname map first.
  93. const std::string hostname = request->url().host();
  94. const std::string scheme = request->url().scheme();
  95. {
  96. auto it = hostname_interceptor_map_.find(make_pair(scheme, hostname));
  97. if (it != hostname_interceptor_map_.end())
  98. job = it->second->MaybeInterceptRequest(request);
  99. }
  100. if (!job) {
  101. // Not in the hostname map, check the url map.
  102. const std::string& url = request->url().spec();
  103. auto it = url_interceptor_map_.find(url);
  104. if (it != url_interceptor_map_.end())
  105. job = it->second->MaybeInterceptRequest(request);
  106. }
  107. if (job) {
  108. DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
  109. hit_count_++;
  110. }
  111. return job;
  112. }
  113. URLRequestFilter::URLRequestFilter() {
  114. DCHECK(OnMessageLoopForInterceptorAddition());
  115. URLRequestJobFactory::SetInterceptorForTesting(this);
  116. }
  117. URLRequestFilter::~URLRequestFilter() {
  118. DCHECK(OnMessageLoopForInterceptorRemoval());
  119. URLRequestJobFactory::SetInterceptorForTesting(nullptr);
  120. }
  121. } // namespace net