1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#ifndef NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_ 621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#define NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <map> 104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <string> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h" 143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsentemplate <typename T> struct DefaultSingletonTraits; 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace net { 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class is responsible for managing the set of protocol factories and 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// request interceptors that determine how an URLRequestJob gets created to 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// handle an URLRequest. 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MULTI-THREADING NOTICE: 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// URLRequest is designed to have all consumers on a single thread, and 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// so no attempt is made to support ProtocolFactory or Interceptor instances 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// being registered/unregistered or in any way poked on multiple threads. 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// However, we do support checking for supported schemes FROM ANY THREAD 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// (i.e., it is safe to call SupportsScheme on any thread). 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass URLRequestJobManager { 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Returns the singleton instance. 3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static URLRequestJobManager* GetInstance(); 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Instantiate an URLRequestJob implementation based on the registered 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // interceptors and protocol factories. This will always succeed in 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // returning a job unless we are--in the extreme case--out of memory. 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen URLRequestJob* CreateJob(URLRequest* request) const; 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Allows interceptors to hijack the request after examining the new location 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // of a redirect. Returns NULL if no interceptor intervenes. 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen URLRequestJob* MaybeInterceptRedirect(URLRequest* request, 45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const GURL& location) const; 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Allows interceptors to hijack the request after examining the response 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // status and headers. This is also called when there is no server response 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // at all to allow interception of failed requests due to network errors. 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Returns NULL if no interceptor intervenes. 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen URLRequestJob* MaybeInterceptResponse(URLRequest* request) const; 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Returns true if there is a protocol factory registered for the given 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // scheme. Note: also returns true if there is a built-in handler for the 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // given scheme. 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool SupportsScheme(const std::string& scheme) const; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Register a protocol factory associated with the given scheme. The factory 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // parameter may be null to clear any existing association. Returns the 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // previously registered protocol factory if any. 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen URLRequest::ProtocolFactory* RegisterProtocolFactory( 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& scheme, URLRequest::ProtocolFactory* factory); 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Register/unregister a request interceptor. 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void RegisterRequestInterceptor(URLRequest::Interceptor* interceptor); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void UnregisterRequestInterceptor(URLRequest::Interceptor* interceptor); 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch void set_enable_file_access(bool enable) { enable_file_access_ = enable; } 694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool enable_file_access() const { return enable_file_access_; } 704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen typedef std::map<std::string, URLRequest::ProtocolFactory*> FactoryMap; 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen typedef std::vector<URLRequest::Interceptor*> InterceptorList; 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen friend struct DefaultSingletonTraits<URLRequestJobManager>; 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen URLRequestJobManager(); 7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ~URLRequestJobManager(); 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NDEBUG 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The first guy to call this function sets the allowed thread. This way we 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // avoid needing to define that thread externally. Since we expect all 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // callers to be on the same thread, we don't worry about threads racing to 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // set the allowed thread. 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool IsAllowedThread() const { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if 0 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!allowed_thread_initialized_) { 873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen allowed_thread_ = base::PlatformThread::CurrentId(); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott allowed_thread_initialized_ = true; 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return allowed_thread_ == base::PlatformThread::CurrentId(); 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The previous version of this check used GetCurrentThread on Windows to 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // get thread handles to compare. Unfortunately, GetCurrentThread returns 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a constant psuedo-handle (0xFFFFFFFE), and therefore IsAllowedThread 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // always returned true. The above code that's turned off is the correct 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // code, but causes the tree to turn red because some caller isn't 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // respecting our thread requirements. We're turning off the check for now; 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // bug http://b/issue?id=1338969 has been filed to fix things and turn the 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // check back on. 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We use this to assert that CreateJob and the registration functions all 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // run on the same thread. 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen mutable base::PlatformThreadId allowed_thread_; 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen mutable bool allowed_thread_initialized_; 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen mutable base::Lock lock_; 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FactoryMap factories_; 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen InterceptorList interceptors_; 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool enable_file_access_; 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(URLRequestJobManager); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace net 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif // NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_ 121