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

#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "cobalt/loader/cors_preflight_cache.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 (SbStringCompareNoCase(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 obselete ones.
    if (entry_iter->second->expiration_time < base::Time::Now()) {
      url_iter->second.erase(entry_iter);
    }
  }
}

}  // namespace loader
}  // namespace cobalt
