// 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. #include "net/url_request/url_request_job_manager.h" #include #include "base/memory/singleton.h" #include "build/build_config.h" #include "base/strings/string_util.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/base/network_delegate.h" #include "net/net_features.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_error_job.h" #include "net/url_request/url_request_http_job.h" #include "net/url_request/url_request_job_factory.h" namespace net { // The built-in set of protocol factories namespace { struct SchemeToFactory { const char* scheme; URLRequest::ProtocolFactory* factory; }; } // namespace static const SchemeToFactory kBuiltinFactories[] = { {"http", URLRequestHttpJob::Factory}, {"https", URLRequestHttpJob::Factory}, #if BUILDFLAG(ENABLE_WEBSOCKETS) {"ws", URLRequestHttpJob::Factory}, {"wss", URLRequestHttpJob::Factory}, #endif // BUILDFLAG(ENABLE_WEBSOCKETS) }; // static URLRequestJobManager* URLRequestJobManager::GetInstance() { return base::Singleton::get(); } URLRequestJob* URLRequestJobManager::CreateJob( URLRequest* request, NetworkDelegate* network_delegate) const { DCHECK(IsAllowedThread()); // If we are given an invalid URL, then don't even try to inspect the scheme. if (!request->url().is_valid()) return new URLRequestErrorJob(request, network_delegate, ERR_INVALID_URL); // We do this here to avoid asking interceptors about unsupported schemes. const URLRequestJobFactory* job_factory = request->context()->job_factory(); const std::string& scheme = request->url().scheme(); // already lowercase if (!job_factory->IsHandledProtocol(scheme)) { return new URLRequestErrorJob( request, network_delegate, ERR_UNKNOWN_URL_SCHEME); } // THREAD-SAFETY NOTICE: // We do not need to acquire the lock here since we are only reading our // data structures. They should only be modified on the current thread. // See if the request should be intercepted. // URLRequestJob* job = job_factory->MaybeCreateJobWithProtocolHandler( scheme, request, network_delegate); if (job) return job; // See if the request should be handled by a built-in protocol factory. for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) { if (scheme == kBuiltinFactories[i].scheme) { URLRequestJob* new_job = (kBuiltinFactories[i].factory)(request, network_delegate, scheme); DCHECK(new_job); // The built-in factories are not expected to fail! return new_job; } } // If we reached here, then it means that a registered protocol factory // wasn't interested in handling the URL. That is fairly unexpected, and we // don't have a specific error to report here :-( LOG(WARNING) << "Failed to map: " << request->url().spec(); return new URLRequestErrorJob(request, network_delegate, ERR_FAILED); } URLRequestJob* URLRequestJobManager::MaybeInterceptRedirect( URLRequest* request, NetworkDelegate* network_delegate, const GURL& location) const { DCHECK(IsAllowedThread()); if (!request->url().is_valid() || request->status().status() == URLRequestStatus::CANCELED) { return NULL; } const URLRequestJobFactory* job_factory = NULL; job_factory = request->context()->job_factory(); const std::string& scheme = request->url().scheme(); // already lowercase if (!job_factory->IsHandledProtocol(scheme)) return NULL; URLRequestJob* job = request->context()->job_factory()->MaybeInterceptRedirect( request, network_delegate, location); if (job) return job; return NULL; } URLRequestJob* URLRequestJobManager::MaybeInterceptResponse( URLRequest* request, NetworkDelegate* network_delegate) const { DCHECK(IsAllowedThread()); if (!request->url().is_valid() || request->status().status() == URLRequestStatus::CANCELED) { return NULL; } const URLRequestJobFactory* job_factory = NULL; job_factory = request->context()->job_factory(); const std::string& scheme = request->url().scheme(); // already lowercase if (!job_factory->IsHandledProtocol(scheme)) return NULL; URLRequestJob* job = request->context()->job_factory()->MaybeInterceptResponse( request, network_delegate); if (job) return job; return NULL; } // static bool URLRequestJobManager::SupportsScheme(const std::string& scheme) { for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) { if (base::LowerCaseEqualsASCII(scheme, kBuiltinFactories[i].scheme)) return true; } return false; } URLRequestJobManager::URLRequestJobManager() { } URLRequestJobManager::~URLRequestJobManager() {} } // namespace net