/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "core/loader/LinkLoader.h"

#include "bindings/core/v8/V8BindingForCore.h"
#include "core/css/MediaList.h"
#include "core/css/MediaQueryEvaluator.h"
#include "core/dom/Document.h"
#include "core/dom/ModuleScript.h"
#include "core/dom/ScriptLoader.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/html/CrossOriginAttribute.h"
#include "core/html/LinkRelAttribute.h"
#include "core/html/parser/HTMLPreloadScanner.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/NetworkHintsInterface.h"
#include "core/loader/modulescript/ModuleScriptFetchRequest.h"
#include "core/loader/private/PrerenderHandle.h"
#include "core/loader/resource/LinkFetchResource.h"
#include "platform/Prerender.h"
#include "platform/loader/LinkHeader.h"
#include "platform/loader/fetch/FetchParameters.h"
#include "platform/loader/fetch/ResourceClient.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/loader/fetch/ResourceFinishObserver.h"
#include "platform/loader/fetch/ResourceLoaderOptions.h"
#include "platform/loader/fetch/fetch_initiator_type_names.h"
#include "platform/network/mime/MIMETypeRegistry.h"
#include "public/platform/WebPrerender.h"

namespace blink {

static unsigned PrerenderRelTypesFromRelAttribute(
    const LinkRelAttribute& rel_attribute,
    Document& document) {
  unsigned result = 0;
  if (rel_attribute.IsLinkPrerender()) {
    result |= kPrerenderRelTypePrerender;
    UseCounter::Count(document, WebFeature::kLinkRelPrerender);
  }
  if (rel_attribute.IsLinkNext()) {
    result |= kPrerenderRelTypeNext;
    UseCounter::Count(document, WebFeature::kLinkRelNext);
  }

  return result;
}

class LinkLoader::FinishObserver final
    : public GarbageCollectedFinalized<ResourceFinishObserver>,
      public ResourceFinishObserver {
  USING_GARBAGE_COLLECTED_MIXIN(FinishObserver);
  USING_PRE_FINALIZER(FinishObserver, ClearResource);

 public:
  FinishObserver(LinkLoader* loader, Resource* resource)
      : loader_(loader), resource_(resource) {
    resource_->AddFinishObserver(
        this, loader_->client_->GetLoadingTaskRunner().get());
  }

  // ResourceFinishObserver implementation
  void NotifyFinished() override {
    if (!resource_)
      return;
    loader_->NotifyFinished();
    ClearResource();
  }
  String DebugName() const override {
    return "LinkLoader::ResourceFinishObserver";
  }

  Resource* GetResource() { return resource_; }
  void ClearResource() {
    if (!resource_)
      return;
    resource_->RemoveFinishObserver(this);
    resource_ = nullptr;
  }

  void Trace(blink::Visitor* visitor) override {
    visitor->Trace(loader_);
    visitor->Trace(resource_);
    blink::ResourceFinishObserver::Trace(visitor);
  }

 private:
  Member<LinkLoader> loader_;
  Member<Resource> resource_;
};

LinkLoader::LinkLoader(LinkLoaderClient* client,
                       scoped_refptr<WebTaskRunner> task_runner)
    : client_(client) {
  DCHECK(client_);
}

LinkLoader::~LinkLoader() {}

void LinkLoader::NotifyFinished() {
  DCHECK(finish_observer_);
  Resource* resource = finish_observer_->GetResource();
  if (resource->ErrorOccurred())
    client_->LinkLoadingErrored();
  else
    client_->LinkLoaded();
}

// https://html.spec.whatwg.org/#link-type-modulepreload
void LinkLoader::NotifyModuleLoadFinished(ModuleScript* module) {
  // Step 11. "If result is null, fire an event named error at the link element,
  // and return." [spec text]
  // Step 12. "Fire an event named load at the link element." [spec text]
  if (!module || module->IsErrored())
    client_->LinkLoadingErrored();
  else
    client_->LinkLoaded();
}

void LinkLoader::DidStartPrerender() {
  client_->DidStartLinkPrerender();
}

void LinkLoader::DidStopPrerender() {
  client_->DidStopLinkPrerender();
}

void LinkLoader::DidSendLoadForPrerender() {
  client_->DidSendLoadForLinkPrerender();
}

void LinkLoader::DidSendDOMContentLoadedForPrerender() {
  client_->DidSendDOMContentLoadedForLinkPrerender();
}

enum LinkCaller {
  kLinkCalledFromHeader,
  kLinkCalledFromMarkup,
};

static void SendMessageToConsoleForPossiblyNullDocument(
    ConsoleMessage* console_message,
    Document* document,
    LocalFrame* frame) {
  DCHECK(document || frame);
  DCHECK(!document || document->GetFrame() == frame);
  // Route the console message through Document if possible, so that script line
  // numbers can be included. Otherwise, route directly to the FrameConsole, to
  // ensure we never drop a message.
  if (document)
    document->AddConsoleMessage(console_message);
  else
    frame->Console().AddMessage(console_message);
}

static void DnsPrefetchIfNeeded(
    const LinkRelAttribute& rel_attribute,
    const KURL& href,
    Document* document,
    LocalFrame* frame,
    const NetworkHintsInterface& network_hints_interface,
    LinkCaller caller) {
  if (rel_attribute.IsDNSPrefetch()) {
    UseCounter::Count(frame, WebFeature::kLinkRelDnsPrefetch);
    if (caller == kLinkCalledFromHeader)
      UseCounter::Count(frame, WebFeature::kLinkHeaderDnsPrefetch);
    Settings* settings = frame ? frame->GetSettings() : nullptr;
    // FIXME: The href attribute of the link element can be in "//hostname"
    // form, and we shouldn't attempt to complete that as URL
    // <https://bugs.webkit.org/show_bug.cgi?id=48857>.
    if (settings && settings->GetDNSPrefetchingEnabled() && href.IsValid() &&
        !href.IsEmpty()) {
      if (settings->GetLogDnsPrefetchAndPreconnect()) {
        SendMessageToConsoleForPossiblyNullDocument(
            ConsoleMessage::Create(
                kOtherMessageSource, kVerboseMessageLevel,
                String("DNS prefetch triggered for " + href.Host())),
            document, frame);
      }
      network_hints_interface.DnsPrefetchHost(href.Host());
    }
  }
}

static void PreconnectIfNeeded(
    const LinkRelAttribute& rel_attribute,
    const KURL& href,
    Document* document,
    LocalFrame* frame,
    const CrossOriginAttributeValue cross_origin,
    const NetworkHintsInterface& network_hints_interface,
    LinkCaller caller) {
  if (rel_attribute.IsPreconnect() && href.IsValid() &&
      href.ProtocolIsInHTTPFamily()) {
    UseCounter::Count(frame, WebFeature::kLinkRelPreconnect);
    if (caller == kLinkCalledFromHeader)
      UseCounter::Count(frame, WebFeature::kLinkHeaderPreconnect);
    Settings* settings = frame ? frame->GetSettings() : nullptr;
    if (settings && settings->GetLogDnsPrefetchAndPreconnect()) {
      SendMessageToConsoleForPossiblyNullDocument(
          ConsoleMessage::Create(
              kOtherMessageSource, kVerboseMessageLevel,
              String("Preconnect triggered for ") + href.GetString()),
          document, frame);
      if (cross_origin != kCrossOriginAttributeNotSet) {
        SendMessageToConsoleForPossiblyNullDocument(
            ConsoleMessage::Create(
                kOtherMessageSource, kVerboseMessageLevel,
                String("Preconnect CORS setting is ") +
                    String((cross_origin == kCrossOriginAttributeAnonymous)
                               ? "anonymous"
                               : "use-credentials")),
            document, frame);
      }
    }
    network_hints_interface.PreconnectHost(href, cross_origin);
  }
}

WTF::Optional<Resource::Type> LinkLoader::GetResourceTypeFromAsAttribute(
    const String& as) {
  DCHECK_EQ(as.DeprecatedLower(), as);
  if (as == "image") {
    return Resource::kImage;
  } else if (as == "script") {
    return Resource::kScript;
  } else if (as == "style") {
    return Resource::kCSSStyleSheet;
  } else if (as == "video") {
    return Resource::kMedia;
  } else if (as == "audio") {
    return Resource::kMedia;
  } else if (as == "track") {
    return Resource::kTextTrack;
  } else if (as == "font") {
    return Resource::kFont;
  } else if (as == "fetch") {
    return Resource::kRaw;
  }
  return WTF::nullopt;
}

Resource* LinkLoader::GetResourceForTesting() {
  return finish_observer_ ? finish_observer_->GetResource() : nullptr;
}

static bool IsSupportedType(Resource::Type resource_type,
                            const String& mime_type) {
  if (mime_type.IsEmpty())
    return true;
  switch (resource_type) {
    case Resource::kImage:
      return MIMETypeRegistry::IsSupportedImagePrefixedMIMEType(mime_type);
    case Resource::kScript:
      return MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type);
    case Resource::kCSSStyleSheet:
      return MIMETypeRegistry::IsSupportedStyleSheetMIMEType(mime_type);
    case Resource::kFont:
      return MIMETypeRegistry::IsSupportedFontMIMEType(mime_type);
    case Resource::kMedia:
      return MIMETypeRegistry::IsSupportedMediaMIMEType(mime_type, String());
    case Resource::kTextTrack:
      return MIMETypeRegistry::IsSupportedTextTrackMIMEType(mime_type);
    case Resource::kRaw:
      return true;
    default:
      NOTREACHED();
  }
  return false;
}

static bool MediaMatches(Document& document,
                         const String& media,
                         ViewportDescription* viewport_description) {
  if (media.IsEmpty())
    return true;
  MediaValues* media_values =
      MediaValues::CreateDynamicIfFrameExists(document.GetFrame());
  if (viewport_description) {
    media_values->OverrideViewportDimensions(
        viewport_description->max_width.GetFloatValue(),
        viewport_description->max_height.GetFloatValue());
  }

  scoped_refptr<MediaQuerySet> media_queries = MediaQuerySet::Create(media);
  MediaQueryEvaluator evaluator(*media_values);
  return evaluator.Eval(*media_queries);
}

static Resource* PreloadIfNeeded(const LinkRelAttribute& rel_attribute,
                                 const KURL& href,
                                 Document& document,
                                 const String& as,
                                 const String& mime_type,
                                 const String& media,
                                 const String& nonce,
                                 CrossOriginAttributeValue cross_origin,
                                 LinkCaller caller,
                                 ViewportDescription* viewport_description,
                                 ReferrerPolicy referrer_policy) {
  if (!document.Loader() || !rel_attribute.IsLinkPreload())
    return nullptr;

  UseCounter::Count(document, WebFeature::kLinkRelPreload);
  if (!href.IsValid() || href.IsEmpty()) {
    document.AddConsoleMessage(ConsoleMessage::Create(
        kOtherMessageSource, kWarningMessageLevel,
        String("<link rel=preload> has an invalid `href` value")));
    return nullptr;
  }

  // Preload only if media matches
  if (!MediaMatches(document, media, viewport_description))
    return nullptr;

  if (caller == kLinkCalledFromHeader)
    UseCounter::Count(document, WebFeature::kLinkHeaderPreload);
  Optional<Resource::Type> resource_type =
      LinkLoader::GetResourceTypeFromAsAttribute(as);
  if (resource_type == WTF::nullopt) {
    document.AddConsoleMessage(ConsoleMessage::Create(
        kOtherMessageSource, kWarningMessageLevel,
        String("<link rel=preload> must have a valid `as` value")));
    return nullptr;
  }

  if (!IsSupportedType(resource_type.value(), mime_type)) {
    document.AddConsoleMessage(ConsoleMessage::Create(
        kOtherMessageSource, kWarningMessageLevel,
        String("<link rel=preload> has an unsupported `type` value")));
    return nullptr;
  }
  ResourceRequest resource_request(href);
  resource_request.SetRequestContext(ResourceFetcher::DetermineRequestContext(
      resource_type.value(), ResourceFetcher::kImageNotImageSet, false));

  if (referrer_policy != kReferrerPolicyDefault) {
    resource_request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
        referrer_policy, href, document.OutgoingReferrer()));
  }

  ResourceLoaderOptions options;
  options.initiator_info.name = FetchInitiatorTypeNames::link;
  FetchParameters link_fetch_params(resource_request, options);
  link_fetch_params.SetCharset(document.Encoding());

  if (cross_origin != kCrossOriginAttributeNotSet) {
    link_fetch_params.SetCrossOriginAccessControl(document.GetSecurityOrigin(),
                                                  cross_origin);
  }
  link_fetch_params.SetContentSecurityPolicyNonce(nonce);
  Settings* settings = document.GetSettings();
  if (settings && settings->GetLogPreload()) {
    document.AddConsoleMessage(ConsoleMessage::Create(
        kOtherMessageSource, kVerboseMessageLevel,
        String("Preload triggered for " + href.Host() + href.GetPath())));
  }
  link_fetch_params.SetLinkPreload(true);
  return document.Loader()->StartPreload(resource_type.value(),
                                         link_fetch_params);
}

// https://html.spec.whatwg.org/#link-type-modulepreload
static void ModulePreloadIfNeeded(const LinkRelAttribute& rel_attribute,
                                  const KURL& href,
                                  Document& document,
                                  const String& as,
                                  const String& media,
                                  const String& nonce,
                                  CrossOriginAttributeValue cross_origin,
                                  ViewportDescription* viewport_description,
                                  ReferrerPolicy referrer_policy,
                                  LinkLoader* link_loader) {
  if (!document.Loader() || !rel_attribute.IsModulePreload())
    return;

  // TODO(ksakamoto): add UseCounter

  // Step 1. "If the href attribute's value is the empty string, then return."
  // [spec text]
  if (href.IsEmpty()) {
    document.AddConsoleMessage(
        ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel,
                               "<link rel=modulepreload> has no `href` value"));
    return;
  }

  // Step 2. "Let destination be the current state of the as attribute (a
  // destination), or "script" if it is in no state." [spec text]
  // Step 3. "If destination is not script-like, then queue a task on the
  // networking task source to fire an event named error at the link element,
  // and return." [spec text]
  // Currently we only support as="script".
  if (!as.IsEmpty() && as != "script") {
    document.AddConsoleMessage(ConsoleMessage::Create(
        kOtherMessageSource, kWarningMessageLevel,
        String("<link rel=modulepreload> has an invalid `as` value " + as)));
    if (link_loader)
      link_loader->DispatchLinkLoadingErroredAsync();
    return;
  }

  // Step 4. "Parse the URL given by the href attribute, relative to the
  // element's node document. If that fails, then return. Otherwise, let url be
  // the resulting URL record." [spec text]
  // |href| is already resolved in caller side.
  if (!href.IsValid()) {
    document.AddConsoleMessage(ConsoleMessage::Create(
        kOtherMessageSource, kWarningMessageLevel,
        "<link rel=modulepreload> has an invalid `href` value " +
            href.GetString()));
    return;
  }

  // Preload only if media matches.
  // https://html.spec.whatwg.org/#processing-the-media-attribute
  if (!MediaMatches(document, media, viewport_description))
    return;

  // Step 5. "Let settings object be the link element's node document's relevant
  // settings object." [spec text]
  // |document| is the node document here, and its context document is the
  // relevant settings object.
  Document* context_document = document.ContextDocument();

  Modulator* modulator =
      Modulator::From(ToScriptStateForMainWorld(context_document->GetFrame()));
  DCHECK(modulator);
  if (!modulator)
    return;

  // Step 6. "Let credentials mode be the module script credentials mode for the
  // crossorigin attribute." [spec text]
  network::mojom::FetchCredentialsMode credentials_mode =
      ScriptLoader::ModuleScriptCredentialsMode(cross_origin);

  // Step 7. "Let cryptographic nonce be the value of the nonce attribute, if it
  // is specified, or the empty string otherwise." [spec text]
  // |nonce| parameter is the value of the nonce attribute.

  // Step 8. "Let integrity metadata be the value of the integrity attribute, if
  // it is specified, or the empty string otherwise." [spec text]
  // TODO(ksakamoto): Support integrity attribute.

  // Step 9. "Let options be a script fetch options whose cryptographic nonce is
  // cryptographic nonce, integrity metadata is integrity metadata, parser
  // metadata is "not-parser-inserted", and credentials mode is credentials
  // mode." [spec text]
  ModuleScriptFetchRequest request(
      href, referrer_policy,
      ScriptFetchOptions(nonce, IntegrityMetadataSet(), String(),
                         kNotParserInserted, credentials_mode));

  // Step 10. "Fetch a single module script given url, settings object,
  // destination, options, settings object, "client", and with the top-level
  // module fetch flag set. Wait until algorithm asynchronously completes with
  // result." [spec text]
  modulator->FetchSingle(request, ModuleGraphLevel::kDependentModuleFetch,
                         link_loader);

  Settings* settings = document.GetSettings();
  if (settings && settings->GetLogPreload()) {
    document.AddConsoleMessage(ConsoleMessage::Create(
        kOtherMessageSource, kVerboseMessageLevel,
        "Module preload triggered for " + href.Host() + href.GetPath()));
  }

  // Asynchronously continue processing after
  // LinkLoader::NotifyModuleLoadFinished() is called.
}

static Resource* PrefetchIfNeeded(Document& document,
                                  const KURL& href,
                                  const LinkRelAttribute& rel_attribute,
                                  CrossOriginAttributeValue cross_origin,
                                  ReferrerPolicy referrer_policy) {
  if (rel_attribute.IsLinkPrefetch() && href.IsValid() && document.GetFrame()) {
    UseCounter::Count(document, WebFeature::kLinkRelPrefetch);

    ResourceRequest resource_request(href);
    if (referrer_policy != kReferrerPolicyDefault) {
      resource_request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
          referrer_policy, href, document.OutgoingReferrer()));
    }

    ResourceLoaderOptions options;
    options.initiator_info.name = FetchInitiatorTypeNames::link;
    FetchParameters link_fetch_params(resource_request, options);
    if (cross_origin != kCrossOriginAttributeNotSet) {
      link_fetch_params.SetCrossOriginAccessControl(
          document.GetSecurityOrigin(), cross_origin);
    }
    return LinkFetchResource::Fetch(Resource::kLinkPrefetch, link_fetch_params,
                                    document.Fetcher());
  }
  return nullptr;
}

void LinkLoader::LoadLinksFromHeader(
    const String& header_value,
    const KURL& base_url,
    LocalFrame& frame,
    Document* document,
    const NetworkHintsInterface& network_hints_interface,
    CanLoadResources can_load_resources,
    MediaPreloadPolicy media_policy,
    ViewportDescriptionWrapper* viewport_description_wrapper) {
  if (header_value.IsEmpty())
    return;
  LinkHeaderSet header_set(header_value);
  for (auto& header : header_set) {
    if (!header.Valid() || header.Url().IsEmpty() || header.Rel().IsEmpty())
      continue;

    if (media_policy == kOnlyLoadMedia && header.Media().IsEmpty())
      continue;
    if (media_policy == kOnlyLoadNonMedia && !header.Media().IsEmpty())
      continue;

    LinkRelAttribute rel_attribute(header.Rel());
    KURL url(base_url, header.Url());
    // Sanity check to avoid re-entrancy here.
    if (url == base_url)
      continue;
    if (can_load_resources != kOnlyLoadResources) {
      DnsPrefetchIfNeeded(rel_attribute, url, document, &frame,
                          network_hints_interface, kLinkCalledFromHeader);

      PreconnectIfNeeded(rel_attribute, url, document, &frame,
                         GetCrossOriginAttributeValue(header.CrossOrigin()),
                         network_hints_interface, kLinkCalledFromHeader);
    }
    if (can_load_resources != kDoNotLoadResources) {
      DCHECK(document);
      ViewportDescription* viewport_description =
          (viewport_description_wrapper && viewport_description_wrapper->set)
              ? &(viewport_description_wrapper->description)
              : nullptr;

      CrossOriginAttributeValue cross_origin =
          GetCrossOriginAttributeValue(header.CrossOrigin());
      PreloadIfNeeded(rel_attribute, url, *document, header.As(),
                      header.MimeType(), header.Media(), header.Nonce(),
                      cross_origin, kLinkCalledFromHeader, viewport_description,
                      kReferrerPolicyDefault);
      PrefetchIfNeeded(*document, url, rel_attribute, cross_origin,
                       kReferrerPolicyDefault);
      ModulePreloadIfNeeded(rel_attribute, url, *document, header.As(),
                            header.Media(), header.Nonce(), cross_origin,
                            viewport_description, kReferrerPolicyDefault,
                            nullptr);
    }
    if (rel_attribute.IsServiceWorker()) {
      UseCounter::Count(&frame, WebFeature::kLinkHeaderServiceWorker);
    }
    // TODO(yoav): Add more supported headers as needed.
  }
}

bool LinkLoader::LoadLink(
    const LinkRelAttribute& rel_attribute,
    CrossOriginAttributeValue cross_origin,
    const String& type,
    const String& as,
    const String& media,
    const String& nonce,
    ReferrerPolicy referrer_policy,
    const KURL& href,
    Document& document,
    const NetworkHintsInterface& network_hints_interface) {
  // If any loading process is in progress, abort it.
  Abort();

  if (!client_->ShouldLoadLink())
    return false;

  DnsPrefetchIfNeeded(rel_attribute, href, &document, document.GetFrame(),
                      network_hints_interface, kLinkCalledFromMarkup);

  PreconnectIfNeeded(rel_attribute, href, &document, document.GetFrame(),
                     cross_origin, network_hints_interface,
                     kLinkCalledFromMarkup);

  Resource* resource = PreloadIfNeeded(
      rel_attribute, href, document, as, type, media, nonce, cross_origin,
      kLinkCalledFromMarkup, nullptr, referrer_policy);
  if (!resource) {
    resource = PrefetchIfNeeded(document, href, rel_attribute, cross_origin,
                                referrer_policy);
  }
  if (resource)
    finish_observer_ = new FinishObserver(this, resource);

  ModulePreloadIfNeeded(rel_attribute, href, document, as, media, nonce,
                        cross_origin, nullptr, referrer_policy, this);

  if (const unsigned prerender_rel_types =
          PrerenderRelTypesFromRelAttribute(rel_attribute, document)) {
    if (!prerender_) {
      prerender_ =
          PrerenderHandle::Create(document, this, href, prerender_rel_types);
    } else if (prerender_->Url() != href) {
      prerender_->Cancel();
      prerender_ =
          PrerenderHandle::Create(document, this, href, prerender_rel_types);
    }
    // TODO(gavinp): Handle changes to rel types of existing prerenders.
  } else if (prerender_) {
    prerender_->Cancel();
    prerender_.Clear();
  }
  return true;
}

void LinkLoader::DispatchLinkLoadingErroredAsync() {
  client_->GetLoadingTaskRunner()->PostTask(
      BLINK_FROM_HERE, WTF::Bind(&LinkLoaderClient::LinkLoadingErrored,
                                 WrapPersistent(client_.Get())));
}

void LinkLoader::Abort() {
  if (prerender_) {
    prerender_->Cancel();
    prerender_.Clear();
  }
  if (finish_observer_) {
    finish_observer_->ClearResource();
    finish_observer_ = nullptr;
  }
}

void LinkLoader::Trace(blink::Visitor* visitor) {
  visitor->Trace(finish_observer_);
  visitor->Trace(client_);
  visitor->Trace(prerender_);
  SingleModuleClient::Trace(visitor);
  PrerenderClient::Trace(visitor);
}

}  // namespace blink
