/*
    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
    rights reserved.
    Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/

    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.

    This class provides all functionality needed for loading images, style
    sheets and html pages from the web. It has a memory cache for these objects.
*/

#include "platform/loader/fetch/ResourceFetcher.h"

#include "platform/Histogram.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/instrumentation/tracing/TracedValue.h"
#include "platform/loader/fetch/FetchContext.h"
#include "platform/loader/fetch/FetchInitiatorTypeNames.h"
#include "platform/loader/fetch/MemoryCache.h"
#include "platform/loader/fetch/RawResource.h"
#include "platform/loader/fetch/ResourceLoader.h"
#include "platform/loader/fetch/ResourceLoadingLog.h"
#include "platform/loader/fetch/ResourceTimingInfo.h"
#include "platform/loader/fetch/UniqueIdentifier.h"
#include "platform/mhtml/ArchiveResource.h"
#include "platform/mhtml/MHTMLArchive.h"
#include "platform/network/NetworkInstrumentation.h"
#include "platform/network/NetworkUtils.h"
#include "platform/probe/PlatformProbes.h"
#include "platform/weborigin/KnownPorts.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "platform/weborigin/SecurityViolationReportingPolicy.h"
#include "platform/wtf/text/CString.h"
#include "platform/wtf/text/WTFString.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCachePolicy.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebURLRequest.h"

using blink::WebURLRequest;

namespace blink {

namespace {

#define DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, name)                      \
  case Resource::k##name: {                                                 \
    DEFINE_THREAD_SAFE_STATIC_LOCAL(                                        \
        EnumerationHistogram, resource_histogram,                           \
        ("Blink.MemoryCache.RevalidationPolicy." prefix #name, kLoad + 1)); \
    resource_histogram.Count(policy);                                       \
    break;                                                                  \
  }

#define DEFINE_RESOURCE_HISTOGRAM(prefix)                    \
  switch (factory.GetType()) {                               \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, CSSStyleSheet)  \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Font)           \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Image)          \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, ImportResource) \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, LinkPrefetch)   \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, MainResource)   \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Manifest)       \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Media)          \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Mock)           \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Raw)            \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Script)         \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, SVGDocument)    \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, TextTrack)      \
    DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, XSLStyleSheet)  \
  }

void AddRedirectsToTimingInfo(Resource* resource, ResourceTimingInfo* info) {
  // Store redirect responses that were packed inside the final response.
  const auto& responses = resource->GetResponse().RedirectResponses();
  for (size_t i = 0; i < responses.size(); ++i) {
    const KURL& new_url = i + 1 < responses.size()
                              ? KURL(responses[i + 1].Url())
                              : resource->GetResourceRequest().Url();
    bool cross_origin =
        !SecurityOrigin::AreSameSchemeHostPort(responses[i].Url(), new_url);
    info->AddRedirect(responses[i], cross_origin);
  }
}

ResourceLoadPriority TypeToPriority(Resource::Type type) {
  switch (type) {
    case Resource::kMainResource:
    case Resource::kCSSStyleSheet:
    case Resource::kFont:
      // Also parser-blocking scripts (set explicitly in loadPriority)
      return kResourceLoadPriorityVeryHigh;
    case Resource::kXSLStyleSheet:
      DCHECK(RuntimeEnabledFeatures::XSLTEnabled());
    case Resource::kRaw:
    case Resource::kImportResource:
    case Resource::kScript:
      // Also visible resources/images (set explicitly in loadPriority)
      return kResourceLoadPriorityHigh;
    case Resource::kManifest:
    case Resource::kMock:
      // Also late-body scripts discovered by the preload scanner (set
      // explicitly in loadPriority)
      return kResourceLoadPriorityMedium;
    case Resource::kImage:
    case Resource::kTextTrack:
    case Resource::kMedia:
    case Resource::kSVGDocument:
      // Also async scripts (set explicitly in loadPriority)
      return kResourceLoadPriorityLow;
    case Resource::kLinkPrefetch:
      return kResourceLoadPriorityVeryLow;
  }

  NOTREACHED();
  return kResourceLoadPriorityUnresolved;
}

bool ShouldResourceBeAddedToMemoryCache(const FetchParameters& params,
                                        Resource* resource) {
  if (!IsMainThread())
    return false;
  if (params.Options().data_buffering_policy == kDoNotBufferData)
    return false;

  // TODO(yhirano): Stop adding RawResources to MemoryCache completely.
  if (resource->GetType() == Resource::kMainResource)
    return false;
  if (IsRawResource(*resource) &&
      (params.IsSpeculativePreload() || params.IsLinkPreload())) {
    return false;
  }
  return true;
}

}  // namespace

ResourceLoadPriority ResourceFetcher::ComputeLoadPriority(
    Resource::Type type,
    const ResourceRequest& resource_request,
    ResourcePriority::VisibilityStatus visibility,
    FetchParameters::DeferOption defer_option,
    FetchParameters::SpeculativePreloadType speculative_preload_type,
    bool is_link_preload) {
  ResourceLoadPriority priority = TypeToPriority(type);

  // Visible resources (images in practice) get a boost to High priority.
  if (visibility == ResourcePriority::kVisible)
    priority = kResourceLoadPriorityHigh;

  // Resources before the first image are considered "early" in the document and
  // resources after the first image are "late" in the document.  Important to
  // note that this is based on when the preload scanner discovers a resource
  // for the most part so the main parser may not have reached the image element
  // yet.
  if (type == Resource::kImage && !is_link_preload)
    image_fetched_ = true;

  // A preloaded font should not take precedence over critical CSS or
  // parser-blocking scripts.
  if (type == Resource::kFont && is_link_preload)
    priority = kResourceLoadPriorityHigh;

  if (FetchParameters::kIdleLoad == defer_option) {
    priority = kResourceLoadPriorityVeryLow;
  } else if (type == Resource::kScript) {
    // Special handling for scripts.
    // Default/Parser-Blocking/Preload early in document: High (set in
    // typeToPriority)
    // Async/Defer: Low Priority (applies to both preload and parser-inserted)
    // Preload late in document: Medium
    if (FetchParameters::kLazyLoad == defer_option) {
      priority = kResourceLoadPriorityLow;
    } else if (speculative_preload_type ==
                   FetchParameters::SpeculativePreloadType::kInDocument &&
               image_fetched_) {
      // Speculative preload is used as a signal for scripts at the bottom of
      // the document.
      priority = kResourceLoadPriorityMedium;
    }
  } else if (FetchParameters::kLazyLoad == defer_option) {
    priority = kResourceLoadPriorityVeryLow;
  } else if (resource_request.GetRequestContext() ==
                 WebURLRequest::kRequestContextBeacon ||
             resource_request.GetRequestContext() ==
                 WebURLRequest::kRequestContextPing ||
             resource_request.GetRequestContext() ==
                 WebURLRequest::kRequestContextCSPReport) {
    priority = kResourceLoadPriorityVeryLow;
  }

  // A manually set priority acts as a floor. This is used to ensure that
  // synchronous requests are always given the highest possible priority, as
  // well as to ensure that there isn't priority churn if images move in and out
  // of the viewport, or are displayed more than once, both in and out of the
  // viewport.
  return std::max(priority, resource_request.Priority());
}

static void PopulateTimingInfo(ResourceTimingInfo* info, Resource* resource) {
  KURL initial_url = resource->GetResponse().RedirectResponses().IsEmpty()
                         ? resource->GetResourceRequest().Url()
                         : resource->GetResponse().RedirectResponses()[0].Url();
  info->SetInitialURL(initial_url);
  info->SetFinalResponse(resource->GetResponse());
}

WebURLRequest::RequestContext ResourceFetcher::DetermineRequestContext(
    Resource::Type type,
    IsImageSet is_image_set,
    bool is_main_frame) {
  DCHECK((is_image_set == kImageNotImageSet) ||
         (type == Resource::kImage && is_image_set == kImageIsImageSet));
  switch (type) {
    case Resource::kMainResource:
      if (!is_main_frame)
        return WebURLRequest::kRequestContextIframe;
      // FIXME: Change this to a context frame type (once we introduce them):
      // http://fetch.spec.whatwg.org/#concept-request-context-frame-type
      return WebURLRequest::kRequestContextHyperlink;
    case Resource::kXSLStyleSheet:
      DCHECK(RuntimeEnabledFeatures::XSLTEnabled());
    case Resource::kCSSStyleSheet:
      return WebURLRequest::kRequestContextStyle;
    case Resource::kScript:
      return WebURLRequest::kRequestContextScript;
    case Resource::kFont:
      return WebURLRequest::kRequestContextFont;
    case Resource::kImage:
      if (is_image_set == kImageIsImageSet)
        return WebURLRequest::kRequestContextImageSet;
      return WebURLRequest::kRequestContextImage;
    case Resource::kRaw:
      return WebURLRequest::kRequestContextSubresource;
    case Resource::kImportResource:
      return WebURLRequest::kRequestContextImport;
    case Resource::kLinkPrefetch:
      return WebURLRequest::kRequestContextPrefetch;
    case Resource::kTextTrack:
      return WebURLRequest::kRequestContextTrack;
    case Resource::kSVGDocument:
      return WebURLRequest::kRequestContextImage;
    case Resource::kMedia:  // TODO: Split this.
      return WebURLRequest::kRequestContextVideo;
    case Resource::kManifest:
      return WebURLRequest::kRequestContextManifest;
    case Resource::kMock:
      return WebURLRequest::kRequestContextSubresource;
  }
  NOTREACHED();
  return WebURLRequest::kRequestContextSubresource;
}

ResourceFetcher::ResourceFetcher(FetchContext* new_context,
                                 RefPtr<WebTaskRunner> task_runner)
    : context_(new_context),
      scheduler_(ResourceLoadScheduler::Create(&Context())),
      archive_(Context().IsMainFrame() ? nullptr : Context().Archive()),
      resource_timing_report_timer_(
          std::move(task_runner),
          this,
          &ResourceFetcher::ResourceTimingReportTimerFired),
      auto_load_images_(true),
      images_enabled_(true),
      allow_stale_resources_(false),
      image_fetched_(false) {}

ResourceFetcher::~ResourceFetcher() {}

Resource* ResourceFetcher::CachedResource(const KURL& resource_url) const {
  KURL url = MemoryCache::RemoveFragmentIdentifierIfNeeded(resource_url);
  const WeakMember<Resource>& resource = document_resources_.at(url);
  return resource.Get();
}

bool ResourceFetcher::IsControlledByServiceWorker() const {
  return Context().IsControlledByServiceWorker();
}

bool ResourceFetcher::ResourceNeedsLoad(Resource* resource,
                                        const FetchParameters& params,
                                        RevalidationPolicy policy) {
  // Defer a font load until it is actually needed unless this is a link
  // preload.
  if (resource->GetType() == Resource::kFont && !params.IsLinkPreload())
    return false;
  if (resource->GetType() == Resource::kImage &&
      ShouldDeferImageLoad(resource->Url()))
    return false;
  return policy != kUse || resource->StillNeedsLoad();
}

// Limit the number of URLs in m_validatedURLs to avoid memory bloat.
// http://crbug.com/52411
static const int kMaxValidatedURLsSize = 10000;

void ResourceFetcher::RequestLoadStarted(unsigned long identifier,
                                         Resource* resource,
                                         const FetchParameters& params,
                                         RevalidationPolicy policy,
                                         bool is_static_data) {
  if (policy == kUse && resource->GetStatus() == ResourceStatus::kCached &&
      !validated_urls_.Contains(resource->Url())) {
    // Loaded from MemoryCache.
    DidLoadResourceFromMemoryCache(identifier, resource,
                                   params.GetResourceRequest());
  }

  if (is_static_data)
    return;

  if (policy == kUse && !resource->StillNeedsLoad() &&
      !validated_urls_.Contains(params.GetResourceRequest().Url())) {
    // Resources loaded from memory cache should be reported the first time
    // they're used.
    RefPtr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
        params.Options().initiator_info.name, MonotonicallyIncreasingTime(),
        resource->GetType() == Resource::kMainResource);
    PopulateTimingInfo(info.Get(), resource);
    info->ClearLoadTimings();
    info->SetLoadFinishTime(info->InitialTime());
    scheduled_resource_timing_reports_.push_back(std::move(info));
    if (!resource_timing_report_timer_.IsActive())
      resource_timing_report_timer_.StartOneShot(0, BLINK_FROM_HERE);
  }

  if (validated_urls_.size() >= kMaxValidatedURLsSize) {
    validated_urls_.clear();
  }
  validated_urls_.insert(params.GetResourceRequest().Url());
}

void ResourceFetcher::DidLoadResourceFromMemoryCache(
    unsigned long identifier,
    Resource* resource,
    const ResourceRequest& original_resource_request) {
  ResourceRequest resource_request(resource->Url());
  resource_request.SetFrameType(original_resource_request.GetFrameType());
  resource_request.SetRequestContext(
      original_resource_request.GetRequestContext());
  Context().DispatchDidLoadResourceFromMemoryCache(identifier, resource_request,
                                                   resource->GetResponse());
  Context().DispatchWillSendRequest(identifier, resource_request,
                                    ResourceResponse() /* redirects */,
                                    resource->Options().initiator_info);
  Context().DispatchDidReceiveResponse(
      identifier, resource->GetResponse(), resource_request.GetFrameType(),
      resource_request.GetRequestContext(), resource,
      FetchContext::ResourceResponseType::kFromMemoryCache);

  if (resource->EncodedSize() > 0)
    Context().DispatchDidReceiveData(identifier, 0, resource->EncodedSize());

  Context().DispatchDidFinishLoading(
      identifier, 0, 0, resource->GetResponse().DecodedBodyLength());
}

static std::unique_ptr<TracedValue> UrlForTraceEvent(const KURL& url) {
  std::unique_ptr<TracedValue> value = TracedValue::Create();
  value->SetString("url", url.GetString());
  return value;
}

Resource* ResourceFetcher::ResourceForStaticData(
    const FetchParameters& params,
    const ResourceFactory& factory,
    const SubstituteData& substitute_data) {
  const KURL& url = params.GetResourceRequest().Url();
  DCHECK(url.ProtocolIsData() || substitute_data.IsValid() || archive_);

  // TODO(japhet): We only send main resource data: urls through WebURLLoader
  // for the benefit of a service worker test
  // (RenderViewImplTest.ServiceWorkerNetworkProviderSetup), which is at a layer
  // where it isn't easy to mock out a network load. It uses data: urls to
  // emulate the behavior it wants to test, which would otherwise be reserved
  // for network loads.
  if (!archive_ && !substitute_data.IsValid() &&
      (factory.GetType() == Resource::kMainResource ||
       factory.GetType() == Resource::kRaw))
    return nullptr;

  const String cache_identifier = GetCacheIdentifier();
  if (Resource* old_resource =
          GetMemoryCache()->ResourceForURL(url, cache_identifier)) {
    // There's no reason to re-parse if we saved the data from the previous
    // parse.
    if (params.Options().data_buffering_policy != kDoNotBufferData)
      return old_resource;
    GetMemoryCache()->Remove(old_resource);
  }

  ResourceResponse response;
  RefPtr<SharedBuffer> data;
  if (substitute_data.IsValid()) {
    data = substitute_data.Content();
    response.SetURL(url);
    response.SetMimeType(substitute_data.MimeType());
    response.SetExpectedContentLength(data->size());
    response.SetTextEncodingName(substitute_data.TextEncoding());
  } else if (url.ProtocolIsData()) {
    data = NetworkUtils::ParseDataURLAndPopulateResponse(url, response);
    if (!data)
      return nullptr;
    // |response| is modified by parseDataURLAndPopulateResponse() and is
    // ready to be used.
  } else {
    ArchiveResource* archive_resource =
        archive_->SubresourceForURL(params.Url());
    // The archive doesn't contain the resource, the request must be aborted.
    if (!archive_resource)
      return nullptr;
    data = archive_resource->Data();
    response.SetURL(url);
    response.SetMimeType(archive_resource->MimeType());
    response.SetExpectedContentLength(data->size());
    response.SetTextEncodingName(archive_resource->TextEncoding());
  }

  Resource* resource = factory.Create(
      params.GetResourceRequest(), params.Options(), params.DecoderOptions());
  resource->SetNeedsSynchronousCacheHit(substitute_data.ForceSynchronousLoad());
  // FIXME: We should provide a body stream here.
  resource->SetStatus(ResourceStatus::kPending);
  resource->NotifyStartLoad();
  resource->ResponseReceived(response, nullptr);
  resource->SetDataBufferingPolicy(kBufferData);
  if (data->size())
    resource->SetResourceBuffer(data);
  resource->SetIdentifier(CreateUniqueIdentifier());
  resource->SetCacheIdentifier(cache_identifier);
  resource->Finish();

  if (ShouldResourceBeAddedToMemoryCache(params, resource) &&
      !substitute_data.IsValid()) {
    GetMemoryCache()->Add(resource);
  }

  return resource;
}

Resource* ResourceFetcher::ResourceForBlockedRequest(
    const FetchParameters& params,
    const ResourceFactory& factory,
    ResourceRequestBlockedReason blocked_reason) {
  Resource* resource = factory.Create(
      params.GetResourceRequest(), params.Options(), params.DecoderOptions());
  resource->SetStatus(ResourceStatus::kPending);
  resource->NotifyStartLoad();
  resource->FinishAsError(ResourceError::CancelledDueToAccessCheckError(
      params.Url(), blocked_reason));
  return resource;
}

void ResourceFetcher::MakePreloadedResourceBlockOnloadIfNeeded(
    Resource* resource,
    const FetchParameters& params) {
  // TODO(yoav): Test that non-blocking resources (video/audio/track) continue
  // to not-block even after being preloaded and discovered.
  if (resource && resource->Loader() &&
      resource->IsLoadEventBlockingResourceType() &&
      resource->IsLinkPreload() && !params.IsLinkPreload() &&
      non_blocking_loaders_.Contains(resource->Loader())) {
    non_blocking_loaders_.erase(resource->Loader());
    loaders_.insert(resource->Loader());
  }
}

void ResourceFetcher::UpdateMemoryCacheStats(Resource* resource,
                                             RevalidationPolicy policy,
                                             const FetchParameters& params,
                                             const ResourceFactory& factory,
                                             bool is_static_data) const {
  if (is_static_data)
    return;

  if (params.IsSpeculativePreload() || params.IsLinkPreload()) {
    DEFINE_RESOURCE_HISTOGRAM("Preload.");
  } else {
    DEFINE_RESOURCE_HISTOGRAM("");
  }

  // Aims to count Resource only referenced from MemoryCache (i.e. what would be
  // dead if MemoryCache holds weak references to Resource). Currently we check
  // references to Resource from ResourceClient and |m_preloads| only, because
  // they are major sources of references.
  if (resource && !resource->IsAlive() && !ContainsAsPreload(resource)) {
    DEFINE_RESOURCE_HISTOGRAM("Dead.");
  }
}

bool ResourceFetcher::ContainsAsPreload(Resource* resource) const {
  auto it = preloads_.find(PreloadKey(resource->Url(), resource->GetType()));
  return it != preloads_.end() && it->value == resource;
}

void ResourceFetcher::RemovePreload(Resource* resource) {
  auto it = preloads_.find(PreloadKey(resource->Url(), resource->GetType()));
  if (it == preloads_.end())
    return;
  if (it->value == resource)
    preloads_.erase(it);
}

ResourceFetcher::PrepareRequestResult ResourceFetcher::PrepareRequest(
    FetchParameters& params,
    const ResourceFactory& factory,
    const SubstituteData& substitute_data,
    unsigned long identifier,
    ResourceRequestBlockedReason& blocked_reason) {
  ResourceRequest& resource_request = params.MutableResourceRequest();

  DCHECK(params.Options().synchronous_policy == kRequestAsynchronously ||
         factory.GetType() == Resource::kRaw ||
         factory.GetType() == Resource::kXSLStyleSheet);

  params.OverrideContentType(factory.ContentType());

  SecurityViolationReportingPolicy reporting_policy =
      params.IsSpeculativePreload()
          ? SecurityViolationReportingPolicy::kSuppressReporting
          : SecurityViolationReportingPolicy::kReport;
  Context().PopulateResourceRequest(
      MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()),
      factory.GetType(), params.GetClientHintsPreferences(),
      params.GetResourceWidth(), params.Options(), reporting_policy,
      resource_request);

  if (!params.Url().IsValid())
    return kAbort;

  resource_request.SetPriority(ComputeLoadPriority(
      factory.GetType(), params.GetResourceRequest(),
      ResourcePriority::kNotVisible, params.Defer(),
      params.GetSpeculativePreloadType(), params.IsLinkPreload()));
  InitializeResourceRequest(resource_request, factory.GetType(),
                            params.Defer());
  network_instrumentation::ResourcePrioritySet(identifier,
                                               resource_request.Priority());

  blocked_reason = Context().CanRequest(
      factory.GetType(), resource_request,
      MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()),
      params.Options(),
      /* Don't send security violation reports for speculative preloads */
      reporting_policy, params.GetOriginRestriction());
  if (blocked_reason != ResourceRequestBlockedReason::kNone) {
    DCHECK(!substitute_data.ForceSynchronousLoad());
    return kBlock;
  }

  // For initial requests, call prepareRequest() here before revalidation
  // policy is determined.
  Context().PrepareRequest(resource_request,
                           FetchContext::RedirectType::kNotForRedirect);

  if (!params.Url().IsValid())
    return kAbort;

  RefPtr<SecurityOrigin> origin = params.Options().security_origin;
  params.MutableOptions().cors_flag =
      !origin || !origin->CanRequestNoSuborigin(params.Url());

  if (params.Options().cors_handling_by_resource_fetcher ==
      kEnableCORSHandlingByResourceFetcher) {
    bool allow_stored_credentials = false;
    switch (resource_request.GetFetchCredentialsMode()) {
      case WebURLRequest::kFetchCredentialsModeOmit:
        break;
      case WebURLRequest::kFetchCredentialsModeSameOrigin:
        allow_stored_credentials =
            !params.Options().cors_flag ||
            (origin &&
             origin->HasSuboriginAndShouldAllowCredentialsFor(params.Url()));
        break;
      case WebURLRequest::kFetchCredentialsModeInclude:
      case WebURLRequest::kFetchCredentialsModePassword:
        allow_stored_credentials = true;
        break;
    }
    resource_request.SetAllowStoredCredentials(allow_stored_credentials);
  }

  return kContinue;
}

Resource* ResourceFetcher::RequestResource(
    FetchParameters& params,
    const ResourceFactory& factory,
    const SubstituteData& substitute_data) {
  unsigned long identifier = CreateUniqueIdentifier();
  ResourceRequest& resource_request = params.MutableResourceRequest();
  network_instrumentation::ScopedResourceLoadTracker
      scoped_resource_load_tracker(identifier, resource_request);
  SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.Fetch.RequestResourceTime");
  // TODO(dproy): Remove this. http://crbug.com/659666
  TRACE_EVENT1("blink", "ResourceFetcher::requestResource", "url",
               UrlForTraceEvent(params.Url()));

  Resource* resource = nullptr;
  ResourceRequestBlockedReason blocked_reason =
      ResourceRequestBlockedReason::kNone;

  PrepareRequestResult result = PrepareRequest(params, factory, substitute_data,
                                               identifier, blocked_reason);
  if (result == kAbort)
    return nullptr;
  if (result == kBlock)
    return ResourceForBlockedRequest(params, factory, blocked_reason);

  if (!params.IsSpeculativePreload()) {
    // Only log if it's not for speculative preload.
    Context().RecordLoadingActivity(identifier, resource_request,
                                    factory.GetType(),
                                    params.Options().initiator_info.name);
  }

  // An URL with the "cid" scheme can only be handled by an MHTML Archive.
  // Abort the request when there is none.
  if (!archive_ && resource_request.Url().ProtocolIs(kContentIdScheme))
    return nullptr;

  bool is_data_url = resource_request.Url().ProtocolIsData();
  bool is_static_data = is_data_url || substitute_data.IsValid() || archive_;
  if (is_static_data) {
    resource = ResourceForStaticData(params, factory, substitute_data);
    // Abort the request if the archive doesn't contain the resource, except in
    // the case of data URLs which might have resources such as fonts that need
    // to be decoded only on demand. These data URLs are allowed to be
    // processed using the normal ResourceFetcher machinery.
    if (!resource && !is_data_url && archive_)
      return nullptr;
  }
  RevalidationPolicy policy = kLoad;
  bool preload_found = false;
  if (!resource) {
    resource = MatchPreload(params, factory.GetType());
    if (resource) {
      preload_found = true;
      policy = kUse;
      // If |param| is for a blocking resource and a preloaded resource is
      // found, we may need to make it block the onload event.
      MakePreloadedResourceBlockOnloadIfNeeded(resource, params);
    }
  }
  if (!preload_found) {
    if (!resource && IsMainThread()) {
      resource =
          GetMemoryCache()->ResourceForURL(params.Url(), GetCacheIdentifier());
    }

    policy = DetermineRevalidationPolicy(factory.GetType(), params, resource,
                                         is_static_data);
    TRACE_EVENT_INSTANT1(
        "blink", "ResourceFetcher::determineRevalidationPolicy",
        TRACE_EVENT_SCOPE_THREAD, "revalidationPolicy", policy);
  }

  UpdateMemoryCacheStats(resource, policy, params, factory, is_static_data);

  switch (policy) {
    case kReload:
      GetMemoryCache()->Remove(resource);
    // Fall through
    case kLoad:
      resource = CreateResourceForLoading(params, factory);
      break;
    case kRevalidate:
      InitializeRevalidation(resource_request, resource);
      break;
    case kUse:
      if (resource->IsLinkPreload() && !params.IsLinkPreload())
        resource->SetLinkPreload(false);
      break;
  }
  if (!resource)
    return nullptr;

  // TODO(yoav): turn to a DCHECK. See https://crbug.com/690632
  CHECK_EQ(resource->GetType(), factory.GetType());

  if (policy != kUse)
    resource->SetIdentifier(identifier);

  // TODO(yoav): It is not clear why preloads are exempt from this check. Can we
  // remove the exemption?
  if (!params.IsSpeculativePreload() || policy != kUse) {
    // When issuing another request for a resource that is already in-flight
    // make sure to not demote the priority of the in-flight request. If the new
    // request isn't at the same priority as the in-flight request, only allow
    // promotions. This can happen when a visible image's priority is increased
    // and then another reference to the image is parsed (which would be at a
    // lower priority).
    if (resource_request.Priority() > resource->GetResourceRequest().Priority())
      resource->DidChangePriority(resource_request.Priority(), 0);
    // TODO(yoav): I'd expect the stated scenario to not go here, as its policy
    // would be Use.
  }

  // If only the fragment identifiers differ, it is the same resource.
  DCHECK(EqualIgnoringFragmentIdentifier(resource->Url(), params.Url()));
  RequestLoadStarted(identifier, resource, params, policy, is_static_data);
  document_resources_.Set(
      MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()), resource);

  // Returns with an existing resource if the resource does not need to start
  // loading immediately. If revalidation policy was determined as |Revalidate|,
  // the resource was already initialized for the revalidation here, but won't
  // start loading.
  if (!ResourceNeedsLoad(resource, params, policy)) {
    if (policy != kUse)
      InsertAsPreloadIfNecessary(resource, params, factory.GetType());
    return resource;
  }

  if (!StartLoad(resource))
    return nullptr;

  if (policy != kUse)
    InsertAsPreloadIfNecessary(resource, params, factory.GetType());
  scoped_resource_load_tracker.ResourceLoadContinuesBeyondScope();

  DCHECK(!resource->ErrorOccurred() ||
         params.Options().synchronous_policy == kRequestSynchronously);
  return resource;
}

void ResourceFetcher::ResourceTimingReportTimerFired(TimerBase* timer) {
  DCHECK_EQ(timer, &resource_timing_report_timer_);
  Vector<RefPtr<ResourceTimingInfo>> timing_reports;
  timing_reports.swap(scheduled_resource_timing_reports_);
  for (const auto& timing_info : timing_reports)
    Context().AddResourceTiming(*timing_info);
}

WebURLRequest::RequestContext ResourceFetcher::DetermineRequestContext(
    Resource::Type type,
    IsImageSet is_image_set) const {
  return DetermineRequestContext(type, is_image_set, Context().IsMainFrame());
}

void ResourceFetcher::InitializeResourceRequest(
    ResourceRequest& request,
    Resource::Type type,
    FetchParameters::DeferOption defer) {
  if (request.GetCachePolicy() == WebCachePolicy::kUseProtocolCachePolicy) {
    request.SetCachePolicy(
        Context().ResourceRequestCachePolicy(request, type, defer));
  }
  if (request.GetRequestContext() == WebURLRequest::kRequestContextUnspecified)
    request.SetRequestContext(DetermineRequestContext(type, kImageNotImageSet));
  if (type == Resource::kLinkPrefetch)
    request.SetHTTPHeaderField(HTTPNames::Purpose, "prefetch");

  Context().AddAdditionalRequestHeaders(
      request, (type == Resource::kMainResource) ? kFetchMainResource
                                                 : kFetchSubresource);
}

void ResourceFetcher::InitializeRevalidation(
    ResourceRequest& revalidating_request,
    Resource* resource) {
  DCHECK(resource);
  DCHECK(GetMemoryCache()->Contains(resource));
  DCHECK(resource->IsLoaded());
  DCHECK(resource->CanUseCacheValidator());
  DCHECK(!resource->IsCacheValidator());
  DCHECK(!Context().IsControlledByServiceWorker());

  const AtomicString& last_modified =
      resource->GetResponse().HttpHeaderField(HTTPNames::Last_Modified);
  const AtomicString& e_tag =
      resource->GetResponse().HttpHeaderField(HTTPNames::ETag);
  if (!last_modified.IsEmpty() || !e_tag.IsEmpty()) {
    DCHECK_NE(WebCachePolicy::kBypassingCache,
              revalidating_request.GetCachePolicy());
    if (revalidating_request.GetCachePolicy() ==
        WebCachePolicy::kValidatingCacheData) {
      revalidating_request.SetHTTPHeaderField(HTTPNames::Cache_Control,
                                              "max-age=0");
    }
  }
  if (!last_modified.IsEmpty()) {
    revalidating_request.SetHTTPHeaderField(HTTPNames::If_Modified_Since,
                                            last_modified);
  }
  if (!e_tag.IsEmpty())
    revalidating_request.SetHTTPHeaderField(HTTPNames::If_None_Match, e_tag);

  resource->SetRevalidatingRequest(revalidating_request);
}

Resource* ResourceFetcher::CreateResourceForLoading(
    FetchParameters& params,
    const ResourceFactory& factory) {
  const String cache_identifier = GetCacheIdentifier();
  DCHECK(!IsMainThread() ||
         !GetMemoryCache()->ResourceForURL(params.GetResourceRequest().Url(),
                                           cache_identifier));

  RESOURCE_LOADING_DVLOG(1) << "Loading Resource for "
                            << params.GetResourceRequest().Url().ElidedString();

  Resource* resource = factory.Create(
      params.GetResourceRequest(), params.Options(), params.DecoderOptions());
  resource->SetLinkPreload(params.IsLinkPreload());
  if (params.IsSpeculativePreload()) {
    resource->SetPreloadDiscoveryTime(params.PreloadDiscoveryTime());
  }
  resource->SetCacheIdentifier(cache_identifier);

  if (ShouldResourceBeAddedToMemoryCache(params, resource))
    GetMemoryCache()->Add(resource);
  return resource;
}

void ResourceFetcher::StorePerformanceTimingInitiatorInformation(
    Resource* resource) {
  const AtomicString& fetch_initiator = resource->Options().initiator_info.name;
  if (fetch_initiator == FetchInitiatorTypeNames::internal)
    return;

  bool is_main_resource = resource->GetType() == Resource::kMainResource;

  // The request can already be fetched in a previous navigation. Thus
  // startTime must be set accordingly.
  double start_time = resource->GetResourceRequest().NavigationStartTime()
                          ? resource->GetResourceRequest().NavigationStartTime()
                          : MonotonicallyIncreasingTime();

  // This buffer is created and populated for providing transferSize
  // and redirect timing opt-in information.
  if (is_main_resource) {
    DCHECK(!navigation_timing_info_);
    navigation_timing_info_ = ResourceTimingInfo::Create(
        fetch_initiator, start_time, is_main_resource);
  }

  RefPtr<ResourceTimingInfo> info =
      ResourceTimingInfo::Create(fetch_initiator, start_time, is_main_resource);

  if (resource->IsCacheValidator()) {
    const AtomicString& timing_allow_origin =
        resource->GetResponse().HttpHeaderField(HTTPNames::Timing_Allow_Origin);
    if (!timing_allow_origin.IsEmpty())
      info->SetOriginalTimingAllowOrigin(timing_allow_origin);
  }

  if (!is_main_resource ||
      Context().UpdateTimingInfoForIFrameNavigation(info.Get())) {
    resource_timing_info_map_.insert(resource, std::move(info));
  }
}

void ResourceFetcher::RecordResourceTimingOnRedirect(
    Resource* resource,
    const ResourceResponse& redirect_response,
    bool cross_origin) {
  ResourceTimingInfoMap::iterator it = resource_timing_info_map_.find(resource);
  if (it != resource_timing_info_map_.end()) {
    it->value->AddRedirect(redirect_response, cross_origin);
  }

  if (resource->GetType() == Resource::kMainResource) {
    DCHECK(navigation_timing_info_);
    navigation_timing_info_->AddRedirect(redirect_response, cross_origin);
  }
}

Resource* ResourceFetcher::MatchPreload(const FetchParameters& params,
                                        Resource::Type type) {
  auto it = preloads_.find(PreloadKey(params.Url(), type));
  if (it == preloads_.end())
    return nullptr;

  Resource* resource = it->value;

  if (resource->MustRefetchDueToIntegrityMetadata(params))
    return nullptr;

  if (params.IsSpeculativePreload())
    return resource;
  if (params.IsLinkPreload()) {
    resource->SetLinkPreload(true);
    return resource;
  }

  if (!IsReusableAlsoForPreloading(params, resource, false))
    return nullptr;

  resource->MatchPreload();
  preloads_.erase(it);
  matched_preloads_.push_back(resource);
  return resource;
}

void ResourceFetcher::InsertAsPreloadIfNecessary(Resource* resource,
                                                 const FetchParameters& params,
                                                 Resource::Type type) {
  if (!params.IsSpeculativePreload() && !params.IsLinkPreload())
    return;
  // CSP layout tests verify that preloads are subject to access checks by
  // seeing if they are in the `preload started` list. Therefore do not add
  // them to the list if the load is immediately denied.
  if (resource->GetResourceError().IsAccessCheck())
    return;
  PreloadKey key(params.Url(), type);
  if (preloads_.find(key) == preloads_.end()) {
    preloads_.insert(key, resource);
    resource->MarkAsPreload();
    if (preloaded_urls_for_test_)
      preloaded_urls_for_test_->insert(resource->Url().GetString());
  }
}

bool ResourceFetcher::IsReusableAlsoForPreloading(const FetchParameters& params,
                                                  Resource* existing_resource,
                                                  bool is_static_data) const {
  const ResourceRequest& request = params.GetResourceRequest();

  // Do not load from cache if images are not enabled. There are two general
  // cases:
  //
  // 1. Images are disabled. Don't ever load images, even if the image is cached
  // or it is a data: url. In this case, we "Reload" the image, then defer it
  // with resourceNeedsLoad() so that it never actually goes to the network.
  //
  // 2. Images are enabled, but not loaded automatically. In this case, we will
  // Use cached resources or data: urls, but will similarly fall back to a
  // deferred network load if we don't have the data available without a network
  // request. We check allowImage() here, which is affected by m_imagesEnabled
  // but not m_autoLoadImages, in order to allow for this differing behavior.
  //
  // TODO(japhet): Can we get rid of one of these settings?
  if (existing_resource->GetType() == Resource::kImage &&
      !Context().AllowImage(images_enabled_, existing_resource->Url())) {
    return false;
  }

  // Never use cache entries for downloadToFile / useStreamOnResponse requests.
  // The data will be delivered through other paths.
  if (request.DownloadToFile() || request.UseStreamOnResponse())
    return false;

  // Never reuse opaque responses from a service worker for requests that are
  // not no-cors. https://crbug.com/625575
  // TODO(yhirano): Remove this.
  if (existing_resource->GetResponse().WasFetchedViaServiceWorker() &&
      existing_resource->GetResponse().ServiceWorkerResponseType() ==
          kWebServiceWorkerResponseTypeOpaque &&
      request.GetFetchRequestMode() != WebURLRequest::kFetchRequestModeNoCORS) {
    return false;
  }

  if (is_static_data)
    return true;

  return existing_resource->CanReuse(params);
}

ResourceFetcher::RevalidationPolicy
ResourceFetcher::DetermineRevalidationPolicy(
    Resource::Type type,
    const FetchParameters& fetch_params,
    Resource* existing_resource,
    bool is_static_data) const {
  const ResourceRequest& request = fetch_params.GetResourceRequest();

  if (!existing_resource)
    return kLoad;

  // If the existing resource is loading and the associated fetcher is not equal
  // to |this|, we must not use the resource. Otherwise, CSP violation may
  // happen in redirect handling.
  if (existing_resource->Loader() &&
      existing_resource->Loader()->Fetcher() != this) {
    return kReload;
  }

  // It's hard to share a not-yet-referenced preloads via MemoryCache correctly.
  // A not-yet-matched preloads made by a foreign ResourceFetcher and stored in
  // the memory cache could be used without this block.
  if ((fetch_params.IsLinkPreload() || fetch_params.IsSpeculativePreload()) &&
      existing_resource->IsUnusedPreload()) {
    return kReload;
  }

  // Checks if the resource has an explicit policy about integrity metadata.
  //
  // This is necessary because ScriptResource and CSSStyleSheetResource objects
  // do not keep the raw data around after the source is accessed once, so if
  // the resource is accessed from the MemoryCache for a second time, there is
  // no way to redo an integrity check.
  //
  // Thus, Blink implements a scheme where it caches the integrity information
  // for those resources after the first time it is checked, and if there is
  // another request for that resource, with the same integrity metadata, Blink
  // skips the integrity calculation. However, if the integrity metadata is a
  // mismatch, the MemoryCache must be skipped here, and a new request for the
  // resource must be made to get the raw data. This is expected to be an
  // uncommon case, however, as it implies two same-origin requests to the same
  // resource, but with different integrity metadata.
  if (existing_resource->MustRefetchDueToIntegrityMetadata(fetch_params)) {
    return kReload;
  }

  // If the same URL has been loaded as a different type, we need to reload.
  if (existing_resource->GetType() != type) {
    // FIXME: If existingResource is a Preload and the new type is LinkPrefetch
    // We really should discard the new prefetch since the preload has more
    // specific type information! crbug.com/379893
    // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case.
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
                                 "reloading due to type mismatch.";
    return kReload;
  }

  // If |existing_resource| is not reusable as a preloaded resource, it should
  // not be reusable as a normal resource as well.
  if (!IsReusableAlsoForPreloading(fetch_params, existing_resource,
                                   is_static_data)) {
    return kReload;
  }

  // If resource was populated from a SubstituteData load or data: url, use it.
  if (is_static_data)
    return kUse;

  // Don't reload resources while pasting.
  if (allow_stale_resources_)
    return kUse;

  // WebCachePolicy::ReturnCacheDataElseLoad uses the cache no matter what.
  if (request.GetCachePolicy() == WebCachePolicy::kReturnCacheDataElseLoad)
    return kUse;

  // Don't reuse resources with Cache-control: no-store.
  if (existing_resource->HasCacheControlNoStoreHeader()) {
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
                                 "reloading due to Cache-control: no-store.";
    return kReload;
  }

  // If credentials were sent with the previous request and won't be with this
  // one, or vice versa, re-fetch the resource.
  //
  // This helps with the case where the server sends back
  // "Access-Control-Allow-Origin: *" all the time, but some of the client's
  // requests are made without CORS and some with.
  if (existing_resource->GetResourceRequest().AllowStoredCredentials() !=
      request.AllowStoredCredentials()) {
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
                                 "reloading due to difference in credentials "
                                 "settings.";
    return kReload;
  }

  // During the initial load, avoid loading the same resource multiple times for
  // a single document, even if the cache policies would tell us to. We also
  // group loads of the same resource together. Raw resources are exempted, as
  // XHRs fall into this category and may have user-set Cache-Control: headers
  // or other factors that require separate requests.
  if (type != Resource::kRaw) {
    if (!Context().IsLoadComplete() &&
        validated_urls_.Contains(existing_resource->Url()))
      return kUse;
    if (existing_resource->IsLoading())
      return kUse;
  }

  // WebCachePolicy::BypassingCache always reloads
  if (request.GetCachePolicy() == WebCachePolicy::kBypassingCache) {
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
                                 "reloading due to "
                                 "WebCachePolicy::BypassingCache.";
    return kReload;
  }

  // We'll try to reload the resource if it failed last time.
  if (existing_resource->ErrorOccurred()) {
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
                                 "reloading due to resource being in the error "
                                 "state";
    return kReload;
  }

  // List of available images logic allows images to be re-used without cache
  // validation. We restrict this only to images from memory cache which are the
  // same as the version in the current document.
  if (type == Resource::kImage &&
      existing_resource == CachedResource(request.Url())) {
    return kUse;
  }

  if (existing_resource->MustReloadDueToVaryHeader(request))
    return kReload;

  // If any of the redirects in the chain to loading the resource were not
  // cacheable, we cannot reuse our cached resource.
  if (!existing_resource->CanReuseRedirectChain()) {
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
                                 "reloading due to an uncacheable redirect";
    return kReload;
  }

  // Check if the cache headers requires us to revalidate (cache expiration for
  // example).
  if (request.GetCachePolicy() == WebCachePolicy::kValidatingCacheData ||
      existing_resource->MustRevalidateDueToCacheHeaders() ||
      request.CacheControlContainsNoCache()) {
    // Revalidation is harmful for non-matched preloads because it may lead to
    // sharing one preloaded resource among multiple ResourceFetchers.
    if (existing_resource->IsUnusedPreload())
      return kReload;

    // See if the resource has usable ETag or Last-modified headers. If the page
    // is controlled by the ServiceWorker, we choose the Reload policy because
    // the revalidation headers should not be exposed to the
    // ServiceWorker.(crbug.com/429570)
    if (existing_resource->CanUseCacheValidator() &&
        !Context().IsControlledByServiceWorker()) {
      // If the resource is already a cache validator but not started yet, the
      // |Use| policy should be applied to subsequent requests.
      if (existing_resource->IsCacheValidator()) {
        DCHECK(existing_resource->StillNeedsLoad());
        return kUse;
      }
      return kRevalidate;
    }

    // No, must reload.
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
                                 "reloading due to missing cache validators.";
    return kReload;
  }

  return kUse;
}

void ResourceFetcher::SetAutoLoadImages(bool enable) {
  if (enable == auto_load_images_)
    return;

  auto_load_images_ = enable;

  if (!auto_load_images_)
    return;

  ReloadImagesIfNotDeferred();
}

void ResourceFetcher::SetImagesEnabled(bool enable) {
  if (enable == images_enabled_)
    return;

  images_enabled_ = enable;

  if (!images_enabled_)
    return;

  ReloadImagesIfNotDeferred();
}

bool ResourceFetcher::ShouldDeferImageLoad(const KURL& url) const {
  return !Context().AllowImage(images_enabled_, url) || !auto_load_images_;
}

void ResourceFetcher::ReloadImagesIfNotDeferred() {
  for (Resource* resource : document_resources_.Values()) {
    if (resource->GetType() == Resource::kImage && resource->StillNeedsLoad() &&
        !ShouldDeferImageLoad(resource->Url()))
      StartLoad(resource);
  }
}

void ResourceFetcher::ClearContext() {
  scheduler_->Shutdown();
  ClearPreloads(ResourceFetcher::kClearAllPreloads);
  context_ = Context().Detach();
}

int ResourceFetcher::BlockingRequestCount() const {
  return loaders_.size();
}

int ResourceFetcher::NonblockingRequestCount() const {
  return non_blocking_loaders_.size();
}

void ResourceFetcher::EnableIsPreloadedForTest() {
  if (preloaded_urls_for_test_)
    return;
  preloaded_urls_for_test_ = WTF::WrapUnique(new HashSet<String>);

  for (const auto& pair : preloads_) {
    Resource* resource = pair.value;
    preloaded_urls_for_test_->insert(resource->Url().GetString());
  }
}

bool ResourceFetcher::IsPreloadedForTest(const KURL& url) const {
  DCHECK(preloaded_urls_for_test_);
  return preloaded_urls_for_test_->Contains(url.GetString());
}

void ResourceFetcher::ClearPreloads(ClearPreloadsPolicy policy) {
  LogPreloadStats(policy);

  Vector<PreloadKey> keys_to_be_removed;
  for (const auto& pair : preloads_) {
    Resource* resource = pair.value;
    if (policy == kClearAllPreloads || !resource->IsLinkPreload()) {
      GetMemoryCache()->Remove(resource);
      keys_to_be_removed.push_back(pair.key);
    }
  }
  preloads_.RemoveAll(keys_to_be_removed);

  matched_preloads_.clear();
}

void ResourceFetcher::WarnUnusedPreloads() {
  for (const auto& pair : preloads_) {
    Resource* resource = pair.value;
    if (resource && resource->IsLinkPreload() && resource->IsUnusedPreload()) {
      Context().AddConsoleMessage(
          "The resource " + resource->Url().GetString() +
              " was preloaded using link preload but not used within a few "
              "seconds from the window's load event. Please make sure it "
              "wasn't preloaded for nothing.",
          FetchContext::kLogWarningMessage);
    }
  }
}

ArchiveResource* ResourceFetcher::CreateArchive(Resource* resource) {
  // Only the top-frame can load MHTML.
  if (!Context().IsMainFrame()) {
    Context().AddConsoleMessage(
        "Attempted to load a multipart archive into an subframe: " +
            resource->Url().GetString(),
        FetchContext::kLogErrorMessage);
    return nullptr;
  }

  archive_ = MHTMLArchive::Create(resource->Url(), resource->ResourceBuffer());
  if (!archive_) {
    // Log if attempting to load an invalid archive resource.
    Context().AddConsoleMessage(
        "Malformed multipart archive: " + resource->Url().GetString(),
        FetchContext::kLogErrorMessage);
    return nullptr;
  }

  return archive_->MainResource();
}

ResourceTimingInfo* ResourceFetcher::GetNavigationTimingInfo() {
  return navigation_timing_info_.Get();
}

void ResourceFetcher::HandleLoadCompletion(Resource* resource) {
  Context().DidLoadResource(resource);

  resource->ReloadIfLoFiOrPlaceholderImage(this, Resource::kReloadIfNeeded);
}

void ResourceFetcher::HandleLoaderFinish(Resource* resource,
                                         double finish_time,
                                         LoaderFinishType type) {
  DCHECK(resource);

  ResourceLoader* loader = resource->Loader();
  if (type == kDidFinishFirstPartInMultipart) {
    // When loading a multipart resource, make the loader non-block when
    // finishing loading the first part.
    MoveResourceLoaderToNonBlocking(loader);
  } else {
    RemoveResourceLoader(loader);
    DCHECK(!non_blocking_loaders_.Contains(loader));
  }
  DCHECK(!loaders_.Contains(loader));

  const int64_t encoded_data_length =
      resource->GetResponse().EncodedDataLength();

  if (resource->GetType() == Resource::kMainResource) {
    DCHECK(navigation_timing_info_);
    // Store redirect responses that were packed inside the final response.
    AddRedirectsToTimingInfo(resource, navigation_timing_info_.Get());
    if (resource->GetResponse().IsHTTP()) {
      PopulateTimingInfo(navigation_timing_info_.Get(), resource);
      navigation_timing_info_->AddFinalTransferSize(
          encoded_data_length == -1 ? 0 : encoded_data_length);
    }
  }
  if (RefPtr<ResourceTimingInfo> info =
          resource_timing_info_map_.Take(resource)) {
    // Store redirect responses that were packed inside the final response.
    AddRedirectsToTimingInfo(resource, info.Get());

    if (resource->GetResponse().IsHTTP() &&
        resource->GetResponse().HttpStatusCode() < 400) {
      PopulateTimingInfo(info.Get(), resource);
      info->SetLoadFinishTime(finish_time);
      // encodedDataLength == -1 means "not available".
      // TODO(ricea): Find cases where it is not available but the
      // PerformanceResourceTiming spec requires it to be available and fix
      // them.
      info->AddFinalTransferSize(
          encoded_data_length == -1 ? 0 : encoded_data_length);

      if (resource->Options().request_initiator_context == kDocumentContext)
        Context().AddResourceTiming(*info);
      resource->ReportResourceTimingToClients(*info);
    }
  }

  Context().DispatchDidFinishLoading(
      resource->Identifier(), finish_time, encoded_data_length,
      resource->GetResponse().DecodedBodyLength());

  if (type == kDidFinishLoading)
    resource->Finish(finish_time);

  HandleLoadCompletion(resource);
}

void ResourceFetcher::HandleLoaderError(Resource* resource,
                                        const ResourceError& error) {
  DCHECK(resource);

  RemoveResourceLoader(resource->Loader());

  resource_timing_info_map_.Take(resource);

  bool is_internal_request = resource->Options().initiator_info.name ==
                             FetchInitiatorTypeNames::internal;

  Context().DispatchDidFail(resource->Identifier(), error,
                            resource->GetResponse().EncodedDataLength(),
                            is_internal_request);

  if (error.IsCancellation())
    RemovePreload(resource);
  resource->FinishAsError(error);

  HandleLoadCompletion(resource);
}

void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) {
  DCHECK(loader);
  // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in.
  CHECK(loaders_.Contains(loader));
  non_blocking_loaders_.insert(loader);
  loaders_.erase(loader);
}

bool ResourceFetcher::StartLoad(Resource* resource) {
  DCHECK(resource);
  DCHECK(resource->StillNeedsLoad());

  ResourceRequest request(resource->GetResourceRequest());
  ResourceLoader* loader = nullptr;

  {
    // Forbids JavaScript/revalidation until start()
    // to prevent unintended state transitions.
    Resource::RevalidationStartForbiddenScope
        revalidation_start_forbidden_scope(resource);
    ScriptForbiddenIfMainThreadScope script_forbidden_scope;

    if (!Context().ShouldLoadNewResource(resource->GetType()) &&
        IsMainThread()) {
      GetMemoryCache()->Remove(resource);
      return false;
    }

    ResourceResponse response;

    blink::probe::PlatformSendRequest probe(&Context(), resource->Identifier(),
                                            request, response,
                                            resource->Options().initiator_info);

    Context().DispatchWillSendRequest(resource->Identifier(), request, response,
                                      resource->Options().initiator_info);

    // Resource requests from suborigins should not be intercepted by the
    // service worker of the physical origin. This has the effect that, for now,
    // suborigins do not work with service workers. See
    // https://w3c.github.io/webappsec-suborigins/.
    SecurityOrigin* source_origin = Context().GetSecurityOrigin();
    if (source_origin && source_origin->HasSuborigin())
      request.SetServiceWorkerMode(WebURLRequest::ServiceWorkerMode::kNone);

    // TODO(shaochuan): Saving modified ResourceRequest back to |resource|,
    // remove once dispatchWillSendRequest() takes const ResourceRequest.
    // crbug.com/632580
    resource->SetResourceRequest(request);

    loader = ResourceLoader::Create(this, scheduler_, resource);
    if (resource->ShouldBlockLoadEvent())
      loaders_.insert(loader);
    else
      non_blocking_loaders_.insert(loader);

    StorePerformanceTimingInitiatorInformation(resource);
    resource->SetFetcherSecurityOrigin(source_origin);

    // NotifyStartLoad() shouldn't cause AddClient/RemoveClient().
    Resource::ProhibitAddRemoveClientInScope
        prohibit_add_remove_client_in_scope(resource);

    resource->NotifyStartLoad();
  }

  loader->Start();
  return true;
}

void ResourceFetcher::RemoveResourceLoader(ResourceLoader* loader) {
  DCHECK(loader);
  if (loaders_.Contains(loader))
    loaders_.erase(loader);
  else if (non_blocking_loaders_.Contains(loader))
    non_blocking_loaders_.erase(loader);
  else
    NOTREACHED();
}

void ResourceFetcher::StopFetching() {
  // TODO(toyoshim): May want to suspend scheduler while canceling loaders so
  // that the cancellations below do not awake unnecessary scheduling.

  HeapVector<Member<ResourceLoader>> loaders_to_cancel;
  for (const auto& loader : non_blocking_loaders_) {
    if (!loader->GetKeepalive())
      loaders_to_cancel.push_back(loader);
  }
  for (const auto& loader : loaders_) {
    if (!loader->GetKeepalive())
      loaders_to_cancel.push_back(loader);
  }

  for (const auto& loader : loaders_to_cancel) {
    if (loaders_.Contains(loader) || non_blocking_loaders_.Contains(loader))
      loader->Cancel();
  }
}

void ResourceFetcher::SetDefersLoading(bool defers) {
  for (const auto& loader : non_blocking_loaders_)
    loader->SetDefersLoading(defers);
  for (const auto& loader : loaders_)
    loader->SetDefersLoading(defers);
}

void ResourceFetcher::UpdateAllImageResourcePriorities() {
  TRACE_EVENT0(
      "blink",
      "ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities");
  for (const auto& document_resource : document_resources_) {
    Resource* resource = document_resource.value.Get();
    if (!resource || resource->GetType() != Resource::kImage ||
        !resource->IsLoading())
      continue;

    ResourcePriority resource_priority = resource->PriorityFromObservers();
    ResourceLoadPriority resource_load_priority =
        ComputeLoadPriority(Resource::kImage, resource->GetResourceRequest(),
                            resource_priority.visibility);
    if (resource_load_priority == resource->GetResourceRequest().Priority())
      continue;

    resource->DidChangePriority(resource_load_priority,
                                resource_priority.intra_priority_value);
    network_instrumentation::ResourcePrioritySet(resource->Identifier(),
                                                 resource_load_priority);
    Context().DispatchDidChangeResourcePriority(
        resource->Identifier(), resource_load_priority,
        resource_priority.intra_priority_value);
  }
}

void ResourceFetcher::ReloadLoFiImages() {
  for (const auto& document_resource : document_resources_) {
    Resource* resource = document_resource.value.Get();
    if (resource)
      resource->ReloadIfLoFiOrPlaceholderImage(this, Resource::kReloadAlways);
  }
}

void ResourceFetcher::LogPreloadStats(ClearPreloadsPolicy policy) {
  unsigned scripts = 0;
  unsigned script_misses = 0;
  unsigned stylesheets = 0;
  unsigned stylesheet_misses = 0;
  unsigned images = 0;
  unsigned image_misses = 0;
  unsigned fonts = 0;
  unsigned font_misses = 0;
  unsigned medias = 0;
  unsigned media_misses = 0;
  unsigned text_tracks = 0;
  unsigned text_track_misses = 0;
  unsigned imports = 0;
  unsigned import_misses = 0;
  unsigned raws = 0;
  unsigned raw_misses = 0;
  for (const auto& pair : preloads_) {
    Resource* resource = pair.value;
    // Do not double count link rel preloads. These do not get cleared if the
    // ClearPreloadsPolicy is only clearing speculative markup preloads.
    if (resource->IsLinkPreload() &&
        policy == kClearSpeculativeMarkupPreloads) {
      continue;
    }
    int miss_count = resource->IsUnusedPreload() ? 1 : 0;
    switch (resource->GetType()) {
      case Resource::kImage:
        images++;
        image_misses += miss_count;
        break;
      case Resource::kScript:
        scripts++;
        script_misses += miss_count;
        break;
      case Resource::kCSSStyleSheet:
        stylesheets++;
        stylesheet_misses += miss_count;
        break;
      case Resource::kFont:
        fonts++;
        font_misses += miss_count;
        break;
      case Resource::kMedia:
        medias++;
        media_misses += miss_count;
        break;
      case Resource::kTextTrack:
        text_tracks++;
        text_track_misses += miss_count;
        break;
      case Resource::kImportResource:
        imports++;
        import_misses += miss_count;
        break;
      case Resource::kRaw:
        raws++;
        raw_misses += miss_count;
        break;
      case Resource::kMock:
        // Do not count Resource::Mock because this type is only for testing.
        break;
      default:
        NOTREACHED();
    }
  }
  DEFINE_STATIC_LOCAL(CustomCountHistogram, image_preloads,
                      ("PreloadScanner.Counts2.Image", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, image_preload_misses,
                      ("PreloadScanner.Counts2.Miss.Image", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, script_preloads,
                      ("PreloadScanner.Counts2.Script", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, script_preload_misses,
                      ("PreloadScanner.Counts2.Miss.Script", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, stylesheet_preloads,
                      ("PreloadScanner.Counts2.CSSStyleSheet", 0, 100, 25));
  DEFINE_STATIC_LOCAL(
      CustomCountHistogram, stylesheet_preload_misses,
      ("PreloadScanner.Counts2.Miss.CSSStyleSheet", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, font_preloads,
                      ("PreloadScanner.Counts2.Font", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, font_preload_misses,
                      ("PreloadScanner.Counts2.Miss.Font", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, media_preloads,
                      ("PreloadScanner.Counts2.Media", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, media_preload_misses,
                      ("PreloadScanner.Counts2.Miss.Media", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, text_track_preloads,
                      ("PreloadScanner.Counts2.TextTrack", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, text_track_preload_misses,
                      ("PreloadScanner.Counts2.Miss.TextTrack", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, import_preloads,
                      ("PreloadScanner.Counts2.Import", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, import_preload_misses,
                      ("PreloadScanner.Counts2.Miss.Import", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, raw_preloads,
                      ("PreloadScanner.Counts2.Raw", 0, 100, 25));
  DEFINE_STATIC_LOCAL(CustomCountHistogram, raw_preload_misses,
                      ("PreloadScanner.Counts2.Miss.Raw", 0, 100, 25));
  if (images)
    image_preloads.Count(images);
  if (image_misses)
    image_preload_misses.Count(image_misses);
  if (scripts)
    script_preloads.Count(scripts);
  if (script_misses)
    script_preload_misses.Count(script_misses);
  if (stylesheets)
    stylesheet_preloads.Count(stylesheets);
  if (stylesheet_misses)
    stylesheet_preload_misses.Count(stylesheet_misses);
  if (fonts)
    font_preloads.Count(fonts);
  if (font_misses)
    font_preload_misses.Count(font_misses);
  if (medias)
    media_preloads.Count(medias);
  if (media_misses)
    media_preload_misses.Count(media_misses);
  if (text_tracks)
    text_track_preloads.Count(text_tracks);
  if (text_track_misses)
    text_track_preload_misses.Count(text_track_misses);
  if (imports)
    import_preloads.Count(imports);
  if (import_misses)
    import_preload_misses.Count(import_misses);
  if (raws)
    raw_preloads.Count(raws);
  if (raw_misses)
    raw_preload_misses.Count(raw_misses);
}

String ResourceFetcher::GetCacheIdentifier() const {
  if (Context().IsControlledByServiceWorker())
    return String::Number(Context().ServiceWorkerID());
  return MemoryCache::DefaultCacheIdentifier();
}

void ResourceFetcher::EmulateLoadStartedForInspector(
    Resource* resource,
    const KURL& url,
    WebURLRequest::RequestContext request_context,
    const AtomicString& initiator_name) {
  if (CachedResource(url))
    return;
  ResourceRequest resource_request(url);
  resource_request.SetRequestContext(request_context);
  ResourceLoaderOptions options = resource->Options();
  options.initiator_info.name = initiator_name;
  FetchParameters params(resource_request, options);
  Context().CanRequest(resource->GetType(), resource->LastResourceRequest(),
                       resource->LastResourceRequest().Url(), params.Options(),
                       SecurityViolationReportingPolicy::kReport,
                       params.GetOriginRestriction());
  RequestLoadStarted(resource->Identifier(), resource, params, kUse);
}

DEFINE_TRACE(ResourceFetcher) {
  visitor->Trace(context_);
  visitor->Trace(scheduler_);
  visitor->Trace(archive_);
  visitor->Trace(loaders_);
  visitor->Trace(non_blocking_loaders_);
  visitor->Trace(document_resources_);
  visitor->Trace(preloads_);
  visitor->Trace(matched_preloads_);
  visitor->Trace(resource_timing_info_map_);
}

}  // namespace blink
