/*
 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
 * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2002, 2005, 2006, 2008, 2009, 2010, 2012 Apple Inc. All rights
 * reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "third_party/blink/renderer/core/css/style_rule_import.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/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"

namespace blink {

StyleRuleImport::StyleRuleImport(const String& href,
                                 scoped_refptr<MediaQuerySet> media,
                                 OriginClean origin_clean)
    : StyleRuleBase(kImport),
      parent_style_sheet_(nullptr),
      style_sheet_client_(MakeGarbageCollected<ImportedStyleSheetClient>(this)),
      str_href_(href),
      media_queries_(media),
      loading_(false),
      origin_clean_(origin_clean) {
  if (!media_queries_)
    media_queries_ = MediaQuerySet::Create(String(), nullptr);
}

StyleRuleImport::~StyleRuleImport() = default;

void StyleRuleImport::Dispose() {
  style_sheet_client_->Dispose();
}

void StyleRuleImport::TraceAfterDispatch(blink::Visitor* visitor) const {
  visitor->Trace(style_sheet_client_);
  visitor->Trace(parent_style_sheet_);
  visitor->Trace(style_sheet_);
  StyleRuleBase::TraceAfterDispatch(visitor);
}

void StyleRuleImport::NotifyFinished(Resource* resource) {
  if (style_sheet_)
    style_sheet_->ClearOwnerRule();

  auto* cached_style_sheet = To<CSSStyleSheetResource>(resource);
  Document* document = nullptr;

  // Fallback to an insecure context parser if we don't have a parent style
  // sheet.
  const CSSParserContext* parent_context =
      StrictCSSParserContext(SecureContextMode::kInsecureContext);

  if (parent_style_sheet_) {
    document = parent_style_sheet_->SingleOwnerDocument();
    parent_context = parent_style_sheet_->ParserContext();
  }

  // If either parent or resource is marked as ad, the new CSS will be tagged
  // as an ad.
  CSSParserContext* context = MakeGarbageCollected<CSSParserContext>(
      parent_context, cached_style_sheet->GetResponse().ResponseUrl(),
      cached_style_sheet->GetResponse().IsCorsSameOrigin(),
      Referrer(cached_style_sheet->GetResponse().ResponseUrl(),
               cached_style_sheet->GetReferrerPolicy()),
      cached_style_sheet->Encoding(), document);
  if (cached_style_sheet->GetResourceRequest().IsAdResource())
    context->SetIsAdRelated();

  style_sheet_ = MakeGarbageCollected<StyleSheetContents>(
      context, cached_style_sheet->Url(), this);
  style_sheet_->ParseAuthorStyleSheet(cached_style_sheet);

  loading_ = false;

  if (parent_style_sheet_) {
    parent_style_sheet_->NotifyLoadedSheet(cached_style_sheet);
    parent_style_sheet_->CheckLoaded();
  }
}

bool StyleRuleImport::IsLoading() const {
  return loading_ || (style_sheet_ && style_sheet_->IsLoading());
}

void StyleRuleImport::RequestStyleSheet() {
  if (!parent_style_sheet_)
    return;
  Document* document = parent_style_sheet_->SingleOwnerDocument();
  if (!document)
    return;

  Document* document_for_origin = document;
  if (document->ImportsController()) {
    // For @imports from HTML imported Documents, we use the
    // context document for getting origin and ResourceFetcher to use the main
    // Document's origin, while using the element document for CompleteURL() to
    // use imported Documents' base URLs.
    document_for_origin =
        To<LocalDOMWindow>(document->GetExecutionContext())->document();
  }

  ResourceFetcher* fetcher = document_for_origin->Fetcher();
  if (!fetcher)
    return;

  KURL abs_url;
  if (!parent_style_sheet_->BaseURL().IsNull()) {
    // use parent styleheet's URL as the base URL
    abs_url = KURL(parent_style_sheet_->BaseURL(), str_href_);
  } else {
    abs_url = document->CompleteURL(str_href_);
  }

  // Check for a cycle in our import chain.  If we encounter a stylesheet
  // in our parent chain with the same URL, then just bail.
  StyleSheetContents* root_sheet = parent_style_sheet_;
  for (StyleSheetContents* sheet = parent_style_sheet_; sheet;
       sheet = sheet->ParentStyleSheet()) {
    if (EqualIgnoringFragmentIdentifier(abs_url, sheet->BaseURL()) ||
        EqualIgnoringFragmentIdentifier(
            abs_url, document->CompleteURL(sheet->OriginalURL())))
      return;
    root_sheet = sheet;
  }

  const CSSParserContext* parser_context = parent_style_sheet_->ParserContext();
  Referrer referrer = parser_context->GetReferrer();
  ResourceLoaderOptions options(parser_context->JavascriptWorld());
  options.initiator_info.name = fetch_initiator_type_names::kCSS;
  options.initiator_info.referrer = referrer.referrer;
  ResourceRequest resource_request(abs_url);
  resource_request.SetReferrerString(referrer.referrer);
  resource_request.SetReferrerPolicy(referrer.referrer_policy);
  if (parser_context->IsAdRelated())
    resource_request.SetIsAdResource();
  FetchParameters params(std::move(resource_request), options);
  params.SetCharset(parent_style_sheet_->Charset());
  params.SetFromOriginDirtyStyleSheet(origin_clean_ != OriginClean::kTrue);
  loading_ = true;
  DCHECK(!style_sheet_client_->GetResource());

  params.SetRenderBlockingBehavior(root_sheet->GetRenderBlockingBehavior());
  // TODO(yoav): Set defer status based on the IsRenderBlocking flag.
  // https://bugs.chromium.org/p/chromium/issues/detail?id=1001078
  CSSStyleSheetResource::Fetch(params, fetcher, style_sheet_client_);
  if (loading_) {
    // if the import rule is issued dynamically, the sheet may be
    // removed from the pending sheet count, so let the doc know
    // the sheet being imported is pending.
    if (parent_style_sheet_ && parent_style_sheet_->LoadCompleted() &&
        root_sheet == parent_style_sheet_) {
      parent_style_sheet_->StartLoadingDynamicSheet();
    }
  }
}

}  // namespace blink
