/*
 * Copyright 2017 The Cobalt Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cobalt/loader/cors_preflight_cache.h"

#include <algorithm>
#include <utility>

#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"

namespace {
bool MethodNameToRequestType(const std::string& method,
                             net::URLFetcher::RequestType* request_type) {
  if (base::LowerCaseEqualsASCII(method, "get")) {
    *request_type = net::URLFetcher::GET;
  } else if (base::LowerCaseEqualsASCII(method, "post")) {
    *request_type = net::URLFetcher::POST;
  } else if (base::LowerCaseEqualsASCII(method, "head")) {
    *request_type = net::URLFetcher::HEAD;
  } else if (base::LowerCaseEqualsASCII(method, "delete")) {
    *request_type = net::URLFetcher::DELETE_REQUEST;
  } else if (base::LowerCaseEqualsASCII(method, "put")) {
    *request_type = net::URLFetcher::PUT;
  } else {
    return false;
  }
  return true;
}
const char* kAuthorization = "authorization";
}  // namespace

namespace cobalt {
namespace loader {

void CORSPreflightCache::AppendEntry(
    const std::string& url_str, const std::string& origin, int max_age,
    bool has_credentials, const std::vector<std::string>& methods_vec,
    const std::vector<std::string>& headernames_vec) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (max_age <= 0) {
    return;
  }
  base::TimeDelta valid_duration = base::TimeDelta::FromSeconds(max_age);
  scoped_refptr<CORSPreflightCacheEntry> new_entry =
      new CORSPreflightCacheEntry();
  new_entry->credentials = has_credentials;
  new_entry->expiration_time = base::Time::Now() + valid_duration;

  if (methods_vec.size() == 1 && methods_vec.at(0) == "*") {
    new_entry->allow_all_methods = true;
  } else {
    for (const auto& method : methods_vec) {
      net::URLFetcher::RequestType request_type;
      if (MethodNameToRequestType(method, &request_type)) {
        new_entry->methods.insert(request_type);
      }
    }
  }

  if (headernames_vec.size() == 1 && headernames_vec.at(0) == "*") {
    new_entry->allow_all_headers_except_non_wildcard = true;
  }
  // TODO: Consider change this function to use std::copy with std::inserter.
  // Currently compilers on some machines do not support it.
  for (const auto& headername : headernames_vec) {
    new_entry->headernames.insert(headername);
  }

  auto insert_result =
      content_[url_str].insert(std::make_pair(origin, new_entry));
  if (!insert_result.second) {
    insert_result.first->second = new_entry;
  }

  expiration_time_heap_.push(
      ExpirationHeapEntry{new_entry->expiration_time, url_str, origin});
}

// https://fetch.spec.whatwg.org/#concept-cache-match
bool CORSPreflightCache::HaveEntry(
    const std::string& url_str, const std::string& origin,
    bool credentials_mode_is_include,
    const net::URLFetcher::RequestType& new_request_method,
    const std::vector<std::string>& unsafe_headernames) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (url_str.empty() || origin.empty()) {
    return false;
  }
  ClearObsoleteEntries();
  // There is a cache match for request if origin is request's origin,
  // url is request's current url, either credentials is true or request's
  // credentials_mode is not "include"
  auto url_iter = content_.find(url_str);
  if (url_iter == content_.end()) {
    return false;
  }
  auto origin_iter = url_iter->second.find(origin);
  if (origin_iter == url_iter->second.end()) {
    return false;
  }
  auto entry_ptr = origin_iter->second;
  if (!entry_ptr->credentials && credentials_mode_is_include) {
    return false;
  }
  // Either last preflight's Access-Control-Allow-Methods header has * or
  // new request's method, otherwise return false.
  if (!entry_ptr->allow_all_methods &&
      entry_ptr->methods.find(new_request_method) == entry_ptr->methods.end()) {
    return false;
  }
  // Header name is safe if it's not CORS non-wildcard request-header
  // name("Authentication") and last preflight allowed * headers.
  if (entry_ptr->allow_all_headers_except_non_wildcard) {
    bool has_auth_header = false;
    for (const auto& header : unsafe_headernames) {
      if (strcasecmp(header.c_str(), kAuthorization)) {
        has_auth_header = true;
        break;
      }
    }
    // wildcard header is allowed if entry's allowed headers include it.
    return !has_auth_header ||
           (entry_ptr->headernames.find(std::string(kAuthorization)) !=
            entry_ptr->headernames.end());
  }
  // If last preflight does not allow arbitrary header, then match each header
  // with allowed headers.
  for (const auto& unsafe_headername : unsafe_headernames) {
    if (entry_ptr->headernames.find(unsafe_headername) ==
        entry_ptr->headernames.end()) {
      return false;
    }
  }
  return true;
}

void CORSPreflightCache::ClearObsoleteEntries() {
  while (expiration_time_heap_.size() > 0 &&
         expiration_time_heap_.top().expiration_time < base::Time::Now()) {
    auto heap_top = expiration_time_heap_.top();
    expiration_time_heap_.pop();
    auto url_iter = content_.find(heap_top.url_str);
    if (url_iter == content_.end()) {
      continue;
    }
    auto entry_iter = url_iter->second.find(heap_top.origin);
    if (entry_iter == url_iter->second.end()) {
      continue;
    }
    // The entry could have been updated and should only delete obsolete ones.
    if (entry_iter->second->expiration_time < base::Time::Now()) {
      url_iter->second.erase(entry_iter);
    }
  }
}

}  // namespace loader
}  // namespace cobalt
