// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/html/link_style.h"

#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/loader/importance_attribute.h"
#include "third_party/blink/renderer/core/loader/link_load_parameters.h"
#include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h"
#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
#include "third_party/blink/renderer/platform/network/mime/content_type.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"

namespace blink {

static bool StyleSheetTypeIsSupported(const String& type) {
  String trimmed_type = ContentType(type).GetType();
  return trimmed_type.IsEmpty() ||
         MIMETypeRegistry::IsSupportedStyleSheetMIMEType(trimmed_type);
}

LinkStyle::LinkStyle(HTMLLinkElement* owner)
    : LinkResource(owner),
      disabled_state_(kUnset),
      pending_sheet_type_(kNone),
      render_blocking_behavior_(RenderBlockingBehavior::kUnset),
      loading_(false),
      fired_load_(false),
      loaded_sheet_(false) {}

LinkStyle::~LinkStyle() = default;

void LinkStyle::NotifyFinished(Resource* resource) {
  if (!owner_->isConnected()) {
    // While the stylesheet is asynchronously loading, the owner can be
    // disconnected from a document.
    // In that case, cancel any processing on the loaded content.
    loading_ = false;
    RemovePendingSheet();
    if (sheet_)
      ClearSheet();
    return;
  }

  auto* cached_style_sheet = To<CSSStyleSheetResource>(resource);
  // See the comment in pending_script.cc about why this check is necessary
  // here, instead of in the resource fetcher. https://crbug.com/500701.
  if ((!cached_style_sheet->ErrorOccurred() &&
       !owner_->FastGetAttribute(html_names::kIntegrityAttr).IsEmpty() &&
       !cached_style_sheet->IntegrityMetadata().IsEmpty()) ||
      resource->IsLinkPreload()) {
    ResourceIntegrityDisposition disposition =
        cached_style_sheet->IntegrityDisposition();

    SubresourceIntegrityHelper::DoReport(
        *GetExecutionContext(), cached_style_sheet->IntegrityReportInfo());

    if (disposition == ResourceIntegrityDisposition::kFailed) {
      loading_ = false;
      RemovePendingSheet();
      NotifyLoadedSheetAndAllCriticalSubresources(
          Node::kErrorOccurredLoadingSubresource);
      return;
    }
  }

  auto* parser_context = MakeGarbageCollected<CSSParserContext>(
      GetDocument(), cached_style_sheet->GetResponse().ResponseUrl(),
      cached_style_sheet->GetResponse().IsCorsSameOrigin(),
      Referrer(cached_style_sheet->GetResponse().ResponseUrl(),
               cached_style_sheet->GetReferrerPolicy()),
      cached_style_sheet->Encoding());
  if (cached_style_sheet->GetResourceRequest().IsAdResource()) {
    parser_context->SetIsAdRelated();
  }

  if (StyleSheetContents* parsed_sheet =
          cached_style_sheet->CreateParsedStyleSheetFromCache(parser_context)) {
    if (sheet_)
      ClearSheet();
    sheet_ = MakeGarbageCollected<CSSStyleSheet>(parsed_sheet, *owner_);
    sheet_->SetMediaQueries(
        MediaQuerySet::Create(owner_->Media(), GetExecutionContext()));
    if (owner_->IsInDocumentTree())
      SetSheetTitle(owner_->title());

    loading_ = false;
    parsed_sheet->CheckLoaded();
    parsed_sheet->SetRenderBlocking(render_blocking_behavior_);

    return;
  }

  auto* style_sheet = MakeGarbageCollected<StyleSheetContents>(
      parser_context, cached_style_sheet->Url());

  if (sheet_)
    ClearSheet();

  sheet_ = MakeGarbageCollected<CSSStyleSheet>(style_sheet, *owner_);
  sheet_->SetMediaQueries(
      MediaQuerySet::Create(owner_->Media(), GetExecutionContext()));
  if (owner_->IsInDocumentTree())
    SetSheetTitle(owner_->title());

  style_sheet->SetRenderBlocking(render_blocking_behavior_);
  style_sheet->ParseAuthorStyleSheet(cached_style_sheet);

  loading_ = false;
  style_sheet->NotifyLoadedSheet(cached_style_sheet);
  style_sheet->CheckLoaded();

  if (style_sheet->IsCacheableForResource()) {
    const_cast<CSSStyleSheetResource*>(cached_style_sheet)
        ->SaveParsedStyleSheet(style_sheet);
  }
  ClearResource();
}

bool LinkStyle::SheetLoaded() {
  if (!StyleSheetIsLoading()) {
    RemovePendingSheet();
    return true;
  }
  return false;
}

void LinkStyle::NotifyLoadedSheetAndAllCriticalSubresources(
    Node::LoadedSheetErrorStatus error_status) {
  if (fired_load_)
    return;
  loaded_sheet_ = (error_status == Node::kNoErrorLoadingSubresource);
  if (owner_)
    owner_->ScheduleEvent();
  fired_load_ = true;
}

void LinkStyle::StartLoadingDynamicSheet() {
  DCHECK_LT(pending_sheet_type_, kBlocking);
  AddPendingSheet(kBlocking);
}

void LinkStyle::ClearSheet() {
  DCHECK(sheet_);
  DCHECK_EQ(sheet_->ownerNode(), owner_);
  sheet_.Release()->ClearOwnerNode();
}

bool LinkStyle::StyleSheetIsLoading() const {
  if (loading_)
    return true;
  if (!sheet_)
    return false;
  return sheet_->Contents()->IsLoading();
}

void LinkStyle::AddPendingSheet(PendingSheetType type) {
  if (type <= pending_sheet_type_)
    return;
  pending_sheet_type_ = type;

  if (pending_sheet_type_ == kNonBlocking)
    return;
  GetDocument().GetStyleEngine().AddPendingSheet(style_engine_context_);
}

void LinkStyle::RemovePendingSheet() {
  DCHECK(owner_);
  PendingSheetType type = pending_sheet_type_;
  pending_sheet_type_ = kNone;

  if (type == kNone)
    return;
  if (type == kNonBlocking) {
    // Tell StyleEngine to re-compute styleSheets of this owner_'s treescope.
    GetDocument().GetStyleEngine().ModifiedStyleSheetCandidateNode(*owner_);
    return;
  }

  GetDocument().GetStyleEngine().RemovePendingSheet(*owner_,
                                                    style_engine_context_);
}

void LinkStyle::SetDisabledState(bool disabled) {
  LinkStyle::DisabledState old_disabled_state = disabled_state_;
  disabled_state_ = disabled ? kDisabled : kEnabledViaScript;
  // Whenever the disabled attribute is removed, set the link element's
  // explicitly enabled attribute to true.
  if (!disabled)
    explicitly_enabled_ = true;
  if (old_disabled_state == disabled_state_)
    return;

  // If we change the disabled state while the sheet is still loading, then we
  // have to perform three checks:
  if (StyleSheetIsLoading()) {
    // Check #1: The sheet becomes disabled while loading.
    if (disabled_state_ == kDisabled)
      RemovePendingSheet();

    // Check #2: An alternate sheet becomes enabled while it is still loading.
    if (owner_->RelAttribute().IsAlternate() &&
        disabled_state_ == kEnabledViaScript)
      AddPendingSheet(kBlocking);

    // Check #3: A main sheet becomes enabled while it was still loading and
    // after it was disabled via script. It takes really terrible code to make
    // this happen (a double toggle for no reason essentially). This happens
    // on virtualplastic.net, which manages to do about 12 enable/disables on
    // only 3 sheets. :)
    if (!owner_->RelAttribute().IsAlternate() &&
        disabled_state_ == kEnabledViaScript && old_disabled_state == kDisabled)
      AddPendingSheet(kBlocking);

    // If the sheet is already loading just bail.
    return;
  }

  if (sheet_) {
    // TODO(crbug.com/1087043): Remove this if() condition once the feature has
    // landed and no compat issues are reported.
    if (RuntimeEnabledFeatures::LinkDisabledNewSpecBehaviorEnabled(
            GetExecutionContext())) {
      DCHECK(disabled)
          << "If link is being enabled, sheet_ shouldn't exist yet";
      ClearSheet();
      GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate(
          owner_->GetTreeScope());
      return;
    } else {
      sheet_->setDisabled(disabled);
    }
  }

  if (disabled_state_ == kEnabledViaScript && owner_->ShouldProcessStyle())
    Process();
}

LinkStyle::LoadReturnValue LinkStyle::LoadStylesheetIfNeeded(
    const LinkLoadParameters& params,
    const WTF::TextEncoding& charset) {
  if (disabled_state_ == kDisabled || !owner_->RelAttribute().IsStyleSheet() ||
      !StyleSheetTypeIsSupported(params.type) || !ShouldLoadResource() ||
      !params.href.IsValid())
    return kNotNeeded;

  if (GetResource()) {
    RemovePendingSheet();
    ClearResource();
  }

  if (!owner_->ShouldLoadLink())
    return kBail;

  loading_ = true;

  String title = owner_->title();
  if (!title.IsEmpty() && !owner_->IsAlternate() &&
      disabled_state_ != kEnabledViaScript && owner_->IsInDocumentTree()) {
    GetDocument().GetStyleEngine().SetPreferredStylesheetSetNameIfNotSet(title);
  }

  bool media_query_matches = true;
  LocalFrame* frame = LoadingFrame();
  if (!owner_->Media().IsEmpty() && frame) {
    scoped_refptr<MediaQuerySet> media =
        MediaQuerySet::Create(owner_->Media(), GetExecutionContext());
    MediaQueryEvaluator evaluator(frame);
    media_query_matches = evaluator.Eval(*media);
  }

  bool is_in_body = owner_->IsDescendantOf(owner_->GetDocument().body());

  // Don't hold up layout tree construction and script execution on
  // stylesheets that are not needed for the layout at the moment.
  bool critical_style = media_query_matches && !owner_->IsAlternate();
  bool render_blocking = critical_style && owner_->IsCreatedByParser();

  AddPendingSheet(render_blocking ? kBlocking : kNonBlocking);

  // Load stylesheets that are not needed for the layout immediately with low
  // priority.  When the link element is created by scripts, load the
  // stylesheets asynchronously but in high priority.
  FetchParameters::DeferOption defer_option =
      !critical_style ? FetchParameters::kLazyLoad : FetchParameters::kNoDefer;

  render_blocking_behavior_ =
      !critical_style
          ? RenderBlockingBehavior::kNonBlocking
          : (render_blocking
                 ? (is_in_body ? RenderBlockingBehavior::kInBodyParserBlocking
                               : RenderBlockingBehavior::kBlocking)
                 : RenderBlockingBehavior::kNonBlockingDynamic);

  owner_->LoadStylesheet(params, charset, defer_option, this,
                         render_blocking_behavior_);

  if (loading_ && !GetResource()) {
    // Fetch() synchronous failure case.
    // The request may have been denied if (for example) the stylesheet is
    // local and the document is remote, or if there was a Content Security
    // Policy Failure.
    loading_ = false;
    RemovePendingSheet();
    NotifyLoadedSheetAndAllCriticalSubresources(
        Node::kErrorOccurredLoadingSubresource);
  }
  return kLoaded;
}

void LinkStyle::Process() {
  DCHECK(owner_->ShouldProcessStyle());
  const LinkLoadParameters params(
      owner_->RelAttribute(),
      GetCrossOriginAttributeValue(
          owner_->FastGetAttribute(html_names::kCrossoriginAttr)),
      owner_->TypeValue().DeprecatedLower(),
      owner_->AsValue().DeprecatedLower(), owner_->Media().DeprecatedLower(),
      owner_->nonce(), owner_->IntegrityValue(),
      owner_->ImportanceValue().LowerASCII(), owner_->GetReferrerPolicy(),
      owner_->GetNonEmptyURLAttribute(html_names::kHrefAttr),
      owner_->FastGetAttribute(html_names::kImagesrcsetAttr),
      owner_->FastGetAttribute(html_names::kImagesizesAttr));

  WTF::TextEncoding charset = GetCharset();

  if (owner_->RelAttribute().GetIconType() !=
          mojom::blink::FaviconIconType::kInvalid &&
      params.href.IsValid() && !params.href.IsEmpty()) {
    if (!owner_->ShouldLoadLink())
      return;
    if (!GetExecutionContext())
      return;
    if (!GetExecutionContext()->GetSecurityOrigin()->CanDisplay(params.href))
      return;
    if (!GetExecutionContext()
             ->GetContentSecurityPolicy()
             ->AllowImageFromSource(params.href, params.href,
                                    RedirectStatus::kNoRedirect)) {
      return;
    }
    if (GetDocument().GetFrame())
      GetDocument().GetFrame()->UpdateFaviconURL();
  }

  if (!sheet_ && !owner_->LoadLink(params))
    return;

  if (LoadStylesheetIfNeeded(params, charset) == kNotNeeded && sheet_) {
    // we no longer contain a stylesheet, e.g. perhaps rel or type was changed
    ClearSheet();
    GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate(
        owner_->GetTreeScope());
  }
}

void LinkStyle::SetSheetTitle(const String& title) {
  if (!owner_->IsInDocumentTree() || !owner_->RelAttribute().IsStyleSheet())
    return;

  if (sheet_)
    sheet_->SetTitle(title);

  if (title.IsEmpty() || !IsUnset() || owner_->IsAlternate())
    return;

  const KURL& href = owner_->GetNonEmptyURLAttribute(html_names::kHrefAttr);
  if (href.IsValid() && !href.IsEmpty())
    GetDocument().GetStyleEngine().SetPreferredStylesheetSetNameIfNotSet(title);
}

void LinkStyle::OwnerRemoved() {
  if (StyleSheetIsLoading())
    RemovePendingSheet();

  if (sheet_)
    ClearSheet();
}

void LinkStyle::Trace(Visitor* visitor) const {
  visitor->Trace(sheet_);
  LinkResource::Trace(visitor);
  ResourceClient::Trace(visitor);
}

}  // namespace blink
