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

#ifndef COBALT_LOADER_CORS_PREFLIGHT_H_
#define COBALT_LOADER_CORS_PREFLIGHT_H_

#include <memory>
#include <string>
#include <vector>

#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_checker.h"
#include "cobalt/loader/cors_preflight_cache.h"
#include "cobalt/network/network_delegate.h"
#include "cobalt/network/network_module.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "url/gurl.h"

namespace cobalt {
namespace loader {

// This class provide implementation for sending cors-preflight request and
// all cors-related checks. All input origin strings should be serialized
// origins.
class CORSPreflight : public net::URLFetcherDelegate {
 public:
  CORSPreflight(GURL url, net::URLFetcher::RequestType method,
                const network::NetworkModule* network_module,
                base::Closure success_callback, std::string origin,
                base::Closure error_callback,
                scoped_refptr<CORSPreflightCache> preflight_cache);
  void OnURLFetchComplete(const net::URLFetcher* source) override;
  void set_force_preflight(bool forcepreflight) {
    force_preflight_ = forcepreflight;
  }
  void set_credentials_mode_is_include(bool credentialsmodeisinclude) {
    credentials_mode_is_include_ = credentialsmodeisinclude;
  }
  void set_headers(const net::HttpRequestHeaders& headers) {
    headers_ = headers;
  }
  void set_cors_policy(const network::CORSPolicy cors_policy) {
    cors_policy_ = cors_policy;
  }
  // Determine if CORS Preflight is needed by a cross origin request
  bool IsPreflightNeeded();
  // The send method can be called after initializing this class.
  // If a preflight is needed, send will send that preflight and return
  // true; if not send will just return false.
  bool Send();
  // CORS Check is done on response to ensure simple CORS request is
  // allowed by the server.
  static bool CORSCheck(
      const net::HttpResponseHeaders& response_headers,
      const std::string& serialized_origin, bool credentials_mode_is_include,
      network::CORSPolicy cors_policy = network::kCORSRequired);
  // Checks if a header(a name-value pair) is a CORS-Safelisted request-header.
  static bool IsSafeRequestHeader(const std::string& name,
                                  const std::string& value);
  // Returns true if name is a CORS-Safelisted response-header.
  // Call GetHeadersVector before to put server-allowed headers in vector.
  static bool IsSafeResponseHeader(
      const std::string& name,
      const std::vector<std::string>& CORS_exposed_header_name_list,
      bool credentials_mode_is_include);
  // This function populates input vector with headers extracted from
  // Access-Control-Expose-Headers header.
  static void GetServerAllowedHeaders(
      const net::HttpResponseHeaders& response_headers,
      std::vector<std::string>* expose_headers);

 private:
  void Start();

  bool credentials_mode_is_include_;
  bool force_preflight_;
  network::CORSPolicy cors_policy_ = network::kCORSRequired;
  GURL url_;
  net::URLFetcher::RequestType method_;
  const network::NetworkModule* network_module_;
  std::unique_ptr<net::URLFetcher> url_fetcher_;
  THREAD_CHECKER(thread_checker_);
  net::HttpRequestHeaders headers_;
  std::string origin_;
  base::Closure error_callback_;
  base::Closure success_callback_;
  scoped_refptr<CORSPreflightCache> preflight_cache_;
};

}  // namespace loader
}  // namespace cobalt

#endif  // COBALT_LOADER_CORS_PREFLIGHT_H_
