| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_ |
| #define NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_ |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "base/synchronization/lock.h" |
| #include "base/threading/platform_thread.h" |
| #include "net/url_request/url_request.h" |
| |
| template <typename T> struct DefaultSingletonTraits; |
| |
| namespace net { |
| |
| // This class is responsible for managing the set of protocol factories and |
| // request interceptors that determine how an URLRequestJob gets created to |
| // handle an URLRequest. |
| // |
| // MULTI-THREADING NOTICE: |
| // URLRequest is designed to have all consumers on a single thread, and |
| // so no attempt is made to support ProtocolFactory or Interceptor instances |
| // being registered/unregistered or in any way poked on multiple threads. |
| // However, we do support checking for supported schemes FROM ANY THREAD |
| // (i.e., it is safe to call SupportsScheme on any thread). |
| // |
| class URLRequestJobManager { |
| public: |
| // Returns the singleton instance. |
| static URLRequestJobManager* GetInstance(); |
| |
| // Instantiate an URLRequestJob implementation based on the registered |
| // interceptors and protocol factories. This will always succeed in |
| // returning a job unless we are--in the extreme case--out of memory. |
| URLRequestJob* CreateJob(URLRequest* request, |
| NetworkDelegate* network_delegate) const; |
| |
| // Allows interceptors to hijack the request after examining the new location |
| // of a redirect. Returns NULL if no interceptor intervenes. |
| URLRequestJob* MaybeInterceptRedirect(URLRequest* request, |
| NetworkDelegate* network_delegate, |
| const GURL& location) const; |
| |
| // Allows interceptors to hijack the request after examining the response |
| // status and headers. This is also called when there is no server response |
| // at all to allow interception of failed requests due to network errors. |
| // Returns NULL if no interceptor intervenes. |
| URLRequestJob* MaybeInterceptResponse( |
| URLRequest* request, NetworkDelegate* network_delegate) const; |
| |
| // Returns true if there is a protocol factory registered for the given |
| // scheme. Note: also returns true if there is a built-in handler for the |
| // given scheme. |
| bool SupportsScheme(const std::string& scheme) const; |
| |
| // Register a protocol factory associated with the given scheme. The factory |
| // parameter may be null to clear any existing association. Returns the |
| // previously registered protocol factory if any. |
| URLRequest::ProtocolFactory* RegisterProtocolFactory( |
| const std::string& scheme, URLRequest::ProtocolFactory* factory); |
| |
| // Register/unregister a request interceptor. |
| void RegisterRequestInterceptor(URLRequest::Interceptor* interceptor); |
| void UnregisterRequestInterceptor(URLRequest::Interceptor* interceptor); |
| |
| private: |
| typedef std::map<std::string, URLRequest::ProtocolFactory*> FactoryMap; |
| typedef std::vector<URLRequest::Interceptor*> InterceptorList; |
| friend struct DefaultSingletonTraits<URLRequestJobManager>; |
| |
| URLRequestJobManager(); |
| ~URLRequestJobManager(); |
| |
| // The first guy to call this function sets the allowed thread. This way we |
| // avoid needing to define that thread externally. Since we expect all |
| // callers to be on the same thread, we don't worry about threads racing to |
| // set the allowed thread. |
| bool IsAllowedThread() const { |
| #if 0 |
| if (!allowed_thread_initialized_) { |
| allowed_thread_ = base::PlatformThread::CurrentId(); |
| allowed_thread_initialized_ = true; |
| } |
| return allowed_thread_ == base::PlatformThread::CurrentId(); |
| #else |
| // The previous version of this check used GetCurrentThread on Windows to |
| // get thread handles to compare. Unfortunately, GetCurrentThread returns |
| // a constant pseudo-handle (0xFFFFFFFE), and therefore IsAllowedThread |
| // always returned true. The above code that's turned off is the correct |
| // code, but causes the tree to turn red because some caller isn't |
| // respecting our thread requirements. We're turning off the check for now; |
| // bug http://b/issue?id=1338969 has been filed to fix things and turn the |
| // check back on. |
| return true; |
| } |
| |
| // We use this to assert that CreateJob and the registration functions all |
| // run on the same thread. |
| mutable base::PlatformThreadId allowed_thread_; |
| mutable bool allowed_thread_initialized_; |
| #endif |
| |
| mutable base::Lock lock_; |
| FactoryMap factories_; |
| InterceptorList interceptors_; |
| |
| DISALLOW_COPY_AND_ASSIGN(URLRequestJobManager); |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_ |