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