// Copyright 2014 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/dom/html_link_element.h"

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

#include "base/bind.h"
#include "base/strings/string_tokenizer.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/cssom/css_parser.h"
#include "cobalt/cssom/css_style_sheet.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/window.h"
#include "cobalt/web/csp_delegate.h"
#include "nb/memory_scope.h"
#include "url/gurl.h"

namespace cobalt {
namespace dom {
namespace {

bool IsValidRelChar(char const& c) {
  return (isalnum(c) || c == '_' || c == '\\' || c == '-');
}

bool IsValidSplashScreenFormat(const std::string& rel) {
  base::StringTokenizer tokenizer(rel, "_");
  tokenizer.set_options(base::StringTokenizer::RETURN_DELIMS);
  bool is_valid_format = true;
  while (tokenizer.GetNext()) {
    std::string token = tokenizer.token();
    if (strcmp(token.c_str(), "splashscreen") == 0) {
      is_valid_format = true;
    } else {
      for (char const& c : token) {
        if (!IsValidRelChar(c)) {
          return false;
        }
      }
      is_valid_format = false;
    }
  }
  return is_valid_format;
}

web::CspDelegate::ResourceType GetCspResourceTypeForRel(
    const std::string& rel) {
  if (rel == "stylesheet") {
    return web::CspDelegate::kStyle;
  } else if (IsValidSplashScreenFormat(rel)) {
    return web::CspDelegate::kLocation;
  } else {
    NOTIMPLEMENTED();
    return web::CspDelegate::kImage;
  }
}

bool IsRelContentCriticalResource(const std::string& rel) {
  return rel == "stylesheet";
}

loader::RequestMode GetRequestMode(
    const base::Optional<std::string>& cross_origin_attribute) {
  // https://html.spec.whatwg.org/#cors-settings-attribute
  if (cross_origin_attribute) {
    if (*cross_origin_attribute == "use-credentials") {
      return loader::kCORSModeIncludeCredentials;
    } else {
      // The invalid value default of crossorigin is Anonymous state, leading to
      // "same-origin" credentials mode.
      return loader::kCORSModeSameOriginCredentials;
    }
  }
  // crossorigin attribute's missing value default is No CORS state, leading to
  // "no-cors" request mode.
  return loader::kNoCORSMode;
}
}  // namespace

// static
const char HTMLLinkElement::kTagName[] = "link";
// static
const std::vector<std::string> HTMLLinkElement::kSupportedRelValues = {
    "stylesheet"};

void HTMLLinkElement::OnInsertedIntoDocument() {
  HTMLElement::OnInsertedIntoDocument();
  if (std::find(kSupportedRelValues.begin(), kSupportedRelValues.end(),
                rel()) != kSupportedRelValues.end()) {
    Obtain();
  } else if (IsValidSplashScreenFormat(rel())) {
    Obtain();
  } else {
    LOG(WARNING) << "<link> has unsupported rel value: " << rel() << ".";
  }
}

base::Optional<std::string> HTMLLinkElement::cross_origin() const {
  base::Optional<std::string> cross_origin_attribute =
      GetAttribute("crossOrigin");
  if (cross_origin_attribute &&
      (*cross_origin_attribute != "anonymous" &&
       *cross_origin_attribute != "use-credentials")) {
    return std::string();
  }
  return cross_origin_attribute;
}

void HTMLLinkElement::set_cross_origin(
    const base::Optional<std::string>& value) {
  if (value) {
    SetAttribute("crossOrigin", *value);
  } else {
    RemoveAttribute("crossOrigin");
  }
}

void HTMLLinkElement::OnRemovedFromDocument() {
  HTMLElement::OnRemovedFromDocument();

  DCHECK(base::MessageLoop::current());
  ReleaseLoader();

  if (style_sheet_) {
    Document* document = node_document();
    if (document) {
      document->OnStyleSheetsModified();
    }
  }
}

void HTMLLinkElement::ResolveAndSetAbsoluteURL() {
  // Resolve the URL given by the href attribute, relative to the element.
  const GURL& base_url = node_document()->location()->url();
  absolute_url_ = base_url.Resolve(href());

  LOG_IF(WARNING, !absolute_url_.is_valid())
      << href() << " cannot be resolved based on " << base_url << ".";
}

// Algorithm for Obtain:
//   https://www.w3.org/TR/html50/document-metadata.html#concept-link-obtain
void HTMLLinkElement::Obtain() {
  TRACK_MEMORY_SCOPE("DOM");
  TRACE_EVENT0("cobalt::dom", "HTMLLinkElement::Obtain()");
  // Custom, not in any spec.
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Document* document = node_document();

  // If the document has no browsing context, do not obtain, parse or apply the
  // resource.
  if (!document->html_element_context()) {
    return;
  }

  DCHECK(base::MessageLoop::current());
  DCHECK(!loader_);

  // 1. If the href attribute's value is the empty string, then abort these
  // steps.
  if (href().empty()) {
    return;
  }

  // 2. Resolve the URL given by the href attribute, relative to the element.
  ResolveAndSetAbsoluteURL();

  // 3. If the previous step fails, then abort these steps.
  if (!absolute_url_.is_valid()) {
    return;
  }

  // 4. Do a potentially CORS-enabled fetch of the resulting absolute URL, with
  // the mode being the current state of the element's crossorigin content
  // attribute, the origin being the origin of the link element's Document, and
  // the default origin behaviour set to taint.
  csp::SecurityCallback csp_callback = base::Bind(
      &web::CspDelegate::CanLoad, base::Unretained(document->csp_delegate()),
      GetCspResourceTypeForRel(rel()));

  fetched_last_url_origin_ = loader::Origin();

  if (IsRelContentCriticalResource(rel())) {
    // The element must delay the load event of the element's document until all
    // the attempts to obtain the resource and its critical subresources are
    // complete.
    document->IncreaseLoadingCounter();
  }

  request_mode_ = GetRequestMode(GetAttribute("crossOrigin"));

  DCHECK(!loader_);
  loader::Origin origin = document->location()
                              ? document->location()->GetOriginAsObject()
                              : loader::Origin();
  disk_cache::ResourceType type;
  if (rel() == "stylesheet") {
    type = disk_cache::kCSS;
  } else if (IsValidSplashScreenFormat(rel())) {
    type = disk_cache::kSplashScreen;
  } else {
    LOG(WARNING) << "<link> has unsupported rel value: " << rel() << ".";
    NOTIMPLEMENTED();
    return;
  }

  loader_ = html_element_context()->loader_factory()->CreateLinkLoader(
      absolute_url_, origin, csp_callback, request_mode_, type,
      base::Bind(&HTMLLinkElement::OnContentProduced, base::Unretained(this)),
      base::Bind(&HTMLLinkElement::OnLoadingComplete, base::Unretained(this)));
}

void HTMLLinkElement::OnContentProduced(const loader::Origin& last_url_origin,
                                        std::unique_ptr<std::string> content) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(content);
  TRACK_MEMORY_SCOPE("DOM");
  TRACE_EVENT0("cobalt::dom", "HTMLLinkElement::OnContentProduced()");

  // Get resource's final destination url from loader.
  fetched_last_url_origin_ = last_url_origin;

  Document* document = node_document();
  if (rel() == "stylesheet") {
    OnStylesheetLoaded(document, *content);
  } else if (IsValidSplashScreenFormat(rel())) {
    OnSplashscreenLoaded(document, *content);
  } else {
    NOTIMPLEMENTED();
    return;
  }
  // Once the attempts to obtain the resource and its critical subresources
  // are complete, the user agent must, if the loads were successful, queue a
  // task to fire a simple event named load at the link element, or, if the
  // resource or one of its critical subresources failed to completely load
  // for any reason (e.g. DNS error, HTTP 404 response, a connection being
  // prematurely closed, unsupported Content-Type), queue a task to fire a
  // simple event named error at the link element.
  PostToDispatchEventName(FROM_HERE, base::Tokens::load());

  if (IsRelContentCriticalResource(rel())) {
    // The element must delay the load event of the element's document until all
    // the attempts to obtain the resource and its critical subresources are
    // complete.
    document->DecreaseLoadingCounterAndMaybeDispatchLoadEvent();
  }
}

void HTMLLinkElement::OnLoadingComplete(
    const base::Optional<std::string>& error) {
  // GetLoadTimingInfo and create resource timing before loader released.
  GetLoadTimingInfoAndCreateResourceTiming();

  base::MessageLoop::current()->task_runner()->PostTask(
      FROM_HERE, base::Bind(&HTMLLinkElement::ReleaseLoader, this));

  if (!error) return;

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  TRACE_EVENT0("cobalt::dom", "HTMLLinkElement::OnLoadingComplete()");

  LOG(ERROR) << *error;

  // Once the attempts to obtain the resource and its critical subresources are
  // complete, the user agent must, if the loads were successful, queue a task
  // to fire a simple event named load at the link element, or, if the resource
  // or one of its critical subresources failed to completely load for any
  // reason (e.g. DNS error, HTTP 404 response, a connection being prematurely
  // closed, unsupported Content-Type), queue a task to fire a simple event
  // named error at the link element.
  PostToDispatchEventName(FROM_HERE, base::Tokens::error());

  if (IsRelContentCriticalResource(rel())) {
    // The element must delay the load event of the element's document until all
    // the attempts to obtain the resource and its critical subresources are
    // complete.
    node_document()->DecreaseLoadingCounterAndMaybeDispatchLoadEvent();
  }
}

void HTMLLinkElement::OnSplashscreenLoaded(Document* document,
                                           const std::string& content) {
  scoped_refptr<Window> window = document->window();
  std::string link = rel();
  size_t last_underscore = link.find_last_of("_");
  base::Optional<std::string> topic;
  if (last_underscore != std::string::npos) {
    topic = link.substr(0, last_underscore);
  }
  window->CacheSplashScreen(content, topic);
}

void HTMLLinkElement::OnStylesheetLoaded(Document* document,
                                         const std::string& content) {
  scoped_refptr<cssom::CSSStyleSheet> css_style_sheet =
      document->html_element_context()->css_parser()->ParseStyleSheet(
          content, base::SourceLocation(href(), 1, 1));
  css_style_sheet->SetLocationUrl(absolute_url_);
  // If not loading from network-fetched resources or fetched resource is same
  // origin as the document, set origin-clean flag to true.
  if (request_mode_ != loader::kNoCORSMode || !loader_ ||
      document->location()->url().SchemeIsFile() ||
      (fetched_last_url_origin_ == document->location()->GetOriginAsObject())) {
    css_style_sheet->SetOriginClean(true);
  }
  style_sheet_ = css_style_sheet;
  document->OnStyleSheetsModified();
}

void HTMLLinkElement::ReleaseLoader() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  loader_.reset();
}

void HTMLLinkElement::CollectStyleSheet(
    cssom::StyleSheetVector* style_sheets) const {
  if (style_sheet_) {
    style_sheets->push_back(style_sheet_);
  }
}

void HTMLLinkElement::GetLoadTimingInfoAndCreateResourceTiming() {
  if (html_element_context()->performance() == nullptr) return;
  if (loader_) {
    html_element_context()->performance()->CreatePerformanceResourceTiming(
        loader_->get_load_timing_info(), kTagName, absolute_url_.spec());
  }
}

}  // namespace dom
}  // namespace cobalt
