/*
 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
 * reserved.
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (C) 2008 Alp Toker <alp@atoker.com>
 * Copyright (C) Research In Motion Limited 2009. All rights reserved.
 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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/FrameLoader.h"

#include "bindings/core/v8/DOMWrapperWorld.h"
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/SerializedScriptValue.h"
#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/dom/ViewportDescription.h"
#include "core/editing/Editor.h"
#include "core/events/GestureEvent.h"
#include "core/events/KeyboardEvent.h"
#include "core/events/MouseEvent.h"
#include "core/events/PageTransitionEvent.h"
#include "core/fetch/ResourceFetcher.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/VisualViewport.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/input/EventHandler.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/loader/DocumentLoadTiming.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FormSubmission.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/LinkLoader.h"
#include "core/loader/MixedContentChecker.h"
#include "core/loader/NavigationScheduler.h"
#include "core/loader/NetworkHintsInterface.h"
#include "core/loader/ProgressTracker.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
#include "core/origin_trials/OriginTrialContext.h"
#include "core/page/ChromeClient.h"
#include "core/page/CreateWindow.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "core/page/WindowFeatures.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/svg/graphics/SVGImage.h"
#include "core/xml/parser/XMLDocumentParser.h"
#include "platform/InstanceCounters.h"
#include "platform/PluginScriptForbiddenScope.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/UserGestureIndicator.h"
#include "platform/feature_policy/FeaturePolicy.h"
#include "platform/network/HTTPParsers.h"
#include "platform/network/ResourceRequest.h"
#include "platform/scroll/ScrollAnimatorBase.h"
#include "platform/tracing/TraceEvent.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "platform/weborigin/Suborigin.h"
#include "public/platform/WebCachePolicy.h"
#include "public/platform/WebURLRequest.h"
#include "wtf/AutoReset.h"
#include "wtf/text/CString.h"
#include "wtf/text/WTFString.h"
#include <memory>

using blink::WebURLRequest;

namespace blink {

using namespace HTMLNames;

bool isBackForwardLoadType(FrameLoadType type) {
  return type == FrameLoadTypeBackForward ||
         type == FrameLoadTypeInitialHistoryLoad;
}

bool isReloadLoadType(FrameLoadType type) {
  return type == FrameLoadTypeReload ||
         type == FrameLoadTypeReloadMainResource ||
         type == FrameLoadTypeReloadBypassingCache;
}

static bool needsHistoryItemRestore(FrameLoadType type) {
  if (!RuntimeEnabledFeatures::
          reloadwithoutSubResourceCacheRevalidationEnabled() &&
      type == FrameLoadTypeReloadMainResource)
    return false;
  // TODO(toyoshim): Shall we return true for FrameLoadTypeInitialHistoryLoad
  // too?
  return type == FrameLoadTypeBackForward || isReloadLoadType(type);
}

// static
ResourceRequest FrameLoader::resourceRequestFromHistoryItem(
    HistoryItem* item,
    WebCachePolicy cachePolicy) {
  RefPtr<EncodedFormData> formData = item->formData();
  ResourceRequest request(item->url());
  request.setHTTPReferrer(item->referrer());
  request.setCachePolicy(cachePolicy);
  if (formData) {
    request.setHTTPMethod(HTTPNames::POST);
    request.setHTTPBody(formData);
    request.setHTTPContentType(item->formContentType());
    request.addHTTPOriginIfNeeded(item->referrer().referrer);
  }
  return request;
}

ResourceRequest FrameLoader::resourceRequestForReload(
    FrameLoadType frameLoadType,
    const KURL& overrideURL,
    ClientRedirectPolicy clientRedirectPolicy) {
  DCHECK(isReloadLoadType(frameLoadType));
  WebCachePolicy cachePolicy =
      frameLoadType == FrameLoadTypeReloadBypassingCache
          ? WebCachePolicy::BypassingCache
          : WebCachePolicy::ValidatingCacheData;
  if (!m_currentItem)
    return ResourceRequest();
  ResourceRequest request =
      resourceRequestFromHistoryItem(m_currentItem.get(), cachePolicy);

  // ClientRedirectPolicy is an indication that this load was triggered by some
  // direct interaction with the page. If this reload is not a client redirect,
  // we should reuse the referrer from the original load of the current
  // document. If this reload is a client redirect (e.g., location.reload()), it
  // was initiated by something in the current document and should therefore
  // show the current document's url as the referrer.
  if (clientRedirectPolicy == ClientRedirectPolicy::ClientRedirect) {
    request.setHTTPReferrer(SecurityPolicy::generateReferrer(
        m_frame->document()->getReferrerPolicy(), m_frame->document()->url(),
        m_frame->document()->outgoingReferrer()));
  }

  if (!overrideURL.isEmpty()) {
    request.setURL(overrideURL);
    request.clearHTTPReferrer();
  }
  request.setSkipServiceWorker(frameLoadType ==
                                       FrameLoadTypeReloadBypassingCache
                                   ? WebURLRequest::SkipServiceWorker::All
                                   : WebURLRequest::SkipServiceWorker::None);
  return request;
}

FrameLoader::FrameLoader(LocalFrame* frame)
    : m_frame(frame),
      m_progressTracker(ProgressTracker::create(frame)),
      m_loadType(FrameLoadTypeStandard),
      m_inStopAllLoaders(false),
      m_checkTimer(TaskRunnerHelper::get(TaskType::Networking, frame),
                   this,
                   &FrameLoader::checkTimerFired),
      m_forcedSandboxFlags(SandboxNone),
      m_dispatchingDidClearWindowObjectInMainWorld(false),
      m_protectProvisionalLoader(false),
      m_isNavigationHandledByClient(false) {
  TRACE_EVENT_OBJECT_CREATED_WITH_ID("loading", "FrameLoader", this);
  takeObjectSnapshot();
}

FrameLoader::~FrameLoader() {
  // Verify that this FrameLoader has been detached.
  DCHECK(!m_progressTracker);
}

DEFINE_TRACE(FrameLoader) {
  visitor->trace(m_frame);
  visitor->trace(m_progressTracker);
  visitor->trace(m_documentLoader);
  visitor->trace(m_provisionalDocumentLoader);
  visitor->trace(m_currentItem);
  visitor->trace(m_provisionalItem);
  visitor->trace(m_deferredHistoryLoad);
}

void FrameLoader::init() {
  ResourceRequest initialRequest(KURL(ParsedURLString, emptyString()));
  initialRequest.setRequestContext(WebURLRequest::RequestContextInternal);
  initialRequest.setFrameType(m_frame->isMainFrame()
                                  ? WebURLRequest::FrameTypeTopLevel
                                  : WebURLRequest::FrameTypeNested);
  m_provisionalDocumentLoader =
      client()->createDocumentLoader(m_frame, initialRequest, SubstituteData(),
                                     ClientRedirectPolicy::NotClientRedirect);
  m_provisionalDocumentLoader->startLoadingMainResource();
  m_frame->document()->cancelParsing();
  m_stateMachine.advanceTo(
      FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
  // Self-suspend if created in an already deferred Page. Note that both
  // startLoadingMainResource() and cancelParsing() may have already detached
  // the frame, since they both fire JS events.
  if (m_frame->page() && m_frame->page()->defersLoading())
    setDefersLoading(true);
  takeObjectSnapshot();
}

FrameLoaderClient* FrameLoader::client() const {
  return static_cast<FrameLoaderClient*>(m_frame->client());
}

void FrameLoader::setDefersLoading(bool defers) {
  if (m_provisionalDocumentLoader)
    m_provisionalDocumentLoader->fetcher()->setDefersLoading(defers);

  if (Document* document = m_frame->document()) {
    document->fetcher()->setDefersLoading(defers);
    if (defers)
      document->suspendScheduledTasks();
    else
      document->resumeScheduledTasks();
  }

  if (!defers) {
    if (m_deferredHistoryLoad) {
      load(FrameLoadRequest(nullptr, m_deferredHistoryLoad->m_request),
           m_deferredHistoryLoad->m_loadType,
           m_deferredHistoryLoad->m_item.get(),
           m_deferredHistoryLoad->m_historyLoadType);
      m_deferredHistoryLoad.clear();
    }
    m_frame->navigationScheduler().startTimer();
    scheduleCheckCompleted();
  }
}

void FrameLoader::saveScrollState() {
  if (!m_currentItem || !m_frame->view())
    return;

  // Shouldn't clobber anything if we might still restore later.
  if (needsHistoryItemRestore(m_loadType) && m_documentLoader &&
      !m_documentLoader->initialScrollState().wasScrolledByUser)
    return;

  if (ScrollableArea* layoutScrollableArea =
          m_frame->view()->layoutViewportScrollableArea())
    m_currentItem->setScrollOffset(layoutScrollableArea->scrollOffset());
  m_currentItem->setVisualViewportScrollOffset(toScrollOffset(
      m_frame->host()->visualViewport().visibleRect().location()));

  if (m_frame->isMainFrame())
    m_currentItem->setPageScaleFactor(m_frame->page()->pageScaleFactor());

  client()->didUpdateCurrentHistoryItem();
}

void FrameLoader::dispatchUnloadEvent() {
  NavigationDisablerForUnload navigationDisabler;

  // If the frame is unloading, the provisional loader should no longer be
  // protected. It will be detached soon.
  m_protectProvisionalLoader = false;
  saveScrollState();

  if (m_frame->document() && !SVGImage::isInSVGImage(m_frame->document()))
    m_frame->document()->dispatchUnloadEvents();
}

void FrameLoader::didExplicitOpen() {
  // Calling document.open counts as committing the first real document load.
  if (!m_stateMachine.committedFirstRealDocumentLoad())
    m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);

  // Only model a document.open() as part of a navigation if its parent is not
  // done or in the process of completing.
  if (Frame* parent = m_frame->tree().parent()) {
    if ((parent->isLocalFrame() &&
         toLocalFrame(parent)->document()->loadEventStillNeeded()) ||
        (parent->isRemoteFrame() && parent->isLoading())) {
      m_progressTracker->progressStarted();
    }
  }

  // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing
  // away results from a subsequent window.document.open / window.document.write
  // call. Canceling redirection here works for all cases because document.open
  // implicitly precedes document.write.
  m_frame->navigationScheduler().cancel();
}

void FrameLoader::clear() {
  // clear() is called during (Local)Frame detachment or when reusing a
  // FrameLoader by putting a new Document within it
  // (DocumentLoader::ensureWriter().)
  if (m_stateMachine.creatingInitialEmptyDocument())
    return;

  m_frame->editor().clear();
  m_frame->document()->removeFocusedElementOfSubtree(m_frame->document());
  m_frame->eventHandler().clear();
  if (m_frame->view())
    m_frame->view()->clear();

  m_frame->script().enableEval();

  m_frame->navigationScheduler().cancel();

  m_checkTimer.stop();

  if (m_stateMachine.isDisplayingInitialEmptyDocument())
    m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);

  takeObjectSnapshot();
}

// This is only called by ScriptController::executeScriptIfJavaScriptURL and
// always contains the result of evaluating a javascript: url. This is the
// <iframe src="javascript:'html'"> case.
void FrameLoader::replaceDocumentWhileExecutingJavaScriptURL(
    const String& source,
    Document* ownerDocument) {
  if (!m_frame->document()->loader() ||
      m_frame->document()->pageDismissalEventBeingDispatched() !=
          Document::NoDismissal)
    return;

  DocumentLoader* documentLoader(m_frame->document()->loader());

  UseCounter::count(*m_frame->document(),
                    UseCounter::ReplaceDocumentViaJavaScriptURL);

  // Prepare a DocumentInit before clearing the frame, because it may need to
  // inherit an aliased security context.
  DocumentInit init(ownerDocument, m_frame->document()->url(), m_frame);
  init.withNewRegistrationContext();

  stopAllLoaders();
  // Don't allow any new child frames to load in this frame: attaching a new
  // child frame during or after detaching children results in an attached
  // frame on a detached DOM tree, which is bad.
  SubframeLoadingDisabler disabler(m_frame->document());
  m_frame->detachChildren();
  m_frame->document()->shutdown();
  clear();

  // detachChildren() potentially detaches the frame from the document. The
  // loading cannot continue in that case.
  if (!m_frame->page())
    return;

  client()->transitionToCommittedForNewPage();
  documentLoader->replaceDocumentWhileExecutingJavaScriptURL(init, source);
}

void FrameLoader::clearProvisionalHistoryItem() {
  m_provisionalItem.clear();
}

void FrameLoader::setHistoryItemStateForCommit(
    FrameLoadType loadType,
    HistoryCommitType historyCommitType,
    HistoryNavigationType navigationType) {
  HistoryItem* oldItem = m_currentItem;
  if (isBackForwardLoadType(loadType) && m_provisionalItem)
    m_currentItem = m_provisionalItem.release();
  else
    m_currentItem = HistoryItem::create();
  m_currentItem->setURL(m_documentLoader->urlForHistory());
  m_currentItem->setDocumentState(m_frame->document()->formElementsState());
  m_currentItem->setTarget(m_frame->tree().uniqueName());
  m_currentItem->setReferrer(SecurityPolicy::generateReferrer(
      m_documentLoader->request().getReferrerPolicy(), m_currentItem->url(),
      m_documentLoader->request().httpReferrer()));
  m_currentItem->setFormInfoFromRequest(m_documentLoader->request());

  // Don't propagate state from the old item to the new item if there isn't an
  // old item (obviously), or if this is a back/forward navigation, since we
  // explicitly want to restore the state we just committed.
  if (!oldItem || isBackForwardLoadType(loadType))
    return;
  // Don't propagate state from the old item if this is a different-document
  // navigation, unless the before and after pages are logically related. This
  // means they have the same url (ignoring fragment) and the new item was
  // loaded via reload or client redirect.
  if (navigationType == HistoryNavigationType::DifferentDocument &&
      (historyCommitType != HistoryInertCommit ||
       !equalIgnoringFragmentIdentifier(oldItem->url(), m_currentItem->url())))
    return;
  m_currentItem->setDocumentSequenceNumber(oldItem->documentSequenceNumber());
  m_currentItem->setScrollOffset(oldItem->scrollOffset());
  m_currentItem->setVisualViewportScrollOffset(
      oldItem->visualViewportScrollOffset());
  m_currentItem->setPageScaleFactor(oldItem->pageScaleFactor());
  m_currentItem->setScrollRestorationType(oldItem->scrollRestorationType());

  // The item sequence number determines whether items are "the same", such
  // back/forward navigation between items with the same item sequence number is
  // a no-op. Only treat this as identical if the navigation did not create a
  // back/forward entry and the url is identical or it was loaded via
  // history.replaceState().
  if (historyCommitType == HistoryInertCommit &&
      (navigationType == HistoryNavigationType::HistoryApi ||
       oldItem->url() == m_currentItem->url())) {
    m_currentItem->setStateObject(oldItem->stateObject());
    m_currentItem->setItemSequenceNumber(oldItem->itemSequenceNumber());
  }
}

static HistoryCommitType loadTypeToCommitType(FrameLoadType type) {
  switch (type) {
    case FrameLoadTypeStandard:
      return StandardCommit;
    case FrameLoadTypeInitialInChildFrame:
    case FrameLoadTypeInitialHistoryLoad:
      return InitialCommitInChildFrame;
    case FrameLoadTypeBackForward:
      return BackForwardCommit;
    default:
      break;
  }
  return HistoryInertCommit;
}

void FrameLoader::receivedFirstData() {
  if (m_stateMachine.creatingInitialEmptyDocument())
    return;

  HistoryCommitType historyCommitType = loadTypeToCommitType(m_loadType);
  if (historyCommitType == StandardCommit &&
      (m_documentLoader->urlForHistory().isEmpty() ||
       (opener() && !m_currentItem &&
        m_documentLoader->originalRequest().url().isEmpty())))
    historyCommitType = HistoryInertCommit;
  setHistoryItemStateForCommit(m_loadType, historyCommitType,
                               HistoryNavigationType::DifferentDocument);

  if (!m_stateMachine.committedMultipleRealLoads() &&
      m_loadType == FrameLoadTypeStandard) {
    m_stateMachine.advanceTo(
        FrameLoaderStateMachine::CommittedMultipleRealLoads);
  }

  client()->dispatchDidCommitLoad(m_currentItem.get(), historyCommitType);

  // When the embedder gets notified (above) that the new navigation has
  // committed, the embedder will drop the old Content Security Policy and
  // therefore now is a good time to report to the embedder the Content Security
  // Policies that have accumulated so far for the new navigation.
  m_frame->securityContext()->contentSecurityPolicy()->reportAccumulatedHeaders(
      client());

  // didObserveLoadingBehavior() must be called after dispatchDidCommitLoad() is
  // called for the metrics tracking logic to handle it properly.
  if (client()->isControlledByServiceWorker(*m_documentLoader)) {
    client()->didObserveLoadingBehavior(
        WebLoadingBehaviorServiceWorkerControlled);
  }

  // Links with media values need more information (like viewport information).
  // This happens after the first chunk is parsed in HTMLDocumentParser.
  m_documentLoader->dispatchLinkHeaderPreloads(nullptr,
                                               LinkLoader::OnlyLoadNonMedia);

  TRACE_EVENT1("devtools.timeline", "CommitLoad", "data",
               InspectorCommitLoadEvent::data(m_frame));
  InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
  m_frame->page()->didCommitLoad(m_frame);
  dispatchDidClearDocumentOfWindowObject();

  takeObjectSnapshot();
}

void FrameLoader::didInstallNewDocument(bool dispatchWindowObjectAvailable) {
  DCHECK(m_frame);
  DCHECK(m_frame->document());

  m_frame->document()->setReadyState(Document::Loading);

  if (dispatchWindowObjectAvailable)
    dispatchDidClearDocumentOfWindowObject();

  m_frame->document()->initContentSecurityPolicy(
      m_documentLoader ? m_documentLoader->releaseContentSecurityPolicy()
                       : ContentSecurityPolicy::create());

  if (m_provisionalItem && isBackForwardLoadType(m_loadType)) {
    m_frame->document()->setStateForNewFormElements(
        m_provisionalItem->documentState());
  }
}

void FrameLoader::didBeginDocument() {
  DCHECK(m_frame);
  DCHECK(m_frame->document());
  DCHECK(m_frame->document()->fetcher());

  if (m_documentLoader) {
    String suboriginHeader =
        m_documentLoader->response().httpHeaderField(HTTPNames::Suborigin);
    if (!suboriginHeader.isNull()) {
      Vector<String> messages;
      Suborigin suborigin;
      if (parseSuboriginHeader(suboriginHeader, &suborigin, messages))
        m_frame->document()->enforceSuborigin(suborigin);

      for (auto& message : messages) {
        m_frame->document()->addConsoleMessage(
            ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel,
                                   "Error with Suborigin header: " + message));
      }
    }
    m_frame->document()->clientHintsPreferences().updateFrom(
        m_documentLoader->clientHintsPreferences());
  }

  Settings* settings = m_frame->document()->settings();
  if (settings) {
    m_frame->document()->fetcher()->setImagesEnabled(settings->imagesEnabled());
    m_frame->document()->fetcher()->setAutoLoadImages(
        settings->loadsImagesAutomatically());
  }

  if (m_documentLoader) {
    const AtomicString& dnsPrefetchControl =
        m_documentLoader->response().httpHeaderField(
            HTTPNames::X_DNS_Prefetch_Control);
    if (!dnsPrefetchControl.isEmpty())
      m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);

    String headerContentLanguage = m_documentLoader->response().httpHeaderField(
        HTTPNames::Content_Language);
    if (!headerContentLanguage.isEmpty()) {
      size_t commaIndex = headerContentLanguage.find(',');
      headerContentLanguage.truncate(
          commaIndex);  // kNotFound == -1 == don't truncate
      headerContentLanguage =
          headerContentLanguage.stripWhiteSpace(isHTMLSpace<UChar>);
      if (!headerContentLanguage.isEmpty()) {
        m_frame->document()->setContentLanguage(
            AtomicString(headerContentLanguage));
      }
    }

    OriginTrialContext::addTokensFromHeader(
        m_frame->document(),
        m_documentLoader->response().httpHeaderField(HTTPNames::Origin_Trial));
    if (RuntimeEnabledFeatures::featurePolicyEnabled()) {
      std::unique_ptr<FeaturePolicy> featurePolicy(
          FeaturePolicy::createFromParentPolicy(
              (isLoadingMainFrame() ? nullptr
                                    : m_frame->client()
                                          ->parent()
                                          ->securityContext()
                                          ->getFeaturePolicy()),
              m_frame->securityContext()->getSecurityOrigin()));
      Vector<String> messages;
      featurePolicy->setHeaderPolicy(
          m_documentLoader->response().httpHeaderField(
              HTTPNames::Feature_Policy),
          messages);
      for (auto& message : messages) {
        m_frame->document()->addConsoleMessage(ConsoleMessage::create(
            OtherMessageSource, ErrorMessageLevel,
            "Error with Feature-Policy header: " + message));
      }
      m_frame->document()->setFeaturePolicy(std::move(featurePolicy));
    }
  }

  if (m_documentLoader) {
    String referrerPolicyHeader = m_documentLoader->response().httpHeaderField(
        HTTPNames::Referrer_Policy);
    if (!referrerPolicyHeader.isNull()) {
      m_frame->document()->parseAndSetReferrerPolicy(referrerPolicyHeader);
    }
  }

  client()->didCreateNewDocument();
}

void FrameLoader::finishedParsing() {
  if (m_stateMachine.creatingInitialEmptyDocument())
    return;

  m_progressTracker->finishedParsing();

  if (client()) {
    ScriptForbiddenScope forbidScripts;
    client()->dispatchDidFinishDocumentLoad();
  }

  if (client()) {
    client()->runScriptsAtDocumentReady(
        m_documentLoader ? m_documentLoader->isCommittedButEmpty() : true);
  }

  checkCompleted();

  if (!m_frame->view())
    return;

  // Check if the scrollbars are really needed for the content. If not, remove
  // them, relayout, and repaint.
  m_frame->view()->restoreScrollbar();
  processFragment(m_frame->document()->url(), NavigationToDifferentDocument);
}

static bool allDescendantsAreComplete(Frame* frame) {
  for (Frame* child = frame->tree().firstChild(); child;
       child = child->tree().traverseNext(frame)) {
    if (child->isLoading())
      return false;
  }
  return true;
}

bool FrameLoader::allAncestorsAreComplete() const {
  for (Frame* ancestor = m_frame; ancestor;
       ancestor = ancestor->tree().parent()) {
    if (ancestor->isLoading())
      return false;
  }
  return true;
}

static bool shouldComplete(Document* document) {
  if (!document->frame())
    return false;
  if (document->parsing() || document->isInDOMContentLoaded())
    return false;
  if (!document->haveImportsLoaded())
    return false;
  if (document->fetcher()->requestCount())
    return false;
  if (document->isDelayingLoadEvent())
    return false;
  return allDescendantsAreComplete(document->frame());
}

static bool shouldSendFinishNotification(LocalFrame* frame) {
  // Don't send stop notifications for inital empty documents, since they don't
  // generate start notifications.
  if (!frame->loader().stateMachine()->committedFirstRealDocumentLoad())
    return false;

  // Don't send didFinishLoad more than once per DocumentLoader.
  if (frame->loader().documentLoader()->sentDidFinishLoad())
    return false;

  // We might have declined to run the load event due to an imminent
  // content-initiated navigation.
  if (!frame->document()->loadEventFinished())
    return false;

  // An event might have restarted a child frame.
  if (!allDescendantsAreComplete(frame))
    return false;
  return true;
}

static bool shouldSendCompleteNotification(LocalFrame* frame,
                                           bool isNavigationHandledByClient) {
  // FIXME: We might have already sent stop notifications and be re-completing.
  if (!frame->isLoading())
    return false;
  // Only send didStopLoading() if there are no navigations in progress at all,
  // whether committed, provisional, or pending.
  return frame->loader().documentLoader()->sentDidFinishLoad() &&
         !frame->loader().provisionalDocumentLoader() &&
         !isNavigationHandledByClient;
}

void FrameLoader::checkCompleted() {
  if (!shouldComplete(m_frame->document()))
    return;

  // OK, completed.
  m_frame->document()->setReadyState(Document::Complete);
  if (m_frame->document()->loadEventStillNeeded())
    m_frame->document()->implicitClose();

  m_frame->navigationScheduler().startTimer();

  if (m_frame->view())
    m_frame->view()->handleLoadCompleted();

  // The readystatechanged or load event may have disconnected this frame.
  if (!m_frame->client())
    return;

  if (shouldSendFinishNotification(m_frame)) {
    // Report mobile vs. desktop page statistics. This will only report on
    // Android.
    if (m_frame->isMainFrame())
      m_frame->document()->viewportDescription().reportMobilePageStats(m_frame);
    m_documentLoader->setSentDidFinishLoad();
    client()->dispatchDidFinishLoad();
    // Finishing the load can detach the frame when running layout tests.
    if (!m_frame->client())
      return;
  }

  if (shouldSendCompleteNotification(m_frame, m_isNavigationHandledByClient)) {
    m_progressTracker->progressCompleted();
    // Retry restoring scroll offset since finishing loading disables content
    // size clamping.
    restoreScrollPositionAndViewState();

    m_loadType = FrameLoadTypeStandard;
    m_frame->localDOMWindow()->finishedLoading();
  }

  Frame* parent = m_frame->tree().parent();
  if (parent && parent->isLocalFrame())
    toLocalFrame(parent)->loader().checkCompleted();
}

void FrameLoader::checkTimerFired(TimerBase*) {
  if (Page* page = m_frame->page()) {
    if (page->defersLoading())
      return;
  }
  checkCompleted();
}

void FrameLoader::scheduleCheckCompleted() {
  if (!m_checkTimer.isActive())
    m_checkTimer.startOneShot(0, BLINK_FROM_HERE);
}

Frame* FrameLoader::opener() {
  return client() ? client()->opener() : 0;
}

void FrameLoader::setOpener(LocalFrame* opener) {
  // If the frame is already detached, the opener has already been cleared.
  if (client())
    client()->setOpener(opener);
}

bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason) {
  // With Oilpan, a FrameLoader might be accessed after the FrameHost has been
  // detached. FrameClient will not be accessible, so bail early.
  if (!client())
    return false;
  Settings* settings = m_frame->settings();
  bool allowed = client()->allowPlugins(settings && settings->pluginsEnabled());
  if (!allowed && reason == AboutToInstantiatePlugin)
    client()->didNotAllowPlugins();
  return allowed;
}

void FrameLoader::updateForSameDocumentNavigation(
    const KURL& newURL,
    SameDocumentNavigationSource sameDocumentNavigationSource,
    PassRefPtr<SerializedScriptValue> data,
    HistoryScrollRestorationType scrollRestorationType,
    FrameLoadType type,
    Document* initiatingDocument) {
  // Update the data source's request with the new URL to fake the URL change
  m_frame->document()->setURL(newURL);
  documentLoader()->setReplacesCurrentHistoryItem(type !=
                                                  FrameLoadTypeStandard);
  documentLoader()->updateForSameDocumentNavigation(
      newURL, sameDocumentNavigationSource);

  // Generate start and stop notifications only when loader is completed so that
  // we don't fire them for fragment redirection that happens in window.onload
  // handler. See https://bugs.webkit.org/show_bug.cgi?id=31838
  if (m_frame->document()->loadEventFinished())
    client()->didStartLoading(NavigationWithinSameDocument);

  HistoryCommitType historyCommitType = loadTypeToCommitType(type);
  if (!m_currentItem)
    historyCommitType = HistoryInertCommit;
  if (m_frame->settings()->historyEntryRequiresUserGesture() &&
      initiatingDocument && !initiatingDocument->hasReceivedUserGesture()) {
    historyCommitType = HistoryInertCommit;
  }

  setHistoryItemStateForCommit(
      type, historyCommitType,
      sameDocumentNavigationSource == SameDocumentNavigationHistoryApi
          ? HistoryNavigationType::HistoryApi
          : HistoryNavigationType::Fragment);
  if (sameDocumentNavigationSource == SameDocumentNavigationHistoryApi) {
    m_currentItem->setStateObject(std::move(data));
    m_currentItem->setScrollRestorationType(scrollRestorationType);
  }
  client()->dispatchDidNavigateWithinPage(
      m_currentItem.get(), historyCommitType, !!initiatingDocument);
  client()->dispatchDidReceiveTitle(m_frame->document()->title());
  if (m_frame->document()->loadEventFinished())
    client()->didStopLoading();
}

void FrameLoader::detachDocumentLoader(Member<DocumentLoader>& loader) {
  if (!loader)
    return;

  FrameNavigationDisabler navigationDisabler(*m_frame);
  loader->detachFromFrame();
  loader = nullptr;
}

void FrameLoader::loadInSameDocument(
    const KURL& url,
    PassRefPtr<SerializedScriptValue> stateObject,
    FrameLoadType frameLoadType,
    HistoryLoadType historyLoadType,
    ClientRedirectPolicy clientRedirect,
    Document* initiatingDocument) {
  // If we have a state object, we cannot also be a new navigation.
  DCHECK(!stateObject || frameLoadType == FrameLoadTypeBackForward);

  // If we have a provisional request for a different document, a fragment
  // scroll should cancel it.
  detachDocumentLoader(m_provisionalDocumentLoader);
  if (!m_frame->host())
    return;
  AutoReset<FrameLoadType> loadTypeChange(&m_loadType, frameLoadType);
  saveScrollState();

  KURL oldURL = m_frame->document()->url();
  bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) &&
                    url.fragmentIdentifier() != oldURL.fragmentIdentifier();
  if (hashChange) {
    // If we were in the autoscroll/middleClickAutoscroll mode we want to stop
    // it before following the link to the anchor
    m_frame->eventHandler().stopAutoscroll();
    m_frame->localDOMWindow()->enqueueHashchangeEvent(oldURL, url);
  }
  m_documentLoader->setIsClientRedirect(clientRedirect ==
                                        ClientRedirectPolicy::ClientRedirect);
  updateForSameDocumentNavigation(url, SameDocumentNavigationDefault, nullptr,
                                  ScrollRestorationAuto, frameLoadType,
                                  initiatingDocument);

  m_documentLoader->initialScrollState().wasScrolledByUser = false;

  checkCompleted();

  m_frame->localDOMWindow()->statePopped(
      stateObject ? std::move(stateObject)
                  : SerializedScriptValue::nullValue());

  if (historyLoadType == HistorySameDocumentLoad)
    restoreScrollPositionAndViewState();

  // We need to scroll to the fragment whether or not a hash change occurred,
  // since the user might have scrolled since the previous navigation.
  processFragment(url, NavigationWithinSameDocument);
  takeObjectSnapshot();
}

// static
void FrameLoader::setReferrerForFrameRequest(FrameLoadRequest& frameRequest) {
  ResourceRequest& request = frameRequest.resourceRequest();
  Document* originDocument = frameRequest.originDocument();

  if (!originDocument)
    return;
  // Anchor elements with the 'referrerpolicy' attribute will have already set
  // the referrer on the request.
  if (request.didSetHTTPReferrer())
    return;
  if (frameRequest.getShouldSendReferrer() == NeverSendReferrer)
    return;

  // Always use the initiating document to generate the referrer. We need to
  // generateReferrer(), because we haven't enforced ReferrerPolicy or
  // https->http referrer suppression yet.
  Referrer referrer = SecurityPolicy::generateReferrer(
      originDocument->getReferrerPolicy(), request.url(),
      originDocument->outgoingReferrer());

  request.setHTTPReferrer(referrer);
  request.addHTTPOriginIfNeeded(referrer.referrer);
}

FrameLoadType FrameLoader::determineFrameLoadType(
    const FrameLoadRequest& request) {
  if (m_frame->tree().parent() &&
      !m_stateMachine.committedFirstRealDocumentLoad())
    return FrameLoadTypeInitialInChildFrame;
  if (!m_frame->tree().parent() && !client()->backForwardLength())
    return FrameLoadTypeStandard;
  if (m_provisionalDocumentLoader &&
      request.substituteData().failingURL() ==
          m_provisionalDocumentLoader->url() &&
      m_loadType == FrameLoadTypeBackForward)
    return FrameLoadTypeBackForward;
  if (request.resourceRequest().getCachePolicy() ==
      WebCachePolicy::ValidatingCacheData)
    return FrameLoadTypeReload;
  if (request.resourceRequest().getCachePolicy() ==
      WebCachePolicy::BypassingCache)
    return FrameLoadTypeReloadBypassingCache;
  // From the HTML5 spec for location.assign():
  // "If the browsing context's session history contains only one Document,
  // and that was the about:blank Document created when the browsing context
  // was created, then the navigation must be done with replacement enabled."
  if (request.replacesCurrentItem() ||
      (!m_stateMachine.committedMultipleRealLoads() &&
       equalIgnoringCase(m_frame->document()->url(), blankURL())))
    return FrameLoadTypeReplaceCurrentItem;

  if (request.resourceRequest().url() == m_documentLoader->urlForHistory()) {
    if (!request.originDocument())
      return FrameLoadTypeReloadMainResource;
    return request.resourceRequest().httpMethod() == HTTPNames::POST
               ? FrameLoadTypeStandard
               : FrameLoadTypeReplaceCurrentItem;
  }

  if (request.substituteData().failingURL() ==
          m_documentLoader->urlForHistory() &&
      m_loadType == FrameLoadTypeReload)
    return FrameLoadTypeReload;

  if (m_frame->settings()->historyEntryRequiresUserGesture() &&
      request.originDocument() &&
      !request.originDocument()->hasReceivedUserGesture())
    return FrameLoadTypeReplaceCurrentItem;

  return FrameLoadTypeStandard;
}

bool FrameLoader::prepareRequestForThisFrame(FrameLoadRequest& request) {
  // If no origin Document* was specified, skip remaining security checks and
  // assume the caller has fully initialized the FrameLoadRequest.
  if (!request.originDocument())
    return true;

  KURL url = request.resourceRequest().url();
  if (m_frame->script().executeScriptIfJavaScriptURL(url, nullptr))
    return false;

  if (!request.originDocument()->getSecurityOrigin()->canDisplay(url)) {
    reportLocalLoadFailed(m_frame, url.elidedString());
    return false;
  }

  if (!request.form() && request.frameName().isEmpty())
    request.setFrameName(m_frame->document()->baseTarget());
  return true;
}

static bool shouldNavigateTargetFrame(NavigationPolicy policy) {
  switch (policy) {
    case NavigationPolicyCurrentTab:
      return true;

    // Navigation will target a *new* frame (e.g. because of a ctrl-click),
    // so the target frame can be ignored.
    case NavigationPolicyNewBackgroundTab:
    case NavigationPolicyNewForegroundTab:
    case NavigationPolicyNewWindow:
    case NavigationPolicyNewPopup:
      return false;

    // Navigation won't really target any specific frame,
    // so the target frame can be ignored.
    case NavigationPolicyIgnore:
    case NavigationPolicyDownload:
      return false;

    case NavigationPolicyHandledByClient:
      // Impossible, because at this point we shouldn't yet have called
      // client()->decidePolicyForNavigation(...).
      NOTREACHED();
      return true;

    default:
      NOTREACHED() << policy;
      return true;
  }
}

static NavigationType determineNavigationType(FrameLoadType frameLoadType,
                                              bool isFormSubmission,
                                              bool haveEvent) {
  bool isReload = isReloadLoadType(frameLoadType);
  bool isBackForward = isBackForwardLoadType(frameLoadType);
  if (isFormSubmission) {
    return (isReload || isBackForward) ? NavigationTypeFormResubmitted
                                       : NavigationTypeFormSubmitted;
  }
  if (haveEvent)
    return NavigationTypeLinkClicked;
  if (isReload)
    return NavigationTypeReload;
  if (isBackForward)
    return NavigationTypeBackForward;
  return NavigationTypeOther;
}

static WebURLRequest::RequestContext determineRequestContextFromNavigationType(
    const NavigationType navigationType) {
  switch (navigationType) {
    case NavigationTypeLinkClicked:
      return WebURLRequest::RequestContextHyperlink;

    case NavigationTypeOther:
      return WebURLRequest::RequestContextLocation;

    case NavigationTypeFormResubmitted:
    case NavigationTypeFormSubmitted:
      return WebURLRequest::RequestContextForm;

    case NavigationTypeBackForward:
    case NavigationTypeReload:
      return WebURLRequest::RequestContextInternal;
  }
  NOTREACHED();
  return WebURLRequest::RequestContextHyperlink;
}

static NavigationPolicy navigationPolicyForRequest(
    const FrameLoadRequest& request) {
  NavigationPolicy policy = NavigationPolicyCurrentTab;
  Event* event = request.triggeringEvent();
  if (!event)
    return policy;

  if (request.form() && event->underlyingEvent())
    event = event->underlyingEvent();

  if (event->isMouseEvent()) {
    MouseEvent* mouseEvent = toMouseEvent(event);
    navigationPolicyFromMouseEvent(mouseEvent->button(), mouseEvent->ctrlKey(),
                                   mouseEvent->shiftKey(), mouseEvent->altKey(),
                                   mouseEvent->metaKey(), &policy);
  } else if (event->isKeyboardEvent()) {
    // The click is simulated when triggering the keypress event.
    KeyboardEvent* keyEvent = toKeyboardEvent(event);
    navigationPolicyFromMouseEvent(0, keyEvent->ctrlKey(), keyEvent->shiftKey(),
                                   keyEvent->altKey(), keyEvent->metaKey(),
                                   &policy);
  } else if (event->isGestureEvent()) {
    // The click is simulated when triggering the gesture-tap event
    GestureEvent* gestureEvent = toGestureEvent(event);
    navigationPolicyFromMouseEvent(
        0, gestureEvent->ctrlKey(), gestureEvent->shiftKey(),
        gestureEvent->altKey(), gestureEvent->metaKey(), &policy);
  }
  return policy;
}

void FrameLoader::load(const FrameLoadRequest& passedRequest,
                       FrameLoadType frameLoadType,
                       HistoryItem* historyItem,
                       HistoryLoadType historyLoadType) {
  DCHECK(m_frame->document());

  if (!m_frame->isNavigationAllowed())
    return;

  if (m_inStopAllLoaders)
    return;

  if (m_frame->page()->defersLoading() &&
      isBackForwardLoadType(frameLoadType)) {
    m_deferredHistoryLoad = DeferredHistoryLoad::create(
        passedRequest.resourceRequest(), historyItem, frameLoadType,
        historyLoadType);
    return;
  }

  FrameLoadRequest request(passedRequest);
  request.resourceRequest().setHasUserGesture(
      UserGestureIndicator::processingUserGesture());

  if (!prepareRequestForThisFrame(request))
    return;

  if (isBackForwardLoadType(frameLoadType)) {
    DCHECK(historyItem);
    m_provisionalItem = historyItem;
  }

  // Form submissions appear to need their special-case of finding the target at
  // schedule rather than at fire.
  Frame* targetFrame = request.form()
                           ? nullptr
                           : m_frame->findFrameForNavigation(
                                 AtomicString(request.frameName()), *m_frame);
  NavigationPolicy policy = navigationPolicyForRequest(request);
  if (targetFrame && targetFrame != m_frame &&
      shouldNavigateTargetFrame(policy)) {
    bool wasInSamePage = targetFrame->page() == m_frame->page();

    request.setFrameName("_self");
    targetFrame->navigate(request);
    Page* page = targetFrame->page();
    if (!wasInSamePage && page)
      page->chromeClient().focus();
    return;
  }

  setReferrerForFrameRequest(request);

  if (!targetFrame && !request.frameName().isEmpty()) {
    if (policy == NavigationPolicyDownload) {
      client()->loadURLExternally(request.resourceRequest(),
                                  NavigationPolicyDownload, String(), false);
    } else {
      request.resourceRequest().setFrameType(WebURLRequest::FrameTypeAuxiliary);
      createWindowForRequest(request, *m_frame, policy);
    }
    return;
  }

  const KURL& url = request.resourceRequest().url();
  FrameLoadType newLoadType = (frameLoadType == FrameLoadTypeStandard)
                                  ? determineFrameLoadType(request)
                                  : frameLoadType;
  bool sameDocumentHistoryNavigation =
      isBackForwardLoadType(newLoadType) &&
      historyLoadType == HistorySameDocumentLoad;
  bool sameDocumentNavigation =
      policy == NavigationPolicyCurrentTab &&
      shouldPerformFragmentNavigation(request.form(),
                                      request.resourceRequest().httpMethod(),
                                      newLoadType, url);

  // Perform same document navigation.
  if (sameDocumentHistoryNavigation || sameDocumentNavigation) {
    DCHECK(historyItem || !sameDocumentHistoryNavigation);
    RefPtr<SerializedScriptValue> stateObject =
        sameDocumentHistoryNavigation ? historyItem->stateObject() : nullptr;

    if (!sameDocumentHistoryNavigation) {
      m_documentLoader->setNavigationType(determineNavigationType(
          newLoadType, false, request.triggeringEvent()));
      if (shouldTreatURLAsSameAsCurrent(url))
        newLoadType = FrameLoadTypeReplaceCurrentItem;
    }

    loadInSameDocument(url, stateObject, newLoadType, historyLoadType,
                       request.clientRedirect(), request.originDocument());
    return;
  }

  startLoad(request, newLoadType, policy);
}

SubstituteData FrameLoader::defaultSubstituteDataForURL(const KURL& url) {
  if (!shouldTreatURLAsSrcdocDocument(url))
    return SubstituteData();
  String srcdoc = m_frame->deprecatedLocalOwner()->fastGetAttribute(srcdocAttr);
  DCHECK(!srcdoc.isNull());
  CString encodedSrcdoc = srcdoc.utf8();
  return SubstituteData(
      SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()),
      "text/html", "UTF-8", KURL());
}

void FrameLoader::reportLocalLoadFailed(LocalFrame* frame, const String& url) {
  DCHECK(!url.isEmpty());
  if (!frame)
    return;

  frame->document()->addConsoleMessage(
      ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel,
                             "Not allowed to load local resource: " + url));
}

void FrameLoader::stopAllLoaders() {
  if (m_frame->document()->pageDismissalEventBeingDispatched() !=
      Document::NoDismissal)
    return;

  // If this method is called from within this method, infinite recursion can
  // occur (3442218). Avoid this.
  if (m_inStopAllLoaders)
    return;

  m_inStopAllLoaders = true;

  m_isNavigationHandledByClient = false;

  for (Frame* child = m_frame->tree().firstChild(); child;
       child = child->tree().nextSibling()) {
    if (child->isLocalFrame())
      toLocalFrame(child)->loader().stopAllLoaders();
  }

  m_frame->document()->suppressLoadEvent();
  if (m_documentLoader)
    m_documentLoader->fetcher()->stopFetching();
  m_frame->document()->cancelParsing();
  if (!m_protectProvisionalLoader)
    detachDocumentLoader(m_provisionalDocumentLoader);

  m_checkTimer.stop();
  m_frame->navigationScheduler().cancel();

  // It's possible that the above actions won't have stopped loading if load
  // completion had been blocked on parsing or if we were in the middle of
  // committing an empty document. In that case, emulate a failed navigation.
  if (!m_provisionalDocumentLoader && m_documentLoader &&
      m_frame->isLoading()) {
    loadFailed(m_documentLoader.get(),
               ResourceError::cancelledError(m_documentLoader->url()));
  }

  m_inStopAllLoaders = false;
  takeObjectSnapshot();
}

void FrameLoader::didAccessInitialDocument() {
  // We only need to notify the client for the main frame.
  if (isLoadingMainFrame()) {
    // Forbid script execution to prevent re-entering V8, since this is called
    // from a binding security check.
    ScriptForbiddenScope forbidScripts;
    if (client())
      client()->didAccessInitialDocument();
  }
}

bool FrameLoader::prepareForCommit() {
  PluginScriptForbiddenScope forbidPluginDestructorScripting;
  DocumentLoader* pdl = m_provisionalDocumentLoader;

  if (m_frame->document()) {
    unsigned nodeCount = 0;
    for (Frame* frame = m_frame; frame; frame = frame->tree().traverseNext()) {
      if (frame->isLocalFrame()) {
        LocalFrame* localFrame = toLocalFrame(frame);
        nodeCount += localFrame->document()->nodeCount();
      }
    }
    unsigned totalNodeCount =
        InstanceCounters::counterValue(InstanceCounters::NodeCounter);
    float ratio = static_cast<float>(nodeCount) / totalNodeCount;
    ThreadState::current()->schedulePageNavigationGCIfNeeded(ratio);
  }

  // Don't allow any new child frames to load in this frame: attaching a new
  // child frame during or after detaching children results in an attached frame
  // on a detached DOM tree, which is bad.
  SubframeLoadingDisabler disabler(m_frame->document());
  if (m_documentLoader) {
    client()->dispatchWillCommitProvisionalLoad();
    dispatchUnloadEvent();
  }
  m_frame->detachChildren();
  // The previous calls to dispatchUnloadEvent() and detachChildren() can
  // execute arbitrary script via things like unload events. If the executed
  // script intiates a new load or causes the current frame to be detached, we
  // need to abandon the current load.
  if (pdl != m_provisionalDocumentLoader)
    return false;
  // detachFromFrame() will abort XHRs that haven't completed, which can trigger
  // event listeners for 'abort'. These event listeners might call
  // window.stop(), which will in turn detach the provisional document loader.
  // At this point, the provisional document loader should not detach, because
  // then the FrameLoader would not have any attached DocumentLoaders.
  if (m_documentLoader) {
    AutoReset<bool> inDetachDocumentLoader(&m_protectProvisionalLoader, true);
    detachDocumentLoader(m_documentLoader);
  }
  // 'abort' listeners can also detach the frame.
  if (!m_frame->client())
    return false;
  DCHECK_EQ(m_provisionalDocumentLoader, pdl);
  // No more events will be dispatched so detach the Document.
  // TODO(yoav): Should we also be nullifying domWindow's document (or
  // domWindow) since the doc is now detached?
  if (m_frame->document())
    m_frame->document()->shutdown();
  m_documentLoader = m_provisionalDocumentLoader.release();
  takeObjectSnapshot();

  return true;
}

void FrameLoader::commitProvisionalLoad() {
  DCHECK(client()->hasWebView());

  // Check if the destination page is allowed to access the previous page's
  // timing information.
  if (m_frame->document()) {
    RefPtr<SecurityOrigin> securityOrigin =
        SecurityOrigin::create(m_provisionalDocumentLoader->request().url());
    m_provisionalDocumentLoader->timing().setHasSameOriginAsPreviousDocument(
        securityOrigin->canRequest(m_frame->document()->url()));
  }

  if (!prepareForCommit())
    return;

  if (isLoadingMainFrame()) {
    m_frame->page()->chromeClient().setEventListenerProperties(
        WebEventListenerClass::TouchStartOrMove,
        WebEventListenerProperties::Nothing);
    m_frame->page()->chromeClient().setEventListenerProperties(
        WebEventListenerClass::MouseWheel, WebEventListenerProperties::Nothing);
    m_frame->page()->chromeClient().setEventListenerProperties(
        WebEventListenerClass::TouchEndOrCancel,
        WebEventListenerProperties::Nothing);
  }

  client()->transitionToCommittedForNewPage();
  m_frame->navigationScheduler().cancel();
  m_frame->editor().clearLastEditCommand();

  // If we are still in the process of initializing an empty document then its
  // frame is not in a consistent state for rendering, so avoid
  // setJSStatusBarText since it may cause clients to attempt to render the
  // frame.
  if (!m_stateMachine.creatingInitialEmptyDocument()) {
    DOMWindow* window = m_frame->domWindow();
    window->setStatus(String());
    window->setDefaultStatus(String());
  }
}

bool FrameLoader::isLoadingMainFrame() const {
  return m_frame->isMainFrame();
}

FrameLoadType FrameLoader::loadType() const {
  return m_loadType;
}

void FrameLoader::restoreScrollPositionAndViewState() {
  FrameView* view = m_frame->view();
  if (!m_frame->page() || !view || !view->layoutViewportScrollableArea() ||
      !m_currentItem || !m_stateMachine.committedFirstRealDocumentLoad() ||
      !documentLoader()) {
    return;
  }

  if (!needsHistoryItemRestore(m_loadType))
    return;

  bool shouldRestoreScroll =
      m_currentItem->scrollRestorationType() != ScrollRestorationManual;
  bool shouldRestoreScale = m_currentItem->pageScaleFactor();

  // This tries to balance:
  // 1. restoring as soon as possible
  // 2. not overriding user scroll (TODO(majidvp): also respect user scale)
  // 3. detecting clamping to avoid repeatedly popping the scroll position down
  //    as the page height increases
  // 4. ignore clamp detection if we are not restoring scroll or after load
  //    completes because that may be because the page will never reach its
  //    previous height
  bool canRestoreWithoutClamping =
      view->layoutViewportScrollableArea()->clampScrollOffset(
          m_currentItem->scrollOffset()) == m_currentItem->scrollOffset();
  bool canRestoreWithoutAnnoyingUser =
      !documentLoader()->initialScrollState().wasScrolledByUser &&
      (canRestoreWithoutClamping || !m_frame->isLoading() ||
       !shouldRestoreScroll);
  if (!canRestoreWithoutAnnoyingUser)
    return;

  if (shouldRestoreScroll) {
    view->layoutViewportScrollableArea()->setScrollOffset(
        m_currentItem->scrollOffset(), ProgrammaticScroll);
  }

  // For main frame restore scale and visual viewport position
  if (m_frame->isMainFrame()) {
    ScrollOffset visualViewportOffset(
        m_currentItem->visualViewportScrollOffset());

    // If the visual viewport's offset is (-1, -1) it means the history item
    // is an old version of HistoryItem so distribute the scroll between
    // the main frame and the visual viewport as best as we can.
    if (visualViewportOffset.width() == -1 &&
        visualViewportOffset.height() == -1) {
      visualViewportOffset =
          m_currentItem->scrollOffset() -
          view->layoutViewportScrollableArea()->scrollOffset();
    }

    VisualViewport& visualViewport = m_frame->host()->visualViewport();
    if (shouldRestoreScale && shouldRestoreScroll) {
      visualViewport.setScaleAndLocation(m_currentItem->pageScaleFactor(),
                                         FloatPoint(visualViewportOffset));
    } else if (shouldRestoreScale) {
      visualViewport.setScale(m_currentItem->pageScaleFactor());
    } else if (shouldRestoreScroll) {
      visualViewport.setLocation(FloatPoint(visualViewportOffset));
    }

    if (ScrollingCoordinator* scrollingCoordinator =
            m_frame->page()->scrollingCoordinator())
      scrollingCoordinator->frameViewRootLayerDidChange(view);
  }

  documentLoader()->initialScrollState().didRestoreFromHistory = true;
}

String FrameLoader::userAgent() const {
  String userAgent = client()->userAgent();
  InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent);
  return userAgent;
}

void FrameLoader::detach() {
  detachDocumentLoader(m_documentLoader);
  detachDocumentLoader(m_provisionalDocumentLoader);

  Frame* parent = m_frame->tree().parent();
  if (parent && parent->isLocalFrame())
    toLocalFrame(parent)->loader().scheduleCheckCompleted();
  if (m_progressTracker) {
    m_progressTracker->dispose();
    m_progressTracker.clear();
  }

  TRACE_EVENT_OBJECT_DELETED_WITH_ID("loading", "FrameLoader", this);
}

void FrameLoader::loadFailed(DocumentLoader* loader,
                             const ResourceError& error) {
  if (!error.isCancellation() && m_frame->owner()) {
    // FIXME: For now, fallback content doesn't work cross process.
    if (m_frame->owner()->isLocal())
      m_frame->deprecatedLocalOwner()->renderFallbackContent();
  }

  HistoryCommitType historyCommitType = loadTypeToCommitType(m_loadType);
  if (loader == m_provisionalDocumentLoader) {
    client()->dispatchDidFailProvisionalLoad(error, historyCommitType);
    if (loader != m_provisionalDocumentLoader)
      return;
    detachDocumentLoader(m_provisionalDocumentLoader);
    m_progressTracker->progressCompleted();
  } else {
    DCHECK_EQ(loader, m_documentLoader);
    if (m_frame->document()->parser())
      m_frame->document()->parser()->stopParsing();
    m_documentLoader->setSentDidFinishLoad();
    if (!m_provisionalDocumentLoader && m_frame->isLoading()) {
      client()->dispatchDidFailLoad(error, historyCommitType);
      m_progressTracker->progressCompleted();
    }
  }
  checkCompleted();
}

bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission,
                                                  const String& httpMethod,
                                                  FrameLoadType loadType,
                                                  const KURL& url) {
  // We don't do this if we are submitting a form with method other than "GET",
  // explicitly reloading, currently displaying a frameset, or if the URL does
  // not have a fragment.
  return (!isFormSubmission || equalIgnoringCase(httpMethod, HTTPNames::GET)) &&
         !isReloadLoadType(loadType) && loadType != FrameLoadTypeBackForward &&
         url.hasFragmentIdentifier() &&
         equalIgnoringFragmentIdentifier(m_frame->document()->url(), url)
         // We don't want to just scroll if a link from within a frameset is
         // trying to reload the frameset into _top.
         && !m_frame->document()->isFrameSet();
}

void FrameLoader::processFragment(const KURL& url,
                                  LoadStartType loadStartType) {
  FrameView* view = m_frame->view();
  if (!view)
    return;

  // Leaking scroll position to a cross-origin ancestor would permit the
  // so-called "framesniffing" attack.
  Frame* boundaryFrame =
      url.hasFragmentIdentifier()
          ? m_frame->findUnsafeParentScrollPropagationBoundary()
          : 0;

  // FIXME: Handle RemoteFrames
  if (boundaryFrame && boundaryFrame->isLocalFrame()) {
    toLocalFrame(boundaryFrame)
        ->view()
        ->setSafeToPropagateScrollToParent(false);
  }

  // If scroll position is restored from history fragment or scroll
  // restoration type is manual, then we should not override it unless this
  // is a same document reload.
  bool shouldScrollToFragment =
      (loadStartType == NavigationWithinSameDocument &&
       !isBackForwardLoadType(m_loadType)) ||
      (documentLoader() &&
       !documentLoader()->initialScrollState().didRestoreFromHistory &&
       !(m_currentItem &&
         m_currentItem->scrollRestorationType() == ScrollRestorationManual));

  view->processUrlFragment(url, shouldScrollToFragment
                                    ? FrameView::UrlFragmentScroll
                                    : FrameView::UrlFragmentDontScroll);

  if (boundaryFrame && boundaryFrame->isLocalFrame())
    toLocalFrame(boundaryFrame)->view()->setSafeToPropagateScrollToParent(true);
}

bool FrameLoader::shouldClose(bool isReload) {
  Page* page = m_frame->page();
  if (!page || !page->chromeClient().canOpenBeforeUnloadConfirmPanel())
    return true;

  // Store all references to each subframe in advance since beforeunload's event
  // handler may modify frame
  HeapVector<Member<LocalFrame>> targetFrames;
  targetFrames.append(m_frame);
  for (Frame* child = m_frame->tree().firstChild(); child;
       child = child->tree().traverseNext(m_frame)) {
    // FIXME: There is not yet any way to dispatch events to out-of-process
    // frames.
    if (child->isLocalFrame())
      targetFrames.append(toLocalFrame(child));
  }

  bool shouldClose = false;
  {
    NavigationDisablerForUnload navigationDisabler;
    size_t i;

    bool didAllowNavigation = false;
    for (i = 0; i < targetFrames.size(); i++) {
      if (!targetFrames[i]->tree().isDescendantOf(m_frame))
        continue;
      if (!targetFrames[i]->document()->dispatchBeforeUnloadEvent(
              page->chromeClient(), isReload, didAllowNavigation))
        break;
    }

    if (i == targetFrames.size())
      shouldClose = true;
  }

  return shouldClose;
}

bool FrameLoader::shouldContinueForNavigationPolicy(
    const ResourceRequest& request,
    const SubstituteData& substituteData,
    DocumentLoader* loader,
    ContentSecurityPolicyDisposition shouldCheckMainWorldContentSecurityPolicy,
    NavigationType type,
    NavigationPolicy policy,
    bool replacesCurrentHistoryItem,
    bool isClientRedirect,
    HTMLFormElement* form) {
  m_isNavigationHandledByClient = false;

  // Don't ask if we are loading an empty URL.
  if (request.url().isEmpty() || substituteData.isValid())
    return true;

  // If we're loading content into |m_frame| (NavigationPolicyCurrentTab), check
  // against the parent's Content Security Policy and kill the load if that
  // check fails, unless we should bypass the main world's CSP.
  if (policy == NavigationPolicyCurrentTab &&
      shouldCheckMainWorldContentSecurityPolicy == CheckContentSecurityPolicy) {
    Frame* parentFrame = m_frame->tree().parent();
    if (parentFrame) {
      ContentSecurityPolicy* parentPolicy =
          parentFrame->securityContext()->contentSecurityPolicy();
      if (!parentPolicy->allowFrameFromSource(request.url(),
                                              request.redirectStatus())) {
        // Fire a load event, as timing attacks would otherwise reveal that the
        // frame was blocked. This way, it looks like every other cross-origin
        // page load.
        m_frame->document()->enforceSandboxFlags(SandboxOrigin);
        m_frame->owner()->dispatchLoad();
        return false;
      }
    }
  }

  bool isFormSubmission = type == NavigationTypeFormSubmitted ||
                          type == NavigationTypeFormResubmitted;
  if (isFormSubmission &&
      !m_frame->document()->contentSecurityPolicy()->allowFormAction(
          request.url()))
    return false;

  policy = client()->decidePolicyForNavigation(request, loader, type, policy,
                                               replacesCurrentHistoryItem,
                                               isClientRedirect);
  if (policy == NavigationPolicyCurrentTab)
    return true;
  if (policy == NavigationPolicyIgnore)
    return false;
  if (policy == NavigationPolicyHandledByClient) {
    m_isNavigationHandledByClient = true;
    // Mark the frame as loading since the embedder is handling the navigation.
    m_progressTracker->progressStarted();

    // If this is a form submit, dispatch that a form is being submitted
    // since the embedder is handling the navigation.
    if (form)
      client()->dispatchWillSubmitForm(form);

    return false;
  }
  if (!LocalDOMWindow::allowPopUp(*m_frame) &&
      !UserGestureIndicator::utilizeUserGesture())
    return false;
  client()->loadURLExternally(request, policy, String(),
                              replacesCurrentHistoryItem);
  return false;
}

void FrameLoader::startLoad(FrameLoadRequest& frameLoadRequest,
                            FrameLoadType type,
                            NavigationPolicy navigationPolicy) {
  DCHECK(client()->hasWebView());
  if (m_frame->document()->pageDismissalEventBeingDispatched() !=
      Document::NoDismissal)
    return;

  NavigationType navigationType = determineNavigationType(
      type,
      frameLoadRequest.resourceRequest().httpBody() || frameLoadRequest.form(),
      frameLoadRequest.triggeringEvent());
  frameLoadRequest.resourceRequest().setRequestContext(
      determineRequestContextFromNavigationType(navigationType));
  frameLoadRequest.resourceRequest().setFrameType(
      m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel
                             : WebURLRequest::FrameTypeNested);
  ResourceRequest& request = frameLoadRequest.resourceRequest();

  // Record the latest requiredCSP value that will be used when sending this
  // request.
  recordLatestRequiredCSP();
  modifyRequestForCSP(request, nullptr);
  if (!shouldContinueForNavigationPolicy(
          request, frameLoadRequest.substituteData(), nullptr,
          frameLoadRequest.shouldCheckMainWorldContentSecurityPolicy(),
          navigationType, navigationPolicy,
          type == FrameLoadTypeReplaceCurrentItem,
          frameLoadRequest.clientRedirect() ==
              ClientRedirectPolicy::ClientRedirect,
          frameLoadRequest.form()))
    return;

  m_frame->document()->cancelParsing();
  detachDocumentLoader(m_provisionalDocumentLoader);

  // beforeunload fired above, and detaching a DocumentLoader can fire events,
  // which can detach this frame.
  if (!m_frame->host())
    return;

  m_provisionalDocumentLoader = client()->createDocumentLoader(
      m_frame, request, frameLoadRequest.substituteData().isValid()
                            ? frameLoadRequest.substituteData()
                            : defaultSubstituteDataForURL(request.url()),
      frameLoadRequest.clientRedirect());
  m_provisionalDocumentLoader->setNavigationType(navigationType);
  m_provisionalDocumentLoader->setReplacesCurrentHistoryItem(
      type == FrameLoadTypeReplaceCurrentItem);
  m_frame->navigationScheduler().cancel();
  m_checkTimer.stop();

  m_loadType = type;

  if (frameLoadRequest.form())
    client()->dispatchWillSubmitForm(frameLoadRequest.form());

  m_progressTracker->progressStarted();
  m_provisionalDocumentLoader->appendRedirect(
      m_provisionalDocumentLoader->request().url());
  client()->dispatchDidStartProvisionalLoad();
  DCHECK(m_provisionalDocumentLoader);
  m_provisionalDocumentLoader->startLoadingMainResource();

  takeObjectSnapshot();
}

void FrameLoader::applyUserAgent(ResourceRequest& request) {
  String userAgent = this->userAgent();
  DCHECK(!userAgent.isNull());
  request.setHTTPUserAgent(AtomicString(userAgent));
}

bool FrameLoader::shouldInterruptLoadForXFrameOptions(
    const String& content,
    const KURL& url,
    unsigned long requestIdentifier) {
  UseCounter::count(m_frame->domWindow()->document(),
                    UseCounter::XFrameOptions);

  Frame* topFrame = m_frame->tree().top();
  if (m_frame == topFrame)
    return false;

  XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);

  switch (disposition) {
    case XFrameOptionsSameOrigin: {
      UseCounter::count(m_frame->domWindow()->document(),
                        UseCounter::XFrameOptionsSameOrigin);
      RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
      // Out-of-process ancestors are always a different origin.
      if (!topFrame->isLocalFrame() ||
          !origin->isSameSchemeHostPort(
              toLocalFrame(topFrame)->document()->getSecurityOrigin()))
        return true;
      for (Frame* frame = m_frame->tree().parent(); frame;
           frame = frame->tree().parent()) {
        if (!frame->isLocalFrame() ||
            !origin->isSameSchemeHostPort(
                toLocalFrame(frame)->document()->getSecurityOrigin())) {
          UseCounter::count(
              m_frame->domWindow()->document(),
              UseCounter::XFrameOptionsSameOriginWithBadAncestorChain);
          break;
        }
      }
      return false;
    }
    case XFrameOptionsDeny:
      return true;
    case XFrameOptionsAllowAll:
      return false;
    case XFrameOptionsConflict: {
      ConsoleMessage* consoleMessage = ConsoleMessage::createForRequest(
          JSMessageSource, ErrorMessageLevel,
          "Multiple 'X-Frame-Options' headers with conflicting values ('" +
              content + "') encountered when loading '" + url.elidedString() +
              "'. Falling back to 'DENY'.",
          url, requestIdentifier);
      m_frame->document()->addConsoleMessage(consoleMessage);
      return true;
    }
    case XFrameOptionsInvalid: {
      ConsoleMessage* consoleMessage = ConsoleMessage::createForRequest(
          JSMessageSource, ErrorMessageLevel,
          "Invalid 'X-Frame-Options' header encountered when loading '" +
              url.elidedString() + "': '" + content +
              "' is not a recognized directive. The header will be ignored.",
          url, requestIdentifier);
      m_frame->document()->addConsoleMessage(consoleMessage);
      return false;
    }
    default:
      NOTREACHED();
      return false;
  }
}

bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const {
  return m_currentItem && url == m_currentItem->url();
}

bool FrameLoader::shouldTreatURLAsSrcdocDocument(const KURL& url) const {
  if (!url.isAboutSrcdocURL())
    return false;
  HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
  if (!isHTMLIFrameElement(ownerElement))
    return false;
  return ownerElement->fastHasAttribute(srcdocAttr);
}

void FrameLoader::dispatchDocumentElementAvailable() {
  ScriptForbiddenScope forbidScripts;
  client()->documentElementAvailable();
}

void FrameLoader::runScriptsAtDocumentElementAvailable() {
  client()->runScriptsAtDocumentElementAvailable();
  // The frame might be detached at this point.
}

void FrameLoader::dispatchDidClearDocumentOfWindowObject() {
  if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript))
    return;

  Settings* settings = m_frame->settings();
  if (settings && settings->forceMainWorldInitialization())
    m_frame->script().initializeMainWorld();
  InspectorInstrumentation::didClearDocumentOfWindowObject(m_frame);

  if (m_dispatchingDidClearWindowObjectInMainWorld)
    return;
  AutoReset<bool> inDidClearWindowObject(
      &m_dispatchingDidClearWindowObjectInMainWorld, true);
  // We just cleared the document, not the entire window object, but for the
  // embedder that's close enough.
  client()->dispatchDidClearWindowObjectInMainWorld();
}

void FrameLoader::dispatchDidClearWindowObjectInMainWorld() {
  if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript))
    return;

  if (m_dispatchingDidClearWindowObjectInMainWorld)
    return;
  AutoReset<bool> inDidClearWindowObject(
      &m_dispatchingDidClearWindowObjectInMainWorld, true);
  client()->dispatchDidClearWindowObjectInMainWorld();
}

SandboxFlags FrameLoader::effectiveSandboxFlags() const {
  SandboxFlags flags = m_forcedSandboxFlags;
  if (FrameOwner* frameOwner = m_frame->owner())
    flags |= frameOwner->getSandboxFlags();
  // Frames need to inherit the sandbox flags of their parent frame.
  if (Frame* parentFrame = m_frame->tree().parent())
    flags |= parentFrame->securityContext()->getSandboxFlags();
  return flags;
}

WebInsecureRequestPolicy FrameLoader::getInsecureRequestPolicy() const {
  Frame* parentFrame = m_frame->tree().parent();
  if (!parentFrame)
    return kLeaveInsecureRequestsAlone;

  return parentFrame->securityContext()->getInsecureRequestPolicy();
}

SecurityContext::InsecureNavigationsSet*
FrameLoader::insecureNavigationsToUpgrade() const {
  DCHECK(m_frame);
  Frame* parentFrame = m_frame->tree().parent();
  if (!parentFrame)
    return nullptr;

  // FIXME: We need a way to propagate insecure requests policy flags to
  // out-of-process frames. For now, we'll always use default behavior.
  if (!parentFrame->isLocalFrame())
    return nullptr;

  DCHECK(toLocalFrame(parentFrame)->document());
  return toLocalFrame(parentFrame)->document()->insecureNavigationsToUpgrade();
}

void FrameLoader::modifyRequestForCSP(ResourceRequest& resourceRequest,
                                      Document* document) const {
  if (RuntimeEnabledFeatures::embedderCSPEnforcementEnabled() &&
      !requiredCSP().isEmpty()) {
    // TODO(amalika): Strengthen this DCHECK that requiredCSP has proper format
    DCHECK(requiredCSP().getString().containsOnlyASCII());
    resourceRequest.setHTTPHeaderField(HTTPNames::Embedding_CSP, requiredCSP());
  }

  // Tack an 'Upgrade-Insecure-Requests' header to outgoing navigational
  // requests, as described in
  // https://w3c.github.io/webappsec/specs/upgrade/#feature-detect
  if (resourceRequest.frameType() != WebURLRequest::FrameTypeNone) {
    // Early return if the request has already been upgraded.
    if (!resourceRequest.httpHeaderField(HTTPNames::Upgrade_Insecure_Requests)
             .isNull()) {
      return;
    }

    resourceRequest.setHTTPHeaderField(HTTPNames::Upgrade_Insecure_Requests,
                                       "1");
  }

  upgradeInsecureRequest(resourceRequest, document);
}

void FrameLoader::upgradeInsecureRequest(ResourceRequest& resourceRequest,
                                         Document* document) const {
  KURL url = resourceRequest.url();

  // If we don't yet have an |m_document| (because we're loading an iframe, for
  // instance), check the FrameLoader's policy.
  WebInsecureRequestPolicy relevantPolicy =
      document ? document->getInsecureRequestPolicy()
               : getInsecureRequestPolicy();
  SecurityContext::InsecureNavigationsSet* relevantNavigationSet =
      document ? document->insecureNavigationsToUpgrade()
               : insecureNavigationsToUpgrade();

  if (url.protocolIs("http") && relevantPolicy & kUpgradeInsecureRequests) {
    // We always upgrade requests that meet any of the following criteria:
    //
    // 1. Are for subresources (including nested frames).
    // 2. Are form submissions.
    // 3. Whose hosts are contained in the document's InsecureNavigationSet.
    if (resourceRequest.frameType() == WebURLRequest::FrameTypeNone ||
        resourceRequest.frameType() == WebURLRequest::FrameTypeNested ||
        resourceRequest.requestContext() == WebURLRequest::RequestContextForm ||
        (!url.host().isNull() &&
         relevantNavigationSet->contains(url.host().impl()->hash()))) {
      UseCounter::count(document,
                        UseCounter::UpgradeInsecureRequestsUpgradedRequest);
      url.setProtocol("https");
      if (url.port() == 80)
        url.setPort(443);
      resourceRequest.setURL(url);
    }
  }
}

void FrameLoader::recordLatestRequiredCSP() {
  m_requiredCSP = m_frame->owner() ? m_frame->owner()->csp() : nullAtom;
}

std::unique_ptr<TracedValue> FrameLoader::toTracedValue() const {
  std::unique_ptr<TracedValue> tracedValue = TracedValue::create();
  tracedValue->beginDictionary("frame");
  tracedValue->setString(
      "id_ref",
      String::format(
          "0x%" PRIx64,
          static_cast<uint64_t>(reinterpret_cast<uintptr_t>(m_frame.get()))));
  tracedValue->endDictionary();
  tracedValue->setBoolean("isLoadingMainFrame", isLoadingMainFrame());
  tracedValue->setString("stateMachine", m_stateMachine.toString());
  tracedValue->setString("provisionalDocumentLoaderURL",
                         m_provisionalDocumentLoader
                             ? m_provisionalDocumentLoader->url()
                             : String());
  tracedValue->setString("documentLoaderURL",
                         m_documentLoader ? m_documentLoader->url() : String());
  return tracedValue;
}

inline void FrameLoader::takeObjectSnapshot() const {
  TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("loading", "FrameLoader", this,
                                      toTracedValue());
}

}  // namespace blink
