// 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/websocket/web_socket.h"

#include <set>
#include <string>
#include <vector>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/window.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/web/context.h"
#include "cobalt/web/environment_settings.h"
#include "cobalt/websocket/close_event.h"
#include "net/base/port_util.h"
#include "net/base/url_util.h"
#include "net/websockets/websocket_errors.h"
#include "url/gurl.h"
#include "url/url_canon.h"
#include "url/url_constants.h"

namespace {

typedef uint16 SerializedCloseStatusCodeType;

static const char kComma[] = ",";

bool IsURLAbsolute(cobalt::web::EnvironmentSettings* settings,
                   const std::string& url) {
  // This is a requirement for calling spec()
  DCHECK(settings->base_url().is_valid());

  url::RawCanonOutputT<char> whitespace_buffer;
  int relative_length;
  bool potentially_dangling_markup;
  const char* relative = RemoveURLWhitespace(
      url.c_str(), static_cast<int>(url.size()), &whitespace_buffer,
      &relative_length, &potentially_dangling_markup);

  url::Component relative_component;

  const std::string& base_url(settings->base_url().spec());
  url::Parsed parsed;

  url::ParseStandardURL(base_url.c_str(), static_cast<int>(base_url.length()),
                        &parsed);

  bool is_relative;
  url::IsRelativeURL(base_url.c_str(), parsed, relative, relative_length, true,
                     &is_relative, &relative_component);

  return !is_relative;
}

bool IsValidSubprotocolCharacter(const char subprotocol_char) {
  // From RFC 2616 (https://tools.ietf.org/html/rfc2616),

  // CHAR: "any US-ASCII character (octets 0 - 127)"
  // CTL: "any US-ASCII control character (octets 0 - 31) and DEL (127)>"
  bool is_CHAR_except_CTL =
      ((subprotocol_char > 31) && (subprotocol_char < 127));
  bool is_separator = false;

  // Per spec, the separators are defined as following where (SP and HT are
  // space and horizontal tab, respectively):
  // separators    = "(" | ")" | "<" | ">" | "@"
  //               | "," | ";" | ":" | "\" | <">
  //               | "/" | "[" | "]" | "?" | "="
  //               | "{" | "}" | SP | HT

  switch (subprotocol_char) {
    case '(':
    case ')':
    case '<':
    case '>':
    case '@':
    case ',':
    case ';':
    case ':':
    case '\\':
    case '"':
    case '/':
    case '[':
    case ']':
    case '?':
    case '=':
    case '{':
    case '}':
    case ' ':
    case '\t':
      is_separator = true;
      break;
    default:
      break;
  }

  return (is_CHAR_except_CTL && !is_separator);
}

bool IsSubProtocolValid(const std::string& sub_protocol) {
  if (sub_protocol.empty()) {
    return false;
  }

  for (std::string::const_iterator it(sub_protocol.begin());
       it != sub_protocol.end(); ++it) {
    if (!IsValidSubprotocolCharacter(*it)) {
      return false;
    }
  }

  return true;
}

bool AreSubProtocolsValid(const std::vector<std::string>& sub_protocols,
                          std::string* invalid_subprotocol) {
  DCHECK(invalid_subprotocol);
  for (std::vector<std::string>::const_iterator it(sub_protocols.begin());
       it != sub_protocols.end(); ++it) {
    if (!IsSubProtocolValid(*it)) {
      *invalid_subprotocol = *it;
      return false;
    }
  }

  return true;
}

bool AreSubProtocolsUnique(const std::vector<std::string>& sub_protocols) {
  if (sub_protocols.size() <= 1) return true;

  std::set<std::string> all_protocols;
  all_protocols.insert(sub_protocols.begin(), sub_protocols.end());
  return (all_protocols.size() == sub_protocols.size());
}

bool IsValidBinaryType(cobalt::web::MessageEvent::ResponseType response_type) {
  return (response_type == cobalt::web::MessageEvent::kBlob) ||
         (response_type == cobalt::web::MessageEvent::kArrayBuffer);
}

}  // namespace

namespace cobalt {
namespace websocket {

const uint16 WebSocket::kConnecting;
const uint16 WebSocket::kOpen;
const uint16 WebSocket::kClosing;
const uint16 WebSocket::kClosed;

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket.
WebSocket::WebSocket(script::EnvironmentSettings* settings,
                     const std::string& url,
                     script::ExceptionState* exception_state)
    : web::EventTarget(settings), require_network_module_(true) {
  const std::vector<std::string> empty{};
  Initialize(settings, url, empty, exception_state);
}

WebSocket::WebSocket(script::EnvironmentSettings* settings,
                     const std::string& url,
                     const std::vector<std::string>& sub_protocols,
                     script::ExceptionState* exception_state)
    : web::EventTarget(settings), require_network_module_(true) {
  Initialize(settings, url, sub_protocols, exception_state);
}

WebSocket::~WebSocket() {
  if (impl_) {
    impl_->ResetWebSocketEventDelegate();
  }
}

std::string WebSocket::binary_type(script::ExceptionState* exception_state) {
  if (!IsValidBinaryType(binary_type_)) {
    NOTREACHED() << "Invalid binary_type_";
    web::DOMException::Raise(web::DOMException::kNone, exception_state);
    return std::string();
  }
  return web::MessageEvent::GetResponseTypeAsString(binary_type_);
}

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket.
WebSocket::WebSocket(script::EnvironmentSettings* settings,
                     const std::string& url,
                     const std::string& sub_protocol_list,
                     script::ExceptionState* exception_state)
    : web::EventTarget(settings), require_network_module_(true) {
  std::vector<std::string> sub_protocols =
      base::SplitString(sub_protocol_list, kComma, base::KEEP_WHITESPACE,
                        base::SPLIT_WANT_NONEMPTY);
  Initialize(settings, url, sub_protocols, exception_state);
}

void WebSocket::set_binary_type(const std::string& binary_type,
                                script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Per spec:
  // "On setting, if the new value is either the string "blob" or the string
  // "arraybuffer", then set the IDL attribute to this new value.
  // Otherwise, throw a SyntaxError exception."
  base::StringPiece binary_type_string_piece(binary_type);
  web::MessageEvent::ResponseType response_type =
      web::MessageEvent::GetResponseType(binary_type_string_piece);
  if (!IsValidBinaryType(response_type)) {
    web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state);
  } else {
    binary_type_ = response_type;
  }
}

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket-close.
void WebSocket::Close(script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  const std::string empty_reason;
  Close(net::kWebSocketNormalClosure, empty_reason, exception_state);
}

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket-close.
void WebSocket::Close(const uint16 code,
                      script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  const std::string empty_reason;
  Close(code, empty_reason, exception_state);
}

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket-close.
void WebSocket::Close(const uint16 code, const std::string& reason,
                      script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // Per spec @ https://www.w3.org/TR/websockets/#dom-websocket-close
  // "If reason is longer than 123 bytes, then throw a SyntaxError exception and
  // abort these steps."
  if (reason.size() > kMaxCloseReasonSize) {
    DLOG(ERROR) << "Reason specified in WebSocket::Close must be less than "
                << kMaxControlPayloadSizeInBytes << " bytes.";

    web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state);
    return;
  }

  if (net::WebSocketErrorToNetError(static_cast<net::WebSocketError>(code)) ==
      net::ERR_UNEXPECTED) {
    web::DOMException::Raise(web::DOMException::kInvalidAccessErr,
                             exception_state);
    return;
  }

  DLOG(INFO) << "Websocket close code " << code;

  switch (ready_state()) {
    case kOpen:
    case kConnecting:
      DCHECK(impl_);
      impl_->Close(net::WebSocketError(code), reason);
      SetReadyState(kClosing);
      break;
    case kClosing:
    case kClosed:
      return;
    default:
      NOTREACHED() << "Invalid ready_state_ " << ready_state()
                   << " in WebSocket::Close.";
  }
}

bool WebSocket::CheckReadyState(script::ExceptionState* exception_state) {
  DCHECK(exception_state);

  // Per Websockets API spec:
  // "If the readyState attribute is CONNECTING, it must throw an
  // InvalidStateError exception"
  if (ready_state() == kConnecting) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             "readyState is not in CONNECTING state",
                             exception_state);
    return false;
  }

  return true;
}

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket-send.
void WebSocket::Send(const std::string& data,
                     script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(impl_);
  if (!CheckReadyState(exception_state)) {
    return;
  }
  std::string error_message;
  bool success = impl_->SendText(data.data(), data.size(), &buffered_amount_,
                                 &error_message);
  if (!success) {
    DLOG(ERROR) << "Unable to send message: [" << error_message << "]";
  }
}

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket-send.
void WebSocket::Send(const scoped_refptr<web::Blob>& data,
                     script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(impl_);
  if (!CheckReadyState(exception_state)) {
    return;
  }
  web::Blob* blob(data.get());
  if (!blob) {
    return;
  }
  std::string error_message;
  bool success = impl_->SendBinary(reinterpret_cast<const char*>(blob->data()),
                                   static_cast<size_t>(blob->size()),
                                   &buffered_amount_, &error_message);
  if (!success) {
    DLOG(ERROR) << "Unable to send message: [" << error_message << "]";
  }
}

// Implements spec at https://www.w3.org/TR/websockets/#dom-websocket-send.
void WebSocket::Send(const script::Handle<script::ArrayBuffer>& data,
                     script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(impl_);
  if (!CheckReadyState(exception_state)) {
    return;
  }
  std::string error_message;
  if (data.IsEmpty()) {
    return;
  }
  bool success =
      impl_->SendBinary(reinterpret_cast<const char*>(data->Data()),
                        data->ByteLength(), &buffered_amount_, &error_message);
  if (!success) {
    DLOG(ERROR) << "Unable to send message: [" << error_message << "]";
  }
}

// Implements spect at https://www.w3.org/TR/websockets/#dom-websocket-send.
void WebSocket::Send(const script::Handle<script::ArrayBufferView>& data,
                     script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(impl_);
  if (!CheckReadyState(exception_state)) {
    return;
  }
  std::string error_message;
  if (data.IsEmpty()) {
    return;
  }
  bool success =
      impl_->SendBinary(reinterpret_cast<const char*>(data->RawData()),
                        data->ByteLength(), &buffered_amount_, &error_message);
  if (!success) {
    DLOG(ERROR) << "Unable to send message: [" << error_message << "]";
  }
}

std::string WebSocket::GetResourceName() const {
  if (resolved_url_.has_query()) {
    return resolved_url_.path() + "?" + resolved_url_.query();
  } else {
    return resolved_url_.path();
  }
}

std::string WebSocket::GetPortAsString() const {
  if (resolved_url_.has_port()) {
    return resolved_url_.port();
  }

  return base::IntToString(GetPort());
}

void WebSocket::OnConnected(const std::string& selected_subprotocol) {
  DLOG(INFO) << "Websockets selected subprotocol: [" << selected_subprotocol
             << "]";
  protocol_ = selected_subprotocol;
  SetReadyState(kOpen);
  this->DispatchEvent(new web::Event(base::Tokens::open()));
}

void WebSocket::OnDisconnected(bool was_clean, uint16 code,
                               const std::string& reason) {
  SetReadyState(kClosed);
  CloseEventInit close_event_init;
  close_event_init.set_was_clean(was_clean);
  close_event_init.set_code(code);
  close_event_init.set_reason(reason);
  this->DispatchEvent(new CloseEvent(base::Tokens::close(), close_event_init));
}

void WebSocket::OnReceivedData(bool is_text_frame,
                               scoped_refptr<net::IOBufferWithSize> data) {
  web::MessageEvent::ResponseType response_type = binary_type_;
  if (is_text_frame) {
    response_type = web::MessageEvent::kText;
  }
  this->DispatchEvent(
      new web::MessageEvent(base::Tokens::message(), response_type, data));
}

void WebSocket::OnWriteDone(uint64_t bytes_written) {
  buffered_amount_ -= bytes_written;
}

void WebSocket::Initialize(script::EnvironmentSettings* settings,
                           const std::string& url,
                           const std::vector<std::string>& sub_protocols,
                           script::ExceptionState* exception_state) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  buffered_amount_ = 0;
  binary_type_ = web::MessageEvent::kBlob;
  is_secure_ = false;
  port_ = -1;
  SetReadyState(kConnecting);

  settings_ = base::polymorphic_downcast<web::EnvironmentSettings*>(settings);
  if (!settings_) {
    web::DOMException::Raise(
        web::DOMException::kNone,
        "Internal error: Unable to get Web Environment Settings.",
        exception_state);
    NOTREACHED() << "Unable to get DOM settings.";
    return;
  }

  if (require_network_module_ && !settings_->context()->network_module()) {
    web::DOMException::Raise(web::DOMException::kNone,
                             "Internal error: Unable to get network module.",
                             exception_state);
    NOTREACHED() << "Unable to get network module.";
    return;
  }

  if (!settings_->base_url().is_valid()) {
    web::DOMException::Raise(
        web::DOMException::kNone,
        "Internal error: base_url (the url of the entry script) must be valid.",
        exception_state);
    return;
  } else {
    // GetOrigin() can only be called on valid urls.
    // Since origin does not contain fragments, spec() is guaranteed
    // to return an ASCII encoded string.
    entry_script_origin_ = settings_->base_url().GetOrigin().spec();
  }

  // Per spec:
  // Parse a WebSocket URL's components from the url argument, to obtain host,
  // port, resource name, and secure. If this fails, throw a SyntaxError
  // exception and abort these steps. [WSP]"

  resolved_url_ = settings_->base_url().Resolve(url);
  if (resolved_url_.is_empty()) {
    web::DOMException::Raise(web::DOMException::kSyntaxErr, "url is empty",
                             exception_state);
    return;
  }

  if (!resolved_url_.is_valid()) {
    web::DOMException::Raise(web::DOMException::kSyntaxErr, "url is invalid",
                             exception_state);
    return;
  }

  bool is_absolute = IsURLAbsolute(settings_, url);

  if (!is_absolute) {
    std::string error_message = "Only relative URLs are supported.  [" + url +
                                "] is not an absolute URL.";
    web::DOMException::Raise(web::DOMException::kSyntaxErr, error_message,
                             exception_state);
    return;
  }
  // Per spec @ https://www.w3.org/TR/websockets/#parsing-websocket-urls:
  // If url does not have a <scheme> component whose value, when converted to
  // ASCII lowercase, is either "ws" or "wss", then fail this algorithm.
  if (resolved_url_.SchemeIs(url::kWsScheme)) {
    is_secure_ = false;
  } else if (resolved_url_.SchemeIs(url::kWssScheme)) {
    is_secure_ = true;
  } else {
    std::string error_message = "Invalid scheme [" + resolved_url_.scheme() +
                                "].  Only " + std::string(url::kWsScheme) +
                                ", and " + std::string(url::kWssScheme) +
                                " schemes are supported.";
    web::DOMException::Raise(web::DOMException::kSyntaxErr, error_message,
                             exception_state);
    return;
  }

  // If url has a <fragment> component, then fail this algorithm.
  std::string fragment(resolved_url_.ref());
  if (!fragment.empty()) {
    std::string error_message =
        "URL has a fragment '" + fragment +
        "'.  Fragments are not are supported in websocket URLs.";
    web::DOMException::Raise(web::DOMException::kSyntaxErr, error_message,
                             exception_state);
    return;
  }

  web::CspDelegate* csp = csp_delegate();
  if (csp &&
      !csp->CanLoad(web::CspDelegate::kWebSocket, resolved_url_, false)) {
    web::DOMException::Raise(web::DOMException::kSecurityErr, exception_state);
    return;
  }

  if (!net::IsPortAllowedForScheme(GetPort(), resolved_url_.scheme())) {
    std::string error_message = "Connecting to port " + GetPortAsString() +
                                " using websockets is not allowed.";
    web::DOMException::Raise(web::DOMException::kSecurityErr, error_message,
                             exception_state);
    return;
  }

  std::string invalid_subprotocol;
  if (!AreSubProtocolsValid(sub_protocols, &invalid_subprotocol)) {
    std::string error_message = "Invalid subprotocol [" + invalid_subprotocol +
                                "].  Subprotocols' characters must be in valid "
                                "range and not have separating characters.  "
                                "See RFC 2616 for details.";
    web::DOMException::Raise(web::DOMException::kSyntaxErr, error_message,
                             exception_state);
    return;
  }

  if (!AreSubProtocolsUnique(sub_protocols)) {
    std::string error_message = "Subprotocol values must be unique.";
    web::DOMException::Raise(web::DOMException::kSyntaxErr, error_message,
                             exception_state);
    return;
  }

  Connect(resolved_url_, sub_protocols);
}

web::CspDelegate* WebSocket::csp_delegate() const {
  DCHECK(environment_settings());
  DCHECK(environment_settings()->context());
  DCHECK(environment_settings()->context()->GetWindowOrWorkerGlobalScope());
  return environment_settings()
      ->context()
      ->GetWindowOrWorkerGlobalScope()
      ->csp_delegate();
}

void WebSocket::Connect(const GURL& url,
                        const std::vector<std::string>& sub_protocols) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(settings_);

  GURL origin_gurl = settings_->base_url().GetOrigin();
  const std::string& origin = origin_gurl.possibly_invalid_spec();

  DCHECK(settings_->context());
  impl_ = base::WrapRefCounted(
      new WebSocketImpl(settings_->context()->network_module(), this));

  impl_->Connect(origin, url, sub_protocols);
}

WebSocket::WebSocket(script::EnvironmentSettings* settings,
                     const std::string& url,
                     script::ExceptionState* exception_state,
                     const bool require_network_module)
    : web::EventTarget(settings),
      require_network_module_(require_network_module) {
  const std::vector<std::string> empty{};
  Initialize(settings, url, empty, exception_state);
}

WebSocket::WebSocket(script::EnvironmentSettings* settings,
                     const std::string& url, const std::string& sub_protocol,
                     script::ExceptionState* exception_state,
                     const bool require_network_module)
    : web::EventTarget(settings),
      require_network_module_(require_network_module) {
  std::vector<std::string> sub_protocols;
  sub_protocols.push_back(sub_protocol);
  Initialize(settings, url, sub_protocols, exception_state);
}

WebSocket::WebSocket(script::EnvironmentSettings* settings,
                     const std::string& url,
                     const std::vector<std::string>& sub_protocols,
                     script::ExceptionState* exception_state,
                     const bool require_network_module)
    : web::EventTarget(settings),
      require_network_module_(require_network_module) {
  Initialize(settings, url, sub_protocols, exception_state);
}

void WebSocket::PotentiallyAllowGarbageCollection() {
  bool prevent_gc = false;
  switch (ready_state()) {
    case kOpen:
      //  Per spec, "A WebSocket object whose readyState attribute's value was
      //  set to OPEN (1) as of the last time the event loop started executing a
      //  task must not be garbage collected if there are any event listeners
      //  registered for message events, error, or close events..
      //  A WebSocket object with an established connection that has data queued
      //  to be transmitted to the network must not be garbage collected."
      prevent_gc = HasOnMessageListener() || HasOnErrorListener() ||
                   HasOnCloseListener() || HasOutstandingData();
      break;
    case kConnecting:
      //  Per spec, "WebSocket object whose readyState attribute's value was set
      //  to CONNECTING (0) as of the last time the event loop started executing
      //  a task must not be garbage collected if there are any event listeners
      //  registered for open events, message events, error events, or close
      //  events."
      prevent_gc = HasOnOpenListener() || HasOnMessageListener() ||
                   HasOnErrorListener() || HasOnCloseListener() ||
                   HasOutstandingData();
      break;
    case kClosing:
      //  Per spec, "A WebSocket object whose readyState attribute's value was
      //  set to CLOSING (2) as of the last time the event loop started
      //  executing a task must not be garbage collected if there are any event
      //  listeners registered for error or close events."
      prevent_gc =
          HasOnErrorListener() || HasOnCloseListener() || HasOutstandingData();
      break;
    case kClosed:
      prevent_gc = false;
      break;
    default:
      NOTREACHED() << "Invalid ready_state: " << ready_state();
  }

  if (prevent_gc != (prevent_gc_while_listening_ != NULL)) {
    if (prevent_gc) {
      prevent_gc_while_listening_.reset(
          new script::GlobalEnvironment::ScopedPreventGarbageCollection(
              settings_->context()->global_environment(), this));
    } else {
      // Note: the fall through in this switch statement is on purpose.
      switch (ready_state_) {
        case kConnecting:
          DCHECK(!HasOnOpenListener());
        case kOpen:
          DCHECK(!HasOnMessageListener());
        case kClosing:
          DCHECK(!HasOnErrorListener());
          DCHECK(!HasOnCloseListener());
        default:
          break;
      }

      prevent_gc_while_listening_.reset();
    }

    // The above function calls should change |(prevent_gc_while_listening_ !=
    // NULL)|.
    DCHECK_EQ(prevent_gc, (prevent_gc_while_listening_ != NULL));
  }
}

}  // namespace websocket
}  // namespace cobalt
