// 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 <algorithm>

#include "base/memory/singleton.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/network_delegate.h"
#include "net/net_buildflags.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<URLRequestJobManager>::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() = default;

URLRequestJobManager::~URLRequestJobManager() = default;

}  // namespace net
