/*
 * Copyright (C) 2013 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/FrameFetchContext.h"

#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/V8DOMActivityLogger.h"
#include "core/dom/Document.h"
#include "core/fetch/ClientHintsPreferences.h"
#include "core/fetch/FetchInitiatorTypeNames.h"
#include "core/fetch/Resource.h"
#include "core/fetch/ResourceLoadingLog.h"
#include "core/fetch/UniqueIdentifier.h"
#include "core/frame/Deprecation.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/imports/HTMLImportsController.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/IdentifiersFactory.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorNetworkAgent.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameClientHintsPreferencesContext.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/MixedContentChecker.h"
#include "core/loader/NetworkHintsInterface.h"
#include "core/loader/PingLoader.h"
#include "core/loader/ProgressTracker.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
#include "core/page/NetworkStateNotifier.h"
#include "core/page/Page.h"
#include "core/paint/FirstMeaningfulPaintDetector.h"
#include "core/svg/graphics/SVGImageChromeClient.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "platform/WebFrameScheduler.h"
#include "platform/instrumentation/tracing/TracedValue.h"
#include "platform/mhtml/MHTMLArchive.h"
#include "platform/network/NetworkUtils.h"
#include "platform/network/ResourceLoadPriority.h"
#include "platform/network/ResourceTimingInfo.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "public/platform/WebCachePolicy.h"
#include "public/platform/WebDocumentSubresourceFilter.h"
#include "public/platform/WebInsecureRequestPolicy.h"
#include "public/platform/WebViewScheduler.h"
#include "wtf/Vector.h"
#include <algorithm>
#include <memory>

namespace blink {

namespace {

void emitWarningForDocWriteScripts(const String& url, Document& document) {
  String message = "A Parser-blocking, cross-origin script, " + url +
                   ", is invoked via document.write. This may be blocked by "
                   "the browser if the device has poor network connectivity. "
                   "See https://www.chromestatus.com/feature/5718547946799104 "
                   "for more details.";
  document.addConsoleMessage(
      ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message));
  WTFLogAlways("%s", message.utf8().data());
}

bool isConnectionEffectively2G(WebEffectiveConnectionType effectiveType) {
  switch (effectiveType) {
    case WebEffectiveConnectionType::TypeSlow2G:
    case WebEffectiveConnectionType::Type2G:
      return true;
    case WebEffectiveConnectionType::Type3G:
    case WebEffectiveConnectionType::Type4G:
    case WebEffectiveConnectionType::TypeUnknown:
    case WebEffectiveConnectionType::TypeOffline:
      return false;
  }
  NOTREACHED();
  return false;
}

bool shouldDisallowFetchForMainFrameScript(ResourceRequest& request,
                                           FetchRequest::DeferOption defer,
                                           Document& document) {
  // Only scripts inserted via document.write are candidates for having their
  // fetch disallowed.
  if (!document.isInDocumentWrite())
    return false;

  if (!document.settings())
    return false;

  if (!document.frame())
    return false;

  // Only block synchronously loaded (parser blocking) scripts.
  if (defer != FetchRequest::NoDefer)
    return false;

  PerformanceMonitor::documentWriteFetchScript(&document);

  if (!request.url().protocolIsInHTTPFamily())
    return false;

  // Avoid blocking same origin scripts, as they may be used to render main
  // page content, whereas cross-origin scripts inserted via document.write
  // are likely to be third party content.
  String requestHost = request.url().host();
  String documentHost = document.getSecurityOrigin()->domain();
  if (requestHost == documentHost)
    return false;

  // If the hosts didn't match, then see if the domains match. For example, if
  // a script is served from static.example.com for a document served from
  // www.example.com, we consider that a first party script and allow it.
  String requestDomain = NetworkUtils::getDomainAndRegistry(
      requestHost, NetworkUtils::IncludePrivateRegistries);
  String documentDomain = NetworkUtils::getDomainAndRegistry(
      documentHost, NetworkUtils::IncludePrivateRegistries);
  // getDomainAndRegistry will return the empty string for domains that are
  // already top-level, such as localhost. Thus we only compare domains if we
  // get non-empty results back from getDomainAndRegistry.
  if (!requestDomain.isEmpty() && !documentDomain.isEmpty() &&
      requestDomain == documentDomain)
    return false;

  emitWarningForDocWriteScripts(request.url().getString(), document);
  request.setHTTPHeaderField("Intervention",
                             "<https://www.chromestatus.com/feature/"
                             "5718547946799104>; level=\"warning\"");

  // Do not block scripts if it is a page reload. This is to enable pages to
  // recover if blocking of a script is leading to a page break and the user
  // reloads the page.
  const FrameLoadType loadType = document.frame()->loader().loadType();
  if (isReloadLoadType(loadType)) {
    // Recording this metric since an increase in number of reloads for pages
    // where a script was blocked could be indicative of a page break.
    document.loader()->didObserveLoadingBehavior(
        WebLoadingBehaviorFlag::WebLoadingBehaviorDocumentWriteBlockReload);
    return false;
  }

  // Add the metadata that this page has scripts inserted via document.write
  // that are eligible for blocking. Note that if there are multiple scripts
  // the flag will be conveyed to the browser process only once.
  document.loader()->didObserveLoadingBehavior(
      WebLoadingBehaviorFlag::WebLoadingBehaviorDocumentWriteBlock);

  const bool is2G =
      networkStateNotifier().connectionType() == WebConnectionTypeCellular2G;
  WebEffectiveConnectionType effectiveConnection =
      document.frame()->client()->getEffectiveConnectionType();

  return document.settings()
             ->getDisallowFetchForDocWrittenScriptsInMainFrame() ||
         (document.settings()
              ->getDisallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections() &&
          is2G) ||
         (document.settings()
              ->getDisallowFetchForDocWrittenScriptsInMainFrameIfEffectively2G() &&
          isConnectionEffectively2G(effectiveConnection));
}

}  // namespace

FrameFetchContext::FrameFetchContext(DocumentLoader* loader, Document* document)
    : m_document(document), m_documentLoader(loader) {
  DCHECK(frame());
}

FrameFetchContext::~FrameFetchContext() {
  m_document = nullptr;
  m_documentLoader = nullptr;
}

LocalFrame* FrameFetchContext::frameOfImportsController() const {
  DCHECK(m_document);
  HTMLImportsController* importsController = m_document->importsController();
  DCHECK(importsController);
  LocalFrame* frame = importsController->master()->frame();
  DCHECK(frame);
  return frame;
}

LocalFrame* FrameFetchContext::frame() const {
  if (!m_documentLoader)
    return frameOfImportsController();

  LocalFrame* frame = m_documentLoader->frame();
  DCHECK(frame);
  return frame;
}

FrameLoaderClient* FrameFetchContext::frameLoaderClient() const {
  return frame()->client();
}

void FrameFetchContext::addAdditionalRequestHeaders(ResourceRequest& request,
                                                    FetchResourceType type) {
  bool isMainResource = type == FetchMainResource;
  if (!isMainResource) {
    if (!request.didSetHTTPReferrer()) {
      DCHECK(m_document);
      request.setHTTPReferrer(SecurityPolicy::generateReferrer(
          m_document->getReferrerPolicy(), request.url(),
          m_document->outgoingReferrer()));
      request.addHTTPOriginIfNeeded(m_document->getSecurityOrigin());
    } else {
      CHECK_EQ(SecurityPolicy::generateReferrer(request.getReferrerPolicy(),
                                                request.url(),
                                                request.httpReferrer())
                   .referrer,
               request.httpReferrer());
      request.addHTTPOriginIfNeeded(request.httpReferrer());
    }
  }

  if (m_document) {
    request.setExternalRequestStateFromRequestorAddressSpace(
        m_document->addressSpace());
  }

  // The remaining modifications are only necessary for HTTP and HTTPS.
  if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
    return;

  if (frame()->loader().loadType() == FrameLoadTypeReload)
    request.clearHTTPHeaderField("Save-Data");

  if (frame()->settings() && frame()->settings()->getDataSaverEnabled())
    request.setHTTPHeaderField("Save-Data", "on");
}

CachePolicy FrameFetchContext::getCachePolicy() const {
  if (m_document && m_document->loadEventFinished())
    return CachePolicyVerify;

  FrameLoadType loadType = frame()->loader().loadType();
  if (loadType == FrameLoadTypeReloadBypassingCache)
    return CachePolicyReload;

  Frame* parentFrame = frame()->tree().parent();
  if (parentFrame && parentFrame->isLocalFrame()) {
    CachePolicy parentCachePolicy = toLocalFrame(parentFrame)
                                        ->document()
                                        ->fetcher()
                                        ->context()
                                        .getCachePolicy();
    if (parentCachePolicy != CachePolicyVerify)
      return parentCachePolicy;
  }

  if (loadType == FrameLoadTypeReload)
    return CachePolicyRevalidate;

  if (m_documentLoader &&
      m_documentLoader->getRequest().getCachePolicy() ==
          WebCachePolicy::ReturnCacheDataElseLoad)
    return CachePolicyHistoryBuffer;

  // Returns CachePolicyVerify for other cases, mainly FrameLoadTypeStandard and
  // FrameLoadTypeReloadMainResource. See public/web/WebFrameLoadType.h to know
  // how these load types work.
  return CachePolicyVerify;
}

static WebCachePolicy memoryCachePolicyToResourceRequestCachePolicy(
    const CachePolicy policy) {
  if (policy == CachePolicyVerify)
    return WebCachePolicy::UseProtocolCachePolicy;
  if (policy == CachePolicyRevalidate)
    return WebCachePolicy::ValidatingCacheData;
  if (policy == CachePolicyReload)
    return WebCachePolicy::BypassingCache;
  if (policy == CachePolicyHistoryBuffer)
    return WebCachePolicy::ReturnCacheDataElseLoad;
  return WebCachePolicy::UseProtocolCachePolicy;
}

WebCachePolicy FrameFetchContext::resourceRequestCachePolicy(
    ResourceRequest& request,
    Resource::Type type,
    FetchRequest::DeferOption defer) const {
  DCHECK(frame());
  if (type == Resource::MainResource) {
    FrameLoadType frameLoadType = frame()->loader().loadType();
    if (request.httpMethod() == "POST" &&
        frameLoadType == FrameLoadTypeBackForward)
      return WebCachePolicy::ReturnCacheDataDontLoad;
    if (frameLoadType == FrameLoadTypeReloadMainResource ||
        request.isConditional() || request.httpMethod() == "POST")
      return WebCachePolicy::ValidatingCacheData;

    for (Frame* f = frame(); f; f = f->tree().parent()) {
      if (!f->isLocalFrame())
        continue;
      FrameLoadType parentFrameLoadType = toLocalFrame(f)->loader().loadType();
      if (parentFrameLoadType == FrameLoadTypeBackForward)
        return WebCachePolicy::ReturnCacheDataElseLoad;
      if (parentFrameLoadType == FrameLoadTypeReloadBypassingCache)
        return WebCachePolicy::BypassingCache;
      if (parentFrameLoadType == FrameLoadTypeReload)
        return WebCachePolicy::ValidatingCacheData;
    }
    // Returns UseProtocolCachePolicy for other cases, parent frames not having
    // special kinds of FrameLoadType as they are checked inside the for loop
    // above, or |frameLoadType| being FrameLoadTypeStandard. See
    // public/web/WebFrameLoadType.h to know how these load types work.
    return WebCachePolicy::UseProtocolCachePolicy;
  }

  // For users on slow connections, we want to avoid blocking the parser in
  // the main frame on script loads inserted via document.write, since it can
  // add significant delays before page content is displayed on the screen.
  if (type == Resource::Script && isMainFrame() && m_document &&
      shouldDisallowFetchForMainFrameScript(request, defer, *m_document))
    return WebCachePolicy::ReturnCacheDataDontLoad;

  if (request.isConditional())
    return WebCachePolicy::ValidatingCacheData;

  if (m_documentLoader && m_document && !m_document->loadEventFinished()) {
    // For POST requests, we mutate the main resource's cache policy to avoid
    // form resubmission. This policy should not be inherited by subresources.
    WebCachePolicy mainResourceCachePolicy =
        m_documentLoader->getRequest().getCachePolicy();
    if (m_documentLoader->getRequest().httpMethod() == "POST") {
      if (mainResourceCachePolicy == WebCachePolicy::ReturnCacheDataDontLoad)
        return WebCachePolicy::ReturnCacheDataElseLoad;
      return WebCachePolicy::UseProtocolCachePolicy;
    }
    return memoryCachePolicyToResourceRequestCachePolicy(getCachePolicy());
  }
  return WebCachePolicy::UseProtocolCachePolicy;
}

// The |m_documentLoader| is null in the FrameFetchContext of an imported
// document.
// FIXME(http://crbug.com/274173): This means Inspector, which uses
// DocumentLoader as a grouping entity, cannot see imported documents.
inline DocumentLoader* FrameFetchContext::masterDocumentLoader() const {
  if (m_documentLoader)
    return m_documentLoader.get();

  return frameOfImportsController()->loader().documentLoader();
}

void FrameFetchContext::dispatchDidChangeResourcePriority(
    unsigned long identifier,
    ResourceLoadPriority loadPriority,
    int intraPriorityValue) {
  TRACE_EVENT1(
      "devtools.timeline", "ResourceChangePriority", "data",
      InspectorChangeResourcePriorityEvent::data(identifier, loadPriority));
  InspectorInstrumentation::didChangeResourcePriority(frame(), identifier,
                                                      loadPriority);
}

void FrameFetchContext::prepareRequest(ResourceRequest& request) {
  frame()->loader().applyUserAgent(request);
  frameLoaderClient()->dispatchWillSendRequest(request);
}

void FrameFetchContext::dispatchWillSendRequest(
    unsigned long identifier,
    ResourceRequest& request,
    const ResourceResponse& redirectResponse,
    const FetchInitiatorInfo& initiatorInfo) {
  TRACE_EVENT1("devtools.timeline", "ResourceSendRequest", "data",
               InspectorSendRequestEvent::data(identifier, frame(), request));
  // For initial requests, prepareRequest() is called in
  // willStartLoadingResource(), before revalidation policy is determined. That
  // call doesn't exist for redirects, so call preareRequest() here.
  if (!redirectResponse.isNull()) {
    prepareRequest(request);
  } else {
    frame()->loader().progress().willStartLoading(identifier,
                                                  request.priority());
  }
  InspectorInstrumentation::willSendRequest(frame(), identifier,
                                            masterDocumentLoader(), request,
                                            redirectResponse, initiatorInfo);
  if (frame()->frameScheduler())
    frame()->frameScheduler()->didStartLoading(identifier);
}

void FrameFetchContext::dispatchDidReceiveResponse(
    unsigned long identifier,
    const ResourceResponse& response,
    WebURLRequest::FrameType frameType,
    WebURLRequest::RequestContext requestContext,
    Resource* resource) {
  dispatchDidReceiveResponseInternal(identifier, response, frameType,
                                     requestContext, resource,
                                     LinkLoader::LoadResourcesAndPreconnect);
}

void FrameFetchContext::dispatchDidReceiveData(unsigned long identifier,
                                               const char* data,
                                               int dataLength) {
  frame()->loader().progress().incrementProgress(identifier, dataLength);
  InspectorInstrumentation::didReceiveData(frame(), identifier, data,
                                           dataLength);
}

void FrameFetchContext::dispatchDidReceiveEncodedData(unsigned long identifier,
                                                      int encodedDataLength) {
  TRACE_EVENT1(
      "devtools.timeline", "ResourceReceivedData", "data",
      InspectorReceiveDataEvent::data(identifier, frame(), encodedDataLength));
  InspectorInstrumentation::didReceiveEncodedDataLength(frame(), identifier,
                                                        encodedDataLength);
}

void FrameFetchContext::dispatchDidDownloadData(unsigned long identifier,
                                                int dataLength,
                                                int encodedDataLength) {
  TRACE_EVENT1(
      "devtools.timeline", "ResourceReceivedData", "data",
      InspectorReceiveDataEvent::data(identifier, frame(), encodedDataLength));
  frame()->loader().progress().incrementProgress(identifier, dataLength);
  InspectorInstrumentation::didReceiveData(frame(), identifier, 0, dataLength);
  InspectorInstrumentation::didReceiveEncodedDataLength(frame(), identifier,
                                                        encodedDataLength);
}

void FrameFetchContext::dispatchDidFinishLoading(unsigned long identifier,
                                                 double finishTime,
                                                 int64_t encodedDataLength) {
  TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
               InspectorResourceFinishEvent::data(identifier, finishTime, false,
                                                  encodedDataLength));
  frame()->loader().progress().completeProgress(identifier);
  InspectorInstrumentation::didFinishLoading(frame(), identifier, finishTime,
                                             encodedDataLength);
  if (frame()->frameScheduler())
    frame()->frameScheduler()->didStopLoading(identifier);
}

void FrameFetchContext::dispatchDidFail(unsigned long identifier,
                                        const ResourceError& error,
                                        int64_t encodedDataLength,
                                        bool isInternalRequest) {
  TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
               InspectorResourceFinishEvent::data(identifier, 0, true,
                                                  encodedDataLength));
  frame()->loader().progress().completeProgress(identifier);
  InspectorInstrumentation::didFailLoading(frame(), identifier, error);
  // Notification to FrameConsole should come AFTER InspectorInstrumentation
  // call, DevTools front-end relies on this.
  if (!isInternalRequest)
    frame()->console().didFailLoading(identifier, error);
  if (frame()->frameScheduler())
    frame()->frameScheduler()->didStopLoading(identifier);
}

void FrameFetchContext::dispatchDidLoadResourceFromMemoryCache(
    unsigned long identifier,
    Resource* resource,
    WebURLRequest::FrameType frameType,
    WebURLRequest::RequestContext requestContext) {
  ResourceRequest request(resource->url());
  request.setFrameType(frameType);
  request.setRequestContext(requestContext);
  frameLoaderClient()->dispatchDidLoadResourceFromMemoryCache(
      request, resource->response());
  dispatchWillSendRequest(identifier, request, ResourceResponse(),
                          resource->options().initiatorInfo);

  InspectorInstrumentation::markResourceAsCached(frame(), identifier);
  if (!resource->response().isNull()) {
    dispatchDidReceiveResponseInternal(identifier, resource->response(),
                                       frameType, requestContext, resource,
                                       LinkLoader::DoNotLoadResources);
  }

  if (resource->encodedSize() > 0)
    dispatchDidReceiveData(identifier, 0, resource->encodedSize());

  dispatchDidFinishLoading(identifier, 0, 0);
}

bool FrameFetchContext::shouldLoadNewResource(Resource::Type type) const {
  if (!m_documentLoader)
    return true;

  FrameLoader& loader = m_documentLoader->frame()->loader();
  if (type == Resource::MainResource)
    return m_documentLoader == loader.provisionalDocumentLoader();
  return m_documentLoader == loader.documentLoader();
}

static std::unique_ptr<TracedValue>
loadResourceTraceData(unsigned long identifier, const KURL& url, int priority) {
  String requestId = IdentifiersFactory::requestId(identifier);

  std::unique_ptr<TracedValue> value = TracedValue::create();
  value->setString("requestId", requestId);
  value->setString("url", url.getString());
  value->setInteger("priority", priority);
  return value;
}

void FrameFetchContext::willStartLoadingResource(
    unsigned long identifier,
    ResourceRequest& request,
    Resource::Type type,
    const AtomicString& fetchInitiatorName,
    bool forPreload) {
  TRACE_EVENT_ASYNC_BEGIN1(
      "blink.net", "Resource", identifier, "data",
      loadResourceTraceData(identifier, request.url(), request.priority()));
  prepareRequest(request);

  if (!m_documentLoader || m_documentLoader->fetcher()->archive() ||
      !request.url().isValid())
    return;
  if (type == Resource::MainResource) {
    m_documentLoader->applicationCacheHost()->willStartLoadingMainResource(
        request);
  } else {
    m_documentLoader->applicationCacheHost()->willStartLoadingResource(request);
  }
  if (!forPreload) {
    V8DOMActivityLogger* activityLogger = nullptr;
    if (fetchInitiatorName == FetchInitiatorTypeNames::xmlhttprequest) {
      activityLogger = V8DOMActivityLogger::currentActivityLogger();
    } else {
      activityLogger =
          V8DOMActivityLogger::currentActivityLoggerIfIsolatedWorld();
    }

    if (activityLogger) {
      Vector<String> argv;
      argv.push_back(Resource::resourceTypeToString(type, fetchInitiatorName));
      argv.push_back(request.url());
      activityLogger->logEvent("blinkRequestResource", argv.size(),
                               argv.data());
    }
  }
}

void FrameFetchContext::didLoadResource(Resource* resource) {
  if (resource->isLoadEventBlockingResourceType())
    frame()->loader().checkCompleted();
  if (m_document)
    FirstMeaningfulPaintDetector::from(*m_document).checkNetworkStable();
}

void FrameFetchContext::addResourceTiming(const ResourceTimingInfo& info) {
  Document* initiatorDocument = m_document && info.isMainResource()
                                    ? m_document->parentDocument()
                                    : m_document.get();
  if (!initiatorDocument || !initiatorDocument->domWindow())
    return;
  DOMWindowPerformance::performance(*initiatorDocument->domWindow())
      ->addResourceTiming(info);
}

bool FrameFetchContext::allowImage(bool imagesEnabled, const KURL& url) const {
  return frameLoaderClient()->allowImage(imagesEnabled, url);
}

void FrameFetchContext::printAccessDeniedMessage(const KURL& url) const {
  if (url.isNull())
    return;

  String message;
  if (!m_document || m_document->url().isNull()) {
    message = "Unsafe attempt to load URL " + url.elidedString() + '.';
  } else if (url.isLocalFile() || m_document->url().isLocalFile()) {
    message = "Unsafe attempt to load URL " + url.elidedString() +
              " from frame with URL " + m_document->url().elidedString() +
              ". 'file:' URLs are treated as unique security origins.\n";
  } else {
    message = "Unsafe attempt to load URL " + url.elidedString() +
              " from frame with URL " + m_document->url().elidedString() +
              ". Domains, protocols and ports must match.\n";
  }

  frame()->document()->addConsoleMessage(ConsoleMessage::create(
      SecurityMessageSource, ErrorMessageLevel, message));
}

ResourceRequestBlockedReason FrameFetchContext::canRequest(
    Resource::Type type,
    const ResourceRequest& resourceRequest,
    const KURL& url,
    const ResourceLoaderOptions& options,
    bool forPreload,
    FetchRequest::OriginRestriction originRestriction) const {
  ResourceRequestBlockedReason blockedReason =
      canRequestInternal(type, resourceRequest, url, options, forPreload,
                         originRestriction, resourceRequest.redirectStatus());
  if (blockedReason != ResourceRequestBlockedReason::None && !forPreload) {
    InspectorInstrumentation::didBlockRequest(
        frame(), resourceRequest, masterDocumentLoader(), options.initiatorInfo,
        blockedReason);
  }
  return blockedReason;
}

ResourceRequestBlockedReason FrameFetchContext::allowResponse(
    Resource::Type type,
    const ResourceRequest& resourceRequest,
    const KURL& url,
    const ResourceLoaderOptions& options) const {
  ResourceRequestBlockedReason blockedReason =
      canRequestInternal(type, resourceRequest, url, options, false,
                         FetchRequest::UseDefaultOriginRestrictionForType,
                         RedirectStatus::FollowedRedirect);
  if (blockedReason != ResourceRequestBlockedReason::None) {
    InspectorInstrumentation::didBlockRequest(
        frame(), resourceRequest, masterDocumentLoader(), options.initiatorInfo,
        blockedReason);
  }
  return blockedReason;
}

ResourceRequestBlockedReason FrameFetchContext::canRequestInternal(
    Resource::Type type,
    const ResourceRequest& resourceRequest,
    const KURL& url,
    const ResourceLoaderOptions& options,
    bool forPreload,
    FetchRequest::OriginRestriction originRestriction,
    ResourceRequest::RedirectStatus redirectStatus) const {
  if (InspectorInstrumentation::shouldBlockRequest(frame(), resourceRequest))
    return ResourceRequestBlockedReason::Inspector;

  SecurityOrigin* securityOrigin = options.securityOrigin.get();
  if (!securityOrigin && m_document)
    securityOrigin = m_document->getSecurityOrigin();

  if (originRestriction != FetchRequest::NoOriginRestriction &&
      securityOrigin && !securityOrigin->canDisplay(url)) {
    if (!forPreload)
      FrameLoader::reportLocalLoadFailed(frame(), url.elidedString());
    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::requestResource URL was not "
                                 "allowed by SecurityOrigin::canDisplay";
    return ResourceRequestBlockedReason::Other;
  }

  // Some types of resources can be loaded only from the same origin. Other
  // types of resources, like Images, Scripts, and CSS, can be loaded from
  // any URL.
  switch (type) {
    case Resource::MainResource:
    case Resource::Image:
    case Resource::CSSStyleSheet:
    case Resource::Script:
    case Resource::Font:
    case Resource::Raw:
    case Resource::LinkPrefetch:
    case Resource::TextTrack:
    case Resource::ImportResource:
    case Resource::Media:
    case Resource::Manifest:
    case Resource::Mock:
      // By default these types of resources can be loaded from any origin.
      // FIXME: Are we sure about Resource::Font?
      if (originRestriction == FetchRequest::RestrictToSameOrigin &&
          !securityOrigin->canRequest(url)) {
        printAccessDeniedMessage(url);
        return ResourceRequestBlockedReason::Origin;
      }
      break;
    case Resource::XSLStyleSheet:
      DCHECK(RuntimeEnabledFeatures::xsltEnabled());
    case Resource::SVGDocument:
      if (!securityOrigin->canRequest(url)) {
        printAccessDeniedMessage(url);
        return ResourceRequestBlockedReason::Origin;
      }
      break;
  }

  // FIXME: Convert this to check the isolated world's Content Security Policy
  // once webkit.org/b/104520 is solved.
  bool shouldBypassMainWorldCSP =
      frame()->script().shouldBypassMainWorldCSP() ||
      options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy;

  // Don't send CSP messages for preloads, we might never actually display those
  // items.
  ContentSecurityPolicy::ReportingStatus cspReporting =
      forPreload ? ContentSecurityPolicy::SuppressReport
                 : ContentSecurityPolicy::SendReport;

  if (m_document) {
    DCHECK(m_document->contentSecurityPolicy());
    if (!shouldBypassMainWorldCSP &&
        !m_document->contentSecurityPolicy()->allowRequest(
            resourceRequest.requestContext(), url,
            options.contentSecurityPolicyNonce, options.integrityMetadata,
            options.parserDisposition, redirectStatus, cspReporting))
      return ResourceRequestBlockedReason::CSP;
  }

  if (type == Resource::Script || type == Resource::ImportResource) {
    DCHECK(frame());
    if (!frameLoaderClient()->allowScriptFromSource(
            !frame()->settings() || frame()->settings()->getScriptEnabled(),
            url)) {
      frameLoaderClient()->didNotAllowScript();
      // TODO(estark): Use a different ResourceRequestBlockedReason here, since
      // this check has nothing to do with CSP. https://crbug.com/600795
      return ResourceRequestBlockedReason::CSP;
    }
  } else if (type == Resource::Media || type == Resource::TextTrack) {
    DCHECK(frame());
    if (!frameLoaderClient()->allowMedia(url))
      return ResourceRequestBlockedReason::Other;
  }

  // SVG Images have unique security rules that prevent all subresource requests
  // except for data urls.
  if (type != Resource::MainResource &&
      frame()->chromeClient().isSVGImageChromeClient() && !url.protocolIsData())
    return ResourceRequestBlockedReason::Origin;

  // Measure the number of legacy URL schemes ('ftp://') and the number of
  // embedded-credential ('http://user:password@...') resources embedded as
  // subresources. in the hopes that we can block them at some point in the
  // future.
  if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) {
    DCHECK(frame()->document());
    if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) &&
        !SchemeRegistry::shouldTreatURLSchemeAsLegacy(
            frame()->document()->getSecurityOrigin()->protocol())) {
      Deprecation::countDeprecation(
          frame()->document(), UseCounter::LegacyProtocolEmbeddedAsSubresource);
    }
    if (!url.user().isEmpty() || !url.pass().isEmpty()) {
      Deprecation::countDeprecation(
          frame()->document(),
          UseCounter::RequestedSubresourceWithEmbeddedCredentials);
    }
  }

  // Check for mixed content. We do this second-to-last so that when folks block
  // mixed content with a CSP policy, they don't get a warning. They'll still
  // get a warning in the console about CSP blocking the load.
  MixedContentChecker::ReportingStatus mixedContentReporting =
      forPreload ? MixedContentChecker::SuppressReport
                 : MixedContentChecker::SendReport;
  if (MixedContentChecker::shouldBlockFetch(frame(), resourceRequest, url,
                                            mixedContentReporting))
    return ResourceRequestBlockedReason::MixedContent;

  // Let the client have the final say into whether or not the load should
  // proceed.
  DocumentLoader* documentLoader = masterDocumentLoader();
  if (documentLoader && documentLoader->subresourceFilter() &&
      type != Resource::MainResource && type != Resource::ImportResource &&
      !documentLoader->subresourceFilter()->allowLoad(
          url, resourceRequest.requestContext()))
    return ResourceRequestBlockedReason::SubresourceFilter;

  return ResourceRequestBlockedReason::None;
}

bool FrameFetchContext::isControlledByServiceWorker() const {
  DCHECK(m_documentLoader || frame()->loader().documentLoader());

  // Service workers are bypassed by suborigins (see
  // https://w3c.github.io/webappsec-suborigins/). Since service worker
  // controllers are assigned based on physical origin, without knowledge of
  // whether the context is in a suborigin, it is necessary to explicitly bypass
  // service workers on a per-request basis. Additionally, it is necessary to
  // explicitly return |false| here so that it is clear that the SW will be
  // bypassed. In particular, this is important for
  // ResourceFetcher::getCacheIdentifier(), which will return the SW's cache if
  // the context's isControlledByServiceWorker() returns |true|, and thus will
  // returned cached resources from the service worker. That would have the
  // effect of not bypassing the SW.
  if (getSecurityOrigin() && getSecurityOrigin()->hasSuborigin())
    return false;

  if (m_documentLoader) {
    return m_documentLoader->frame()
        ->loader()
        .client()
        ->isControlledByServiceWorker(*m_documentLoader);
  }
  // m_documentLoader is null while loading resources from an HTML import. In
  // such cases whether the request is controlled by ServiceWorker or not is
  // determined by the document loader of the frame.
  return frameLoaderClient()->isControlledByServiceWorker(
      *frame()->loader().documentLoader());
}

int64_t FrameFetchContext::serviceWorkerID() const {
  DCHECK(m_documentLoader || frame()->loader().documentLoader());
  if (m_documentLoader) {
    return m_documentLoader->frame()->client()->serviceWorkerID(
        *m_documentLoader);
  }
  // m_documentLoader is null while loading resources from an HTML import.
  // In such cases a service worker ID could be retrieved from the document
  // loader of the frame.
  return frameLoaderClient()->serviceWorkerID(
      *frame()->loader().documentLoader());
}

bool FrameFetchContext::isMainFrame() const {
  return frame()->isMainFrame();
}

bool FrameFetchContext::defersLoading() const {
  return frame()->page()->suspended();
}

bool FrameFetchContext::isLoadComplete() const {
  return m_document && m_document->loadEventFinished();
}

bool FrameFetchContext::pageDismissalEventBeingDispatched() const {
  return m_document &&
         m_document->pageDismissalEventBeingDispatched() !=
             Document::NoDismissal;
}

bool FrameFetchContext::updateTimingInfoForIFrameNavigation(
    ResourceTimingInfo* info) {
  // <iframe>s should report the initial navigation requested by the parent
  // document, but not subsequent navigations.
  // FIXME: Resource timing is broken when the parent is a remote frame.
  if (!frame()->deprecatedLocalOwner() ||
      frame()->deprecatedLocalOwner()->loadedNonEmptyDocument())
    return false;
  frame()->deprecatedLocalOwner()->didLoadNonEmptyDocument();
  // Do not report iframe navigation that restored from history, since its
  // location may have been changed after initial navigation.
  if (frame()->loader().loadType() == FrameLoadTypeInitialHistoryLoad)
    return false;
  info->setInitiatorType(frame()->deprecatedLocalOwner()->localName());
  return true;
}

void FrameFetchContext::sendImagePing(const KURL& url) {
  PingLoader::loadImage(frame(), url);
}

void FrameFetchContext::addConsoleMessage(const String& message,
                                          LogMessageType messageType) const {
  MessageLevel level = messageType == LogWarningMessage ? WarningMessageLevel
                                                        : ErrorMessageLevel;
  if (frame()->document()) {
    frame()->document()->addConsoleMessage(
        ConsoleMessage::create(JSMessageSource, level, message));
  }
}

SecurityOrigin* FrameFetchContext::getSecurityOrigin() const {
  return m_document ? m_document->getSecurityOrigin() : nullptr;
}

void FrameFetchContext::modifyRequestForCSP(ResourceRequest& resourceRequest) {
  // Record the latest requiredCSP value that will be used when sending this
  // request.
  frame()->loader().recordLatestRequiredCSP();
  frame()->loader().modifyRequestForCSP(resourceRequest, m_document);
}

void FrameFetchContext::addClientHintsIfNecessary(
    const ClientHintsPreferences& hintsPreferences,
    const FetchRequest::ResourceWidth& resourceWidth,
    ResourceRequest& request) {
  if (!RuntimeEnabledFeatures::clientHintsEnabled() || !m_document)
    return;

  bool shouldSendDPR = m_document->clientHintsPreferences().shouldSendDPR() ||
                       hintsPreferences.shouldSendDPR();
  bool shouldSendResourceWidth =
      m_document->clientHintsPreferences().shouldSendResourceWidth() ||
      hintsPreferences.shouldSendResourceWidth();
  bool shouldSendViewportWidth =
      m_document->clientHintsPreferences().shouldSendViewportWidth() ||
      hintsPreferences.shouldSendViewportWidth();

  if (shouldSendDPR) {
    request.addHTTPHeaderField(
        "DPR", AtomicString(String::number(m_document->devicePixelRatio())));
  }

  if (shouldSendResourceWidth) {
    if (resourceWidth.isSet) {
      float physicalWidth =
          resourceWidth.width * m_document->devicePixelRatio();
      request.addHTTPHeaderField(
          "Width", AtomicString(String::number(ceil(physicalWidth))));
    }
  }

  if (shouldSendViewportWidth && frame()->view()) {
    request.addHTTPHeaderField(
        "Viewport-Width",
        AtomicString(String::number(frame()->view()->viewportWidth())));
  }
}

void FrameFetchContext::addCSPHeaderIfNecessary(Resource::Type type,
                                                ResourceRequest& request) {
  if (!m_document)
    return;

  const ContentSecurityPolicy* csp = m_document->contentSecurityPolicy();
  if (csp->shouldSendCSPHeader(type))
    request.addHTTPHeaderField("CSP", "active");
}

void FrameFetchContext::populateResourceRequest(
    Resource::Type type,
    const ClientHintsPreferences& hintsPreferences,
    const FetchRequest::ResourceWidth& resourceWidth,
    ResourceRequest& request) {
  setFirstPartyCookieAndRequestorOrigin(request);
  modifyRequestForCSP(request);
  addClientHintsIfNecessary(hintsPreferences, resourceWidth, request);
  addCSPHeaderIfNecessary(type, request);
}

void FrameFetchContext::setFirstPartyCookieAndRequestorOrigin(
    ResourceRequest& request) {
  if (!m_document)
    return;

  if (request.firstPartyForCookies().isNull()) {
    request.setFirstPartyForCookies(
        m_document ? m_document->firstPartyForCookies()
                   : SecurityOrigin::urlWithUniqueSecurityOrigin());
  }

  // Subresource requests inherit their requestor origin from |m_document|
  // directly. Top-level and nested frame types are taken care of in
  // 'FrameLoadRequest()'. Auxiliary frame types in 'createWindow()' and
  // 'FrameLoader::load'.
  // TODO(mkwst): It would be cleaner to adjust blink::ResourceRequest to
  // initialize itself with a `nullptr` initiator so that this can be a simple
  // `isNull()` check. https://crbug.com/625969
  if (request.frameType() == WebURLRequest::FrameTypeNone &&
      request.requestorOrigin()->isUnique()) {
    request.setRequestorOrigin(m_document->isSandboxed(SandboxOrigin)
                                   ? SecurityOrigin::create(m_document->url())
                                   : m_document->getSecurityOrigin());
  }
}

MHTMLArchive* FrameFetchContext::archive() const {
  DCHECK(!isMainFrame());
  // TODO(nasko): How should this work with OOPIF?
  // The MHTMLArchive is parsed as a whole, but can be constructed from frames
  // in mutliple processes. In that case, which process should parse it and how
  // should the output be spread back across multiple processes?
  if (!frame()->tree().parent()->isLocalFrame())
    return nullptr;
  return toLocalFrame(frame()->tree().parent())
      ->loader()
      .documentLoader()
      ->fetcher()
      ->archive();
}

ResourceLoadPriority FrameFetchContext::modifyPriorityForExperiments(
    ResourceLoadPriority priority) {
  // If Settings is null, we can't verify any experiments are in force.
  if (!frame()->settings())
    return priority;

  // If enabled, drop the priority of all resources in a subframe.
  if (frame()->settings()->getLowPriorityIframes() && !frame()->isMainFrame())
    return ResourceLoadPriorityVeryLow;

  return priority;
}

RefPtr<WebTaskRunner> FrameFetchContext::loadingTaskRunner() const {
  return frame()->frameScheduler()->loadingTaskRunner();
}

void FrameFetchContext::dispatchDidReceiveResponseInternal(
    unsigned long identifier,
    const ResourceResponse& response,
    WebURLRequest::FrameType frameType,
    WebURLRequest::RequestContext requestContext,
    Resource* resource,
    LinkLoader::CanLoadResources resourceLoadingPolicy) {
  TRACE_EVENT1(
      "devtools.timeline", "ResourceReceiveResponse", "data",
      InspectorReceiveResponseEvent::data(identifier, frame(), response));
  MixedContentChecker::checkMixedPrivatePublic(frame(),
                                               response.remoteIPAddress());
  if (m_documentLoader &&
      m_documentLoader ==
          m_documentLoader->frame()->loader().provisionalDocumentLoader()) {
    FrameClientHintsPreferencesContext hintsContext(frame());
    m_documentLoader->clientHintsPreferences()
        .updateFromAcceptClientHintsHeader(
            response.httpHeaderField(HTTPNames::Accept_CH), &hintsContext);
    // When response is received with a provisional docloader, the resource
    // haven't committed yet, and we cannot load resources, only preconnect.
    resourceLoadingPolicy = LinkLoader::DoNotLoadResources;
  }
  LinkLoader::loadLinksFromHeader(
      response.httpHeaderField(HTTPNames::Link), response.url(),
      frame()->document(), NetworkHintsInterfaceImpl(), resourceLoadingPolicy,
      LinkLoader::LoadAll, nullptr);

  if (response.hasMajorCertificateErrors()) {
    MixedContentChecker::handleCertificateError(frame(), response, frameType,
                                                requestContext);
  }

  frame()->loader().progress().incrementProgress(identifier, response);
  frameLoaderClient()->dispatchDidReceiveResponse(response);
  DocumentLoader* documentLoader = masterDocumentLoader();
  InspectorInstrumentation::didReceiveResourceResponse(
      frame(), identifier, documentLoader, response, resource);
  // It is essential that inspector gets resource response BEFORE console.
  frame()->console().reportResourceResponseReceived(documentLoader, identifier,
                                                    response);
}

DEFINE_TRACE(FrameFetchContext) {
  visitor->trace(m_document);
  visitor->trace(m_documentLoader);
  FetchContext::trace(visitor);
}

}  // namespace blink
