// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/test/navigation_simulator_impl.h"

#include <utility>
#include "base/bind.h"
#include "base/debug/stack_trace.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/browser/renderer_host/debug_urls.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/frame_messages.h"
#include "content/common/navigation_params.h"
#include "content/common/navigation_params_utils.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/navigation_policy.h"
#include "content/public/common/url_utils.h"
#include "content/test/test_navigation_url_loader.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_web_contents.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/load_flags.h"
#include "net/url_request/redirect_info.h"
#include "services/metrics/public/cpp/ukm_recorder.h"

namespace content {

namespace {

class NavigationThrottleCallbackRunner : public NavigationThrottle {
 public:
  NavigationThrottleCallbackRunner(
      NavigationHandle* handle,
      base::OnceClosure on_will_start_request,
      const base::RepeatingClosure& on_will_redirect_request,
      base::OnceClosure on_will_fail_request,
      base::OnceClosure on_will_process_response)
      : NavigationThrottle(handle),
        on_will_start_request_(std::move(on_will_start_request)),
        on_will_redirect_request_(on_will_redirect_request),
        on_will_fail_request_(std::move(on_will_fail_request)),
        on_will_process_response_(std::move(on_will_process_response)) {}

  NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
    std::move(on_will_start_request_).Run();
    return NavigationThrottle::PROCEED;
  }

  NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override {
    on_will_redirect_request_.Run();
    return NavigationThrottle::PROCEED;
  }

  NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
    std::move(on_will_fail_request_).Run();
    return NavigationThrottle::PROCEED;
  }

  NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
    std::move(on_will_process_response_).Run();
    return NavigationThrottle::PROCEED;
  }

  const char* GetNameForLogging() override {
    return "NavigationThrottleCallbackRunner";
  }

 private:
  base::OnceClosure on_will_start_request_;
  base::RepeatingClosure on_will_redirect_request_;
  base::OnceClosure on_will_fail_request_;
  base::OnceClosure on_will_process_response_;
};

int64_t g_unique_identifier = 0;

FrameTreeNode* GetFrameTreeNodeForPendingEntry(WebContentsImpl* contents) {
  NavigationEntryImpl* pending_entry =
      contents->GetController().GetPendingEntry();
  int frame_tree_node_id = pending_entry->frame_tree_node_id();
  FrameTree* frame_tree = contents->GetFrameTree();
  if (frame_tree_node_id == FrameTreeNode::kFrameTreeNodeInvalidId)
    return frame_tree->root();
  return frame_tree->FindByID(frame_tree_node_id);
}

}  // namespace

// static
RenderFrameHost* NavigationSimulator::NavigateAndCommitFromBrowser(
    WebContents* web_contents,
    const GURL& url) {
  auto simulator =
      NavigationSimulatorImpl::CreateBrowserInitiated(url, web_contents);
  simulator->Commit();
  return simulator->GetFinalRenderFrameHost();
}

// static
RenderFrameHost* NavigationSimulator::Reload(WebContents* web_contents) {
  NavigationEntry* entry =
      web_contents->GetController().GetLastCommittedEntry();
  CHECK(entry);
  auto simulator = NavigationSimulatorImpl::CreateBrowserInitiated(
      entry->GetURL(), web_contents);
  simulator->SetReloadType(ReloadType::NORMAL);
  simulator->Commit();
  return simulator->GetFinalRenderFrameHost();
}

// static
RenderFrameHost* NavigationSimulator::GoBack(WebContents* web_contents) {
  return GoToOffset(web_contents, -1);
}

// static
RenderFrameHost* NavigationSimulator::GoForward(WebContents* web_contents) {
  return GoToOffset(web_contents, 1);
}

// static
RenderFrameHost* NavigationSimulator::GoToOffset(WebContents* web_contents,
                                                 int offset) {
  auto simulator =
      NavigationSimulatorImpl::CreateHistoryNavigation(offset, web_contents);
  simulator->Commit();
  return simulator->GetFinalRenderFrameHost();
}

// static
RenderFrameHost* NavigationSimulator::NavigateAndCommitFromDocument(
    const GURL& original_url,
    RenderFrameHost* render_frame_host) {
  auto simulator = NavigationSimulator::CreateRendererInitiated(
      original_url, render_frame_host);
  simulator->Commit();
  return simulator->GetFinalRenderFrameHost();
}

// static
RenderFrameHost* NavigationSimulator::NavigateAndFailFromBrowser(
    WebContents* web_contents,
    const GURL& url,
    int net_error_code) {
  auto simulator =
      NavigationSimulator::CreateBrowserInitiated(url, web_contents);
  simulator->Fail(net_error_code);
  if (net_error_code == net::ERR_ABORTED)
    return nullptr;
  simulator->CommitErrorPage();
  return simulator->GetFinalRenderFrameHost();
}

// static
RenderFrameHost* NavigationSimulator::ReloadAndFail(WebContents* web_contents,
                                                    int net_error_code) {
  NavigationEntry* entry =
      web_contents->GetController().GetLastCommittedEntry();
  CHECK(entry);
  auto simulator = NavigationSimulator::CreateBrowserInitiated(entry->GetURL(),
                                                               web_contents);
  simulator->SetReloadType(ReloadType::NORMAL);
  simulator->Fail(net_error_code);
  if (net_error_code == net::ERR_ABORTED)
    return nullptr;
  simulator->CommitErrorPage();
  return simulator->GetFinalRenderFrameHost();
}

// static
RenderFrameHost* NavigationSimulator::GoBackAndFail(WebContents* web_contents,
                                                    int net_error_code) {
  return GoToOffsetAndFail(web_contents, -1, net_error_code);
}

// static
RenderFrameHost* NavigationSimulator::GoToOffsetAndFail(
    WebContents* web_contents,
    int offset,
    int net_error_code) {
  auto simulator =
      NavigationSimulator::CreateHistoryNavigation(offset, web_contents);
  simulator->Fail(net_error_code);
  if (net_error_code == net::ERR_ABORTED)
    return nullptr;
  simulator->CommitErrorPage();
  return simulator->GetFinalRenderFrameHost();
}

// static
RenderFrameHost* NavigationSimulator::NavigateAndFailFromDocument(
    const GURL& original_url,
    int net_error_code,
    RenderFrameHost* render_frame_host) {
  auto simulator = NavigationSimulator::CreateRendererInitiated(
      original_url, render_frame_host);
  simulator->Fail(net_error_code);
  if (net_error_code == net::ERR_ABORTED)
    return nullptr;
  simulator->CommitErrorPage();
  return simulator->GetFinalRenderFrameHost();
}

// static
std::unique_ptr<NavigationSimulator>
NavigationSimulator::CreateBrowserInitiated(const GURL& original_url,
                                            WebContents* web_contents) {
  return NavigationSimulatorImpl::CreateBrowserInitiated(original_url,
                                                         web_contents);
}

// static
std::unique_ptr<NavigationSimulatorImpl>
NavigationSimulatorImpl::CreateBrowserInitiated(const GURL& original_url,
                                                WebContents* web_contents) {
  return std::unique_ptr<NavigationSimulatorImpl>(new NavigationSimulatorImpl(
      original_url, true /* browser_initiated */,
      static_cast<WebContentsImpl*>(web_contents), nullptr));
}

// static
std::unique_ptr<NavigationSimulator>
NavigationSimulator::CreateHistoryNavigation(int offset,
                                             WebContents* web_contents) {
  return NavigationSimulatorImpl::CreateHistoryNavigation(offset, web_contents);
}

// static
std::unique_ptr<NavigationSimulatorImpl>
NavigationSimulatorImpl::CreateHistoryNavigation(int offset,
                                                 WebContents* web_contents) {
  auto simulator =
      NavigationSimulatorImpl::CreateBrowserInitiated(GURL(), web_contents);
  simulator->SetSessionHistoryOffset(offset);
  return simulator;
}

// static
std::unique_ptr<NavigationSimulator>
NavigationSimulator::CreateRendererInitiated(
    const GURL& original_url,
    RenderFrameHost* render_frame_host) {
  return NavigationSimulatorImpl::CreateRendererInitiated(original_url,
                                                          render_frame_host);
}

// static
std::unique_ptr<NavigationSimulatorImpl>
NavigationSimulatorImpl::CreateRendererInitiated(
    const GURL& original_url,
    RenderFrameHost* render_frame_host) {
  return std::unique_ptr<NavigationSimulatorImpl>(new NavigationSimulatorImpl(
      original_url, false /* browser_initiated */,
      static_cast<WebContentsImpl*>(
          WebContents::FromRenderFrameHost(render_frame_host)),
      static_cast<TestRenderFrameHost*>(render_frame_host)));
}

// static
std::unique_ptr<NavigationSimulator> NavigationSimulator::CreateFromPending(
    WebContents* contents) {
  return NavigationSimulatorImpl::CreateFromPending(contents);
}

// static
std::unique_ptr<NavigationSimulatorImpl>
NavigationSimulatorImpl::CreateFromPending(WebContents* contents) {
  WebContentsImpl* contents_impl = static_cast<WebContentsImpl*>(contents);

  FrameTreeNode* frame_tree_node =
      GetFrameTreeNodeForPendingEntry(contents_impl);
  return NavigationSimulatorImpl::CreateFromPendingInFrame(frame_tree_node);
}

// static
std::unique_ptr<NavigationSimulatorImpl>
NavigationSimulatorImpl::CreateFromPendingInFrame(
    FrameTreeNode* frame_tree_node) {
  CHECK(frame_tree_node);
  TestRenderFrameHost* test_frame_host =
      static_cast<TestRenderFrameHost*>(frame_tree_node->current_frame_host());
  CHECK(test_frame_host);
  NavigationRequest* request = frame_tree_node->navigation_request();
  // It is possible to not have a NavigationRequest in the frame tree node if
  // it did not go to the network (such as about:blank). In that case it is
  // already in the RenderFrameHost.
  if (!request)
    request = test_frame_host->navigation_requests().begin()->second.get();
  CHECK(request);

  // Simulate the BeforeUnload completion callback if needed.
  if (request->state() == NavigationRequest::WAITING_FOR_RENDERER_RESPONSE)
    test_frame_host->SimulateBeforeUnloadCompleted(true /* proceed */);

  auto simulator = base::WrapUnique(new NavigationSimulatorImpl(
      GURL(), request->browser_initiated(),
      WebContentsImpl::FromFrameTreeNode(frame_tree_node), test_frame_host));
  simulator->frame_tree_node_ = frame_tree_node;
  simulator->InitializeFromStartedRequest(request);
  return simulator;
}

NavigationSimulatorImpl::NavigationSimulatorImpl(
    const GURL& original_url,
    bool browser_initiated,
    WebContentsImpl* web_contents,
    TestRenderFrameHost* render_frame_host)
    : WebContentsObserver(web_contents),
      web_contents_(web_contents),
      render_frame_host_(render_frame_host),
      frame_tree_node_(render_frame_host
                           ? render_frame_host->frame_tree_node()
                           : web_contents->GetMainFrame()->frame_tree_node()),
      request_(nullptr),
      original_url_(original_url),
      navigation_url_(original_url),
      initial_method_("GET"),
      browser_initiated_(browser_initiated),
      referrer_(blink::mojom::Referrer::New()),
      transition_(browser_initiated ? ui::PAGE_TRANSITION_TYPED
                                    : ui::PAGE_TRANSITION_LINK),
      contents_mime_type_("text/html"),
      load_url_params_(nullptr) {
  net::IPAddress address;
  CHECK(address.AssignFromIPLiteral("2001:db8::1"));
  remote_endpoint_ = net::IPEndPoint(address, 80);

  // For renderer-initiated navigation, the RenderFrame must be initialized. Do
  // it if it hasn't happened yet.
  if (!browser_initiated)
    render_frame_host->InitializeRenderFrameIfNeeded();

  if (render_frame_host && render_frame_host->GetParent()) {
    if (!render_frame_host->frame_tree_node()->has_committed_real_load())
      transition_ = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
    else
      transition_ = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
  }

  browser_interface_broker_receiver_ =
      mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
          .InitWithNewPipeAndPassReceiver();
}

NavigationSimulatorImpl::~NavigationSimulatorImpl() {}

void NavigationSimulatorImpl::InitializeFromStartedRequest(
    NavigationRequest* request) {
  CHECK(request);
  request_ = request;
  CHECK(request_->IsNavigationStarted());
  CHECK_EQ(web_contents_, request_->GetDelegate());
  CHECK(render_frame_host_);
  CHECK_EQ(frame_tree_node_, request_->frame_tree_node());
  state_ = STARTED;
  original_url_ = request->commit_params().original_url;
  navigation_url_ = request_->GetURL();
  // |remote_endpoint_| cannot be inferred from the request.
  // |initial_method_| cannot be set after the request has started.
  browser_initiated_ = request_->browser_initiated();
  // |same_document_| should always be false here.
  referrer_ = request_->common_params().referrer.Clone();
  transition_ = request_->GetPageTransition();
  // |reload_type_| cannot be set after the request has started.
  // |session_history_offset_| cannot be set after the request has started.
  has_user_gesture_ = request_->HasUserGesture();
  // |contents_mime_type_| cannot be inferred from the request.

  // Add a throttle to count NavigationThrottle calls count. Bump
  // num_did_start_navigation to account for the fact that the navigation handle
  // has already been created.
  num_did_start_navigation_called_++;
  RegisterTestThrottle(request);
  PrepareCompleteCallbackOnRequest();
}

void NavigationSimulatorImpl::RegisterTestThrottle(NavigationRequest* request) {
  request->RegisterThrottleForTesting(
      std::make_unique<NavigationThrottleCallbackRunner>(
          request,
          base::BindOnce(&NavigationSimulatorImpl::OnWillStartRequest,
                         weak_factory_.GetWeakPtr()),
          base::BindRepeating(&NavigationSimulatorImpl::OnWillRedirectRequest,
                              weak_factory_.GetWeakPtr()),
          base::BindOnce(&NavigationSimulatorImpl::OnWillFailRequest,
                         weak_factory_.GetWeakPtr()),
          base::BindOnce(&NavigationSimulatorImpl::OnWillProcessResponse,
                         weak_factory_.GetWeakPtr())));
}

void NavigationSimulatorImpl::Start() {
  CHECK(state_ == INITIALIZATION || state_ == WAITING_BEFORE_UNLOAD)
      << "NavigationSimulatorImpl::Start should only be called once.";

  if (browser_initiated_) {
    if (!SimulateBrowserInitiatedStart())
      return;
  } else {
    if (!SimulateRendererInitiatedStart())
      return;
  }
  state_ = STARTED;

  CHECK(request_);
  if (IsRendererDebugURL(navigation_url_))
    return;

  if (same_document_ || !IsURLHandledByNetworkStack(navigation_url_) ||
      navigation_url_.IsAboutBlank()) {
    CHECK_EQ(1, num_did_start_navigation_called_);
    return;
  }

  MaybeWaitForThrottleChecksComplete(base::BindOnce(
      &NavigationSimulatorImpl::StartComplete, weak_factory_.GetWeakPtr()));
}

void NavigationSimulatorImpl::StartComplete() {
  CHECK_EQ(1, num_did_start_navigation_called_);
  if (GetLastThrottleCheckResult().action() == NavigationThrottle::PROCEED) {
    CHECK_EQ(1, num_will_start_request_called_);
  } else {
    state_ = FAILED;
  }
}

void NavigationSimulatorImpl::Redirect(const GURL& new_url) {
  CHECK_LE(state_, STARTED) << "NavigationSimulatorImpl::Redirect should be "
                               "called before Fail or Commit";
  CHECK_EQ(0, num_did_finish_navigation_called_)
      << "NavigationSimulatorImpl::Redirect cannot be called after the "
         "navigation has finished";

  if (state_ < STARTED) {
    Start();
    if (state_ == FAILED)
      return;
  }

  navigation_url_ = new_url;
  int previous_num_will_redirect_request_called =
      num_will_redirect_request_called_;
  int previous_did_redirect_navigation_called =
      num_did_redirect_navigation_called_;

  PrepareCompleteCallbackOnRequest();
  NavigationRequest* request = frame_tree_node_->navigation_request();
  CHECK(request) << "Trying to redirect a navigation that does not go to the "
                    "network stack.";

  TestNavigationURLLoader* url_loader =
      static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
  CHECK(url_loader);

  net::RedirectInfo redirect_info;
  redirect_info.status_code = 302;
  redirect_info.new_method = "GET";
  redirect_info.new_url = new_url;
  redirect_info.new_site_for_cookies = net::SiteForCookies::FromUrl(new_url);
  redirect_info.new_referrer = referrer_->url.spec();
  redirect_info.new_referrer_policy =
      Referrer::ReferrerPolicyForUrlRequest(referrer_->policy);
  auto response = network::mojom::URLResponseHead::New();
  response->connection_info = http_connection_info_;
  response->ssl_info = ssl_info_;

  url_loader->CallOnRequestRedirected(redirect_info, std::move(response));

  MaybeWaitForThrottleChecksComplete(base::BindOnce(
      &NavigationSimulatorImpl::RedirectComplete, weak_factory_.GetWeakPtr(),
      previous_num_will_redirect_request_called,
      previous_did_redirect_navigation_called));
}

void NavigationSimulatorImpl::RedirectComplete(
    int previous_num_will_redirect_request_called,
    int previous_did_redirect_navigation_called) {
  if (GetLastThrottleCheckResult().action() == NavigationThrottle::PROCEED) {
    CHECK_EQ(previous_num_will_redirect_request_called + 1,
             num_will_redirect_request_called_);
    CHECK_EQ(previous_did_redirect_navigation_called + 1,
             num_did_redirect_navigation_called_);
  } else {
    state_ = FAILED;
  }
}

void NavigationSimulatorImpl::ReadyToCommit() {
  CHECK_LE(state_, STARTED)
      << "NavigationSimulatorImpl::ReadyToCommit can only "
         "be called once, and cannot be called after "
         "NavigationSimulatorImpl::Fail";
  CHECK_EQ(0, num_did_finish_navigation_called_)
      << "NavigationSimulatorImpl::ReadyToCommit cannot be called after the "
         "navigation has finished";

  if (state_ < STARTED) {
    if (block_invoking_before_unload_completed_callback_ &&
        state_ == WAITING_BEFORE_UNLOAD) {
      // The user should have simulated the BeforeUnloadCompleted by themselves.
      // Finish the initialization and skip the Start simulation.
      InitializeFromStartedRequest(request_);
    } else {
      Start();
      if (state_ == FAILED)
        return;
    }
  }

  if (!response_headers_) {
    response_headers_ =
        base::MakeRefCounted<net::HttpResponseHeaders>(std::string());
  }
  response_headers_->SetHeader("Content-Type", contents_mime_type_);
  PrepareCompleteCallbackOnRequest();
  if (frame_tree_node_->navigation_request()) {
    static_cast<TestRenderFrameHost*>(frame_tree_node_->current_frame_host())
        ->PrepareForCommitDeprecatedForNavigationSimulator(
            remote_endpoint_, was_fetched_via_cache_,
            is_signed_exchange_inner_response_, http_connection_info_,
            ssl_info_, response_headers_);
  }

  // Synchronous failure can cause the navigation to finish here.
  if (!request_) {
    state_ = FAILED;
    return;
  }

  bool needs_throttle_checks = !same_document_ &&
                               !navigation_url_.IsAboutBlank() &&
                               IsURLHandledByNetworkStack(navigation_url_);
  auto complete_closure =
      base::BindOnce(&NavigationSimulatorImpl::ReadyToCommitComplete,
                     weak_factory_.GetWeakPtr(), needs_throttle_checks);
  if (needs_throttle_checks) {
    MaybeWaitForThrottleChecksComplete(std::move(complete_closure));
    return;
  }
  std::move(complete_closure).Run();
}

void NavigationSimulatorImpl::ReadyToCommitComplete(bool ran_throttles) {
  if (ran_throttles) {
    if (GetLastThrottleCheckResult().action() != NavigationThrottle::PROCEED) {
      state_ = FAILED;
      return;
    }
    CHECK_EQ(1, num_will_process_response_called_);
    CHECK_EQ(1, num_ready_to_commit_called_);
  }

  request_id_ = request_->GetGlobalRequestID();

  // Update the RenderFrameHost now that we know which RenderFrameHost will
  // commit the navigation.
  render_frame_host_ =
      static_cast<TestRenderFrameHost*>(request_->GetRenderFrameHost());
  state_ = READY_TO_COMMIT;
}

void NavigationSimulatorImpl::Commit() {
  CHECK_LE(state_, READY_TO_COMMIT)
      << "NavigationSimulatorImpl::Commit can only "
         "be called once, and cannot be called "
         "after NavigationSimulatorImpl::Fail";
  CHECK_EQ(0, num_did_finish_navigation_called_)
      << "NavigationSimulatorImpl::Commit cannot be called after the "
         "navigation "
         "has finished";

  if (state_ < READY_TO_COMMIT) {
    ReadyToCommit();
    if (state_ == FAILED || state_ == FINISHED)
      return;
  }

  // Keep a pointer to the current RenderFrameHost that may be pending deletion
  // after commit.
  RenderFrameHostImpl* previous_rfh =
      render_frame_host_->frame_tree_node()->current_frame_host();

  // RenderDocument: Do not dispatch UnloadACK if the navigation was committed
  // in the same SiteInstance. This has already been dispatched during the
  // navigation in the renderer process.
  if (previous_rfh->GetSiteInstance() == render_frame_host_->GetSiteInstance())
    drop_unload_ack_ = true;

  // If the frame is not alive we do not displatch Unload ACK. CommitPending()
  // may be called immediately and delete the old RenderFrameHost, so we need to
  // record that now while we can still access the object.
  if (!previous_rfh->IsRenderFrameLive())
    drop_unload_ack_ = true;

  if (same_document_) {
    browser_interface_broker_receiver_.reset();
  }

  auto params = BuildDidCommitProvisionalLoadParams(
      same_document_ /* same_document */, false /* failed_navigation */,
      render_frame_host_->last_http_status_code());
  render_frame_host_->SimulateCommitProcessed(
      request_, std::move(params),
      std::move(browser_interface_broker_receiver_), same_document_);

  if (previous_rfh)
    SimulateUnloadCompletionCallbackForPreviousFrameIfNeeded(previous_rfh);

  loading_scenario_ =
      TestRenderFrameHost::LoadingScenario::NewDocumentNavigation;
  state_ = FINISHED;
  if (!keep_loading_)
    StopLoading();

  if (!IsRendererDebugURL(navigation_url_))
    CHECK_EQ(1, num_did_finish_navigation_called_);
}

void NavigationSimulatorImpl::AbortCommit() {
  CHECK_LE(state_, FAILED)
      << "NavigationSimulatorImpl::AbortCommit cannot be called after "
         "NavigationSimulatorImpl::Commit or  "
         "NavigationSimulatorImpl::CommitErrorPage.";
  if (state_ < READY_TO_COMMIT) {
    ReadyToCommit();
    if (state_ == FINISHED)
      return;
  }

  CHECK(render_frame_host_)
      << "NavigationSimulatorImpl::AbortCommit can only be "
         "called for navigations that commit.";
  render_frame_host_->AbortCommit(request_);

  state_ = FINISHED;
  StopLoading();

  CHECK_EQ(1, num_did_finish_navigation_called_);
}

void NavigationSimulatorImpl::AbortFromRenderer() {
  CHECK(!browser_initiated_)
      << "NavigationSimulatorImpl::AbortFromRenderer cannot be called for "
         "browser-initiated navigation.";
  CHECK_LE(state_, FAILED)
      << "NavigationSimulatorImpl::AbortFromRenderer cannot be called after "
         "NavigationSimulatorImpl::Commit or  "
         "NavigationSimulatorImpl::CommitErrorPage.";

  was_aborted_ = true;
  request_->RendererAbortedNavigationForTesting();
  state_ = FINISHED;

  CHECK_EQ(1, num_did_finish_navigation_called_);
}

void NavigationSimulatorImpl::Fail(int error_code) {
  CHECK_LE(state_, STARTED) << "NavigationSimulatorImpl::Fail can only be "
                               "called once, and cannot be called after "
                               "NavigationSimulatorImpl::ReadyToCommit";
  CHECK_EQ(0, num_did_finish_navigation_called_)
      << "NavigationSimulatorImpl::Fail cannot be called after the "
         "navigation has finished";
  CHECK(!IsRendererDebugURL(navigation_url_));

  if (state_ == INITIALIZATION)
    Start();

  state_ = FAILED;

  PrepareCompleteCallbackOnRequest();
  CHECK(request_);
  TestNavigationURLLoader* url_loader =
      static_cast<TestNavigationURLLoader*>(request_->loader_for_testing());
  CHECK(url_loader);
  network::URLLoaderCompletionStatus status(error_code);
  status.resolve_error_info = resolve_error_info_;
  status.ssl_info = ssl_info_;
  url_loader->SimulateErrorWithStatus(status);

  auto complete_closure =
      base::BindOnce(&NavigationSimulatorImpl::FailComplete,
                     weak_factory_.GetWeakPtr(), error_code);
  if (error_code != net::ERR_ABORTED) {
    MaybeWaitForThrottleChecksComplete(std::move(complete_closure));
    return;
  }
  std::move(complete_closure).Run();
}

void NavigationSimulatorImpl::FailComplete(int error_code) {
  bool should_result_in_error_page = error_code != net::ERR_ABORTED;
  if (error_code != net::ERR_ABORTED) {
    NavigationThrottle::ThrottleCheckResult result =
        GetLastThrottleCheckResult();
    if (result.action() == NavigationThrottle::CANCEL ||
        result.action() == NavigationThrottle::CANCEL_AND_IGNORE) {
      should_result_in_error_page = false;
    }
  }

  if (should_result_in_error_page) {
    // TODO(clamy): Check that ReadyToCommit has been called once, once the test
    // architecture of NavigationRequest vs NavigationHandle has been clarified.
    // Currently, when auto-advance is off, this function will be called before
    // NavigationRequest::CommitErrorPage which is the one that triggers the
    // call to observers.
    CHECK_EQ(0, num_did_finish_navigation_called_);
    // Update the RenderFrameHost now that we know which RenderFrameHost will
    // commit the error page.
    render_frame_host_ =
        static_cast<TestRenderFrameHost*>(request_->GetRenderFrameHost());
  }
}

void NavigationSimulatorImpl::CommitErrorPage() {
  CHECK_EQ(FAILED, state_)
      << "NavigationSimulatorImpl::CommitErrorPage can only be "
         "called once, and should be called after Fail "
         "has been called";
  CHECK_EQ(0, num_did_finish_navigation_called_)
      << "NavigationSimulatorImpl::CommitErrorPage cannot be called after the "
         "navigation has finished";

  // Keep a pointer to the current RenderFrameHost that may be pending deletion
  // after commit.
  // RenderDocument: The |previous_rfh| might also be immediately deleted after
  // commit, because it has already run its unload handler.
  RenderFrameHostImpl* previous_rfh =
      render_frame_host_->frame_tree_node()->current_frame_host();

  // RenderDocument: Do not dispatch UnloadACK if the navigation was committed
  // in the same SiteInstance. This has already been dispatched during the
  // navigation in the renderer process.
  if (previous_rfh->GetSiteInstance() == render_frame_host_->GetSiteInstance())
    drop_unload_ack_ = true;

  // If the frame is not alive we do not displatch Unload ACK. CommitPending()
  // may be called immediately and delete the old RenderFrameHost, so we need to
  // record that now while we can still access the object.
  if (!previous_rfh->IsRenderFrameLive())
    drop_unload_ack_ = true;

  auto params = BuildDidCommitProvisionalLoadParams(
      false /* same_document */, true /* failed_navigation */,
      render_frame_host_->last_http_status_code());
  render_frame_host_->SimulateCommitProcessed(
      request_, std::move(params),
      std::move(browser_interface_broker_receiver_), false /* same_document */);

  SimulateUnloadCompletionCallbackForPreviousFrameIfNeeded(previous_rfh);

  state_ = FINISHED;
  if (!keep_loading_)
    StopLoading();

  CHECK_EQ(1, num_did_finish_navigation_called_);
}

void NavigationSimulatorImpl::CommitSameDocument() {
  if (!browser_initiated_) {
    CHECK_EQ(INITIALIZATION, state_)
        << "NavigationSimulatorImpl::CommitSameDocument should be the only "
           "navigation event function called on the NavigationSimulatorImpl";
  } else {
    // This function is intended for same document navigations initiating from
    // the renderer. For regular same document navigations simply use Commit().
    Commit();
    return;
  }

  auto params = BuildDidCommitProvisionalLoadParams(
      true /* same_document */, false /* failed_navigation */,
      render_frame_host_->last_http_status_code());

  browser_interface_broker_receiver_.reset();

  render_frame_host_->SimulateCommitProcessed(
      request_, std::move(params),
      mojo::NullReceiver() /* browser_interface_broker_receiver */,
      true /* same_document */);

  // Same-document commits should never hit network-related stages of committing
  // a navigation.
  CHECK_EQ(0, num_will_start_request_called_);
  CHECK_EQ(0, num_will_process_response_called_);
  CHECK_EQ(0, num_ready_to_commit_called_);

  if (num_did_finish_navigation_called_ == 0) {
    // Fail the navigation if it results in a process kill (e.g. see
    // NavigatorTestWithBrowserSideNavigation.CrossSiteClaimWithinPage test).
    state_ = FAILED;
    return;
  }
  loading_scenario_ =
      TestRenderFrameHost::LoadingScenario::kSameDocumentNavigation;
  state_ = FINISHED;
  if (!keep_loading_)
    StopLoading();

  CHECK_EQ(1, num_did_start_navigation_called_);
  CHECK_EQ(1, num_did_finish_navigation_called_);
}

void NavigationSimulatorImpl::SetInitiatorFrame(
    RenderFrameHost* initiator_frame_host) {
  // Browser-initiated navigations are not associated with an initiator frame.
  CHECK(!browser_initiated_);
  CHECK(initiator_frame_host);

  // TODO(https://crbug.com/1072790): Support cross-process initiators here by
  // using NavigationRequest::CreateBrowserInitiated() (like
  // RenderFrameProxyHost does) for the navigation.
  CHECK_EQ(render_frame_host_->GetProcess(), initiator_frame_host->GetProcess())
      << "The initiator frame must belong to the same process as the frame you "
         "are navigating";
  initiator_frame_host_ = initiator_frame_host;
}

void NavigationSimulatorImpl::SetTransition(ui::PageTransition transition) {
  if (frame_tree_node_ && !frame_tree_node_->IsMainFrame()) {
    // Subframe case. The subframe page transition is only set at commit time in
    // the navigation code, so it can be modified later in time.
    CHECK(PageTransitionCoreTypeIs(transition,
                                   ui::PAGE_TRANSITION_AUTO_SUBFRAME) ||
          PageTransitionCoreTypeIs(transition,
                                   ui::PAGE_TRANSITION_MANUAL_SUBFRAME))
        << "The transition type is not appropriate for a subframe";
  } else {
    CHECK_EQ(INITIALIZATION, state_)
        << "The transition cannot be set after the navigation has started";
    CHECK_EQ(ReloadType::NONE, reload_type_)
        << "The transition cannot be specified for reloads";
    CHECK_EQ(0, session_history_offset_)
        << "The transition cannot be specified for back/forward navigations";
  }
  transition_ = transition;
}

void NavigationSimulatorImpl::SetHasUserGesture(bool has_user_gesture) {
  CHECK_EQ(INITIALIZATION, state_) << "The has_user_gesture parameter cannot "
                                      "be set after the navigation has started";
  has_user_gesture_ = has_user_gesture;
}

void NavigationSimulatorImpl::SetReloadType(ReloadType reload_type) {
  CHECK_EQ(INITIALIZATION, state_) << "The reload_type parameter cannot "
                                      "be set after the navigation has started";
  CHECK(browser_initiated_) << "The reload_type parameter can only be set for "
                               "browser-intiated navigations";
  CHECK_EQ(0, session_history_offset_)
      << "The reload_type parameter cannot be set for "
         "session history navigations";
  reload_type_ = reload_type;
  if (reload_type_ != ReloadType::NONE)
    transition_ = ui::PAGE_TRANSITION_RELOAD;
}

void NavigationSimulatorImpl::SetMethod(const std::string& method) {
  CHECK_EQ(INITIALIZATION, state_) << "The method parameter cannot "
                                      "be set after the navigation has started";
  initial_method_ = method;
}

void NavigationSimulatorImpl::SetIsFormSubmission(bool is_form_submission) {
  CHECK_EQ(INITIALIZATION, state_) << "The form submission parameter cannot "
                                      "be set after the navigation has started";
  is_form_submission_ = is_form_submission;
}

void NavigationSimulatorImpl::SetReferrer(blink::mojom::ReferrerPtr referrer) {
  CHECK_LE(state_, STARTED) << "The referrer cannot be set after the "
                               "navigation has committed or has failed";
  referrer_ = std::move(referrer);
}

void NavigationSimulatorImpl::SetSocketAddress(
    const net::IPEndPoint& remote_endpoint) {
  CHECK_LE(state_, STARTED) << "The socket address cannot be set after the "
                               "navigation has committed or failed";
  remote_endpoint_ = remote_endpoint;
}

void NavigationSimulatorImpl::SetWasFetchedViaCache(
    bool was_fetched_via_cache) {
  CHECK_LE(state_, STARTED) << "The was_fetched_via_cache flag cannot be set "
                               "after the navigation has committed or failed";
  was_fetched_via_cache_ = was_fetched_via_cache;
}

void NavigationSimulatorImpl::SetIsSignedExchangeInnerResponse(
    bool is_signed_exchange_inner_response) {
  CHECK_LE(state_, STARTED) << "The signed exchange flag cannot be set after "
                               "the navigation has committed or failed";
  is_signed_exchange_inner_response_ = is_signed_exchange_inner_response;
}

void NavigationSimulatorImpl::SetFeaturePolicyHeader(
    blink::ParsedFeaturePolicy feature_policy_header) {
  CHECK_LE(state_, STARTED) << "The Feature-Policy headers cannot be set after "
                               "the navigation has committed or failed";
  feature_policy_header_ = std::move(feature_policy_header);
}

void NavigationSimulatorImpl::SetContentsMimeType(
    const std::string& contents_mime_type) {
  CHECK_LE(state_, STARTED) << "The contents mime type cannot be set after the "
                               "navigation has committed or failed";
  contents_mime_type_ = contents_mime_type;
}

void NavigationSimulatorImpl::SetResponseHeaders(
    scoped_refptr<net::HttpResponseHeaders> response_headers) {
  CHECK_LE(state_, STARTED) << "The response headers cannot be set after the "
                               "navigation has committed or failed";
  response_headers_ = response_headers;
}

void NavigationSimulatorImpl::SetLoadURLParams(
    NavigationController::LoadURLParams* load_url_params) {
  load_url_params_ = load_url_params;

  // Make sure the internal attributes of NavigationSimulatorImpl match the
  // LoadURLParams that is going to be sent.
  referrer_ = blink::mojom::Referrer::New(load_url_params->referrer.url,
                                          load_url_params->referrer.policy);
  transition_ = load_url_params->transition_type;
}

void NavigationSimulatorImpl::SetAutoAdvance(bool auto_advance) {
  auto_advance_ = auto_advance;
}

void NavigationSimulatorImpl::SetResolveErrorInfo(
    const net::ResolveErrorInfo& resolve_error_info) {
  resolve_error_info_ = resolve_error_info;
}

void NavigationSimulatorImpl::SetSSLInfo(const net::SSLInfo& ssl_info) {
  ssl_info_ = ssl_info;
}

NavigationThrottle::ThrottleCheckResult
NavigationSimulatorImpl::GetLastThrottleCheckResult() {
  return last_throttle_check_result_.value();
}

NavigationRequest* NavigationSimulatorImpl::GetNavigationHandle() {
  CHECK_GE(state_, STARTED);
  return request_;
}

content::GlobalRequestID NavigationSimulatorImpl::GetGlobalRequestID() {
  CHECK_GT(state_, STARTED) << "The GlobalRequestID is not available until "
                               "after the navigation has completed "
                               "WillProcessResponse";
  return request_id_;
}

void NavigationSimulatorImpl::BrowserInitiatedStartAndWaitBeforeUnload() {
  if (reload_type_ != ReloadType::NONE) {
    web_contents_->GetController().Reload(reload_type_,
                                          false /*check_for_repost */);
  } else if (session_history_offset_) {
    web_contents_->GetController().GoToOffset(session_history_offset_);
  } else {
    if (load_url_params_) {
      web_contents_->GetController().LoadURLWithParams(*load_url_params_);
      load_url_params_ = nullptr;
    } else {
      NavigationController::LoadURLParams load_url_params(navigation_url_);
      load_url_params.referrer = Referrer(*referrer_);
      load_url_params.transition_type = transition_;
      if (initial_method_ == "POST")
        load_url_params.load_type = NavigationController::LOAD_TYPE_HTTP_POST;

      web_contents_->GetController().LoadURLWithParams(load_url_params);
    }
  }

  frame_tree_node_ = GetFrameTreeNodeForPendingEntry(web_contents_);
  CHECK(frame_tree_node_);
  render_frame_host_ =
      static_cast<TestRenderFrameHost*>(frame_tree_node_->current_frame_host());

  // The navigation url might have been rewritten by the NavigationController.
  // Update it.
  NavigationController& controller = web_contents_->GetController();
  NavigationEntryImpl* pending_entry =
      static_cast<NavigationEntryImpl*>(controller.GetPendingEntry());
  FrameNavigationEntry* pending_frame_entry =
      pending_entry->GetFrameEntry(frame_tree_node_);
  navigation_url_ = pending_frame_entry->url();

  state_ = WAITING_BEFORE_UNLOAD;
}

void NavigationSimulatorImpl::DidStartNavigation(
    NavigationHandle* navigation_handle) {
  // Check if this navigation is the one we're simulating.
  if (request_)
    return;

  NavigationRequest* request = NavigationRequest::From(navigation_handle);

  if (request->frame_tree_node() != frame_tree_node_)
    return;

  request_ = request;
  num_did_start_navigation_called_++;

  // Add a throttle to count NavigationThrottle calls count.
  RegisterTestThrottle(request);
  PrepareCompleteCallbackOnRequest();
}

void NavigationSimulatorImpl::DidRedirectNavigation(
    NavigationHandle* navigation_handle) {
  if (request_ == navigation_handle)
    num_did_redirect_navigation_called_++;
}

void NavigationSimulatorImpl::ReadyToCommitNavigation(
    NavigationHandle* navigation_handle) {
  if (request_ && navigation_handle == request_)
    num_ready_to_commit_called_++;
}

void NavigationSimulatorImpl::DidFinishNavigation(
    NavigationHandle* navigation_handle) {
  NavigationRequest* request = NavigationRequest::From(navigation_handle);
  if (request == request_) {
    num_did_finish_navigation_called_++;
    if (navigation_handle->IsServedFromBackForwardCache()) {
      // Back-forward cache navigations commit and finish synchronously, unlike
      // all other navigations, which wait for a reply from the renderer.
      // The |state_| is normally updated to 'FINISHED' when we simulate a
      // renderer reply at the end of the NavigationSimulatorImpl::Commit()
      // function, but we have not reached this stage yet.
      // Set |state_| to FINISHED to ensure that we would not try to simulate
      // navigation commit for the second time.
      RenderFrameHostImpl* previous_rfh = RenderFrameHostImpl::FromID(
          navigation_handle->GetPreviousRenderFrameHostId());
      CHECK(previous_rfh) << "Previous RenderFrameHost should not be destroyed "
                             "without a Unload_ACK";

      // If the frame is not alive we do not displatch Unload ACK.
      // CommitPending() may be called immediately and delete the old
      // RenderFrameHost, so we need to record that now while we can still
      // access the object.
      if (!previous_rfh->IsRenderFrameLive())
        drop_unload_ack_ = true;
      SimulateUnloadCompletionCallbackForPreviousFrameIfNeeded(previous_rfh);
      state_ = FINISHED;
    }
    request_ = nullptr;
    if (was_aborted_)
      CHECK_EQ(net::ERR_ABORTED, request->GetNetErrorCode());
  }
}

void NavigationSimulatorImpl::OnWillStartRequest() {
  num_will_start_request_called_++;
}

void NavigationSimulatorImpl::OnWillRedirectRequest() {
  num_will_redirect_request_called_++;
}

void NavigationSimulatorImpl::OnWillFailRequest() {
  num_will_fail_request_called_++;
}

void NavigationSimulatorImpl::OnWillProcessResponse() {
  num_will_process_response_called_++;
}

bool NavigationSimulatorImpl::SimulateBrowserInitiatedStart() {
  if (state_ == INITIALIZATION)
    BrowserInitiatedStartAndWaitBeforeUnload();

  // Simulate the BeforeUnload completion callback if needed.
  NavigationRequest* request = frame_tree_node_->navigation_request();
  if (request &&
      request->state() == NavigationRequest::WAITING_FOR_RENDERER_RESPONSE) {
    if (block_invoking_before_unload_completed_callback_) {
      // Since we do not simulate the BeforeUnloadCompleted, DidStartNavigation
      // will not have been called, and |request_| will not be properly set. Do
      // it manually.
      request_ = request;
      return false;
    }
    render_frame_host_->SimulateBeforeUnloadCompleted(true /* proceed */);
  }

  // Note: WillStartRequest checks can destroy the request synchronously, or
  // this can be a navigation that doesn't need a network request and that was
  // passed directly to a RenderFrameHost for commit.
  request =
      web_contents_->GetMainFrame()->frame_tree_node()->navigation_request();
  if (!request) {
    if (IsRendererDebugURL(navigation_url_)) {
      // We don't create NavigationRequests nor NavigationHandles for a
      // navigation to a renderer-debug URL. Instead, the URL is passed to the
      // current RenderFrameHost so that the renderer process can handle it.
      CHECK(!request_);
      CHECK(web_contents_->GetMainFrame()->is_loading());

      // A navigation to a renderer-debug URL cannot commit. Simulate the
      // renderer process aborting it.
      render_frame_host_ =
          static_cast<TestRenderFrameHost*>(web_contents_->GetMainFrame());
      StopLoading();
      state_ = FAILED;
      return false;
    } else if (request_ &&
               web_contents_->GetMainFrame()->GetSameDocumentNavigationRequest(
                   request_->commit_params().navigation_token)) {
      CHECK(request_->IsSameDocument());
      same_document_ = true;
      return true;
    }
    return false;
  }

  CHECK_EQ(request_, request);
  return true;
}

bool NavigationSimulatorImpl::SimulateRendererInitiatedStart() {
  mojom::BeginNavigationParamsPtr begin_params =
      mojom::BeginNavigationParams::New(
          initiator_frame_host_
              ? base::make_optional(initiator_frame_host_->GetFrameToken())
              : base::nullopt,
          std::string() /* headers */, net::LOAD_NORMAL,
          false /* skip_service_worker */,
          blink::mojom::RequestContextType::HYPERLINK,
          network::mojom::RequestDestination::kDocument,
          blink::WebMixedContentContextType::kBlockable, is_form_submission_,
          false /* was_initiated_by_link_click */,
          GURL() /* searchable_form_url */,
          std::string() /* searchable_form_encoding */,
          GURL() /* client_side_redirect_url */,
          base::nullopt /* detools_initiator_info */,
          nullptr /* trust_token_params */, impression_,
          base::TimeTicks() /* renderer_before_unload_start */,
          base::TimeTicks() /* renderer_before_unload_end */);
  auto common_params = CreateCommonNavigationParams();
  common_params->navigation_start = base::TimeTicks::Now();
  common_params->url = navigation_url_;
  common_params->initiator_origin = url::Origin();
  common_params->method = initial_method_;
  common_params->referrer = referrer_.Clone();
  common_params->transition = transition_;
  common_params->navigation_type =
      PageTransitionCoreTypeIs(transition_, ui::PAGE_TRANSITION_RELOAD)
          ? mojom::NavigationType::RELOAD
          : mojom::NavigationType::DIFFERENT_DOCUMENT;
  common_params->has_user_gesture = has_user_gesture_;
  common_params->initiator_csp_info = mojom::InitiatorCSPInfo::New(
      should_check_main_world_csp_,
      std::vector<network::mojom::ContentSecurityPolicyPtr>());

  mojo::PendingAssociatedRemote<mojom::NavigationClient>
      navigation_client_remote;
  navigation_client_receiver_ =
      navigation_client_remote.InitWithNewEndpointAndPassReceiver();
  render_frame_host_->frame_host_receiver_for_testing().impl()->BeginNavigation(
      std::move(common_params), std::move(begin_params), mojo::NullRemote(),
      std::move(navigation_client_remote), mojo::NullRemote());

  NavigationRequest* request =
      render_frame_host_->frame_tree_node()->navigation_request();

  // The request failed synchronously.
  if (!request)
    return false;

  CHECK_EQ(request_, request);
  return true;
}

void NavigationSimulatorImpl::MaybeWaitForThrottleChecksComplete(
    base::OnceClosure complete_closure) {
  // If last_throttle_check_result_ is set, then throttle checks completed
  // synchronously.
  if (last_throttle_check_result_) {
    std::move(complete_closure).Run();
    return;
  }

  throttle_checks_complete_closure_ = std::move(complete_closure);
  if (auto_advance_)
    Wait();
}

void NavigationSimulatorImpl::Wait() {
  CHECK(!wait_closure_);
  if (!IsDeferred())
    return;
  base::RunLoop run_loop;
  wait_closure_ = run_loop.QuitClosure();
  run_loop.Run();
}

bool NavigationSimulatorImpl::OnThrottleChecksComplete(
    NavigationThrottle::ThrottleCheckResult result) {
  CHECK(!last_throttle_check_result_);
  last_throttle_check_result_ = result;
  if (wait_closure_)
    std::move(wait_closure_).Run();
  if (throttle_checks_complete_closure_)
    std::move(throttle_checks_complete_closure_).Run();
  return false;
}

void NavigationSimulatorImpl::PrepareCompleteCallbackOnRequest() {
  last_throttle_check_result_.reset();
  request_->set_complete_callback_for_testing(
      base::BindOnce(&NavigationSimulatorImpl::OnThrottleChecksComplete,
                     base::Unretained(this)));
}

RenderFrameHost* NavigationSimulatorImpl::GetFinalRenderFrameHost() {
  CHECK_GE(state_, READY_TO_COMMIT);
  return render_frame_host_;
}

bool NavigationSimulatorImpl::IsDeferred() {
  return !throttle_checks_complete_closure_.is_null();
}

bool NavigationSimulatorImpl::DidCreateNewEntry() {
  if (did_create_new_entry_.has_value())
    return did_create_new_entry_.value();
  if (ui::PageTransitionCoreTypeIs(transition_,
                                   ui::PAGE_TRANSITION_AUTO_SUBFRAME))
    return false;
  if (reload_type_ != ReloadType::NONE ||
      (request_ && NavigationTypeUtils::IsReload(
                       request_->common_params().navigation_type))) {
    return false;
  }
  if (session_history_offset_ ||
      (request_ && NavigationTypeUtils::IsHistory(
                       request_->common_params().navigation_type))) {
    return false;
  }
  if (request_ && (request_->common_params().navigation_type ==
                       mojom::NavigationType::RESTORE ||
                   request_->common_params().navigation_type ==
                       mojom::NavigationType::RESTORE_WITH_POST)) {
    return false;
  }

  return true;
}

void NavigationSimulatorImpl::SetSessionHistoryOffset(
    int session_history_offset) {
  CHECK(session_history_offset);
  session_history_offset_ = session_history_offset;
  transition_ =
      ui::PageTransitionFromInt(transition_ | ui::PAGE_TRANSITION_FORWARD_BACK);
}

void NavigationSimulatorImpl::set_did_create_new_entry(
    bool did_create_new_entry) {
  did_create_new_entry_ = did_create_new_entry;
}

void NavigationSimulatorImpl::set_history_list_was_cleared(
    bool history_cleared) {
  history_list_was_cleared_ = history_cleared;
}

mojom::DidCommitProvisionalLoadParamsPtr
NavigationSimulatorImpl::BuildDidCommitProvisionalLoadParams(
    bool same_document,
    bool failed_navigation,
    int last_http_status_code) {
  auto params = mojom::DidCommitProvisionalLoadParams::New();
  params->url = navigation_url_;
  params->original_request_url = original_url_;
  params->referrer = mojo::Clone(referrer_);
  params->contents_mime_type = contents_mime_type_;
  params->transition = transition_;
  params->gesture =
      has_user_gesture_ ? NavigationGestureUser : NavigationGestureAuto;
  params->history_list_was_cleared = history_list_was_cleared_;
  params->did_create_new_entry = DidCreateNewEntry();
  params->should_replace_current_entry = should_replace_current_entry_;
  params->navigation_token = request_
                                 ? request_->commit_params().navigation_token
                                 : base::UnguessableToken::Create();
  params->post_id = post_id_;

  params->intended_as_new_entry =
      request_ ? request_->commit_params().intended_as_new_entry : false;
  params->method = request_ ? request_->common_params().method : "GET";

  RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();

  if (failed_navigation) {
    // Note: Error pages must commit in a unique origin. So it is left unset.
    params->url_is_unreachable = true;
  } else {
    params->redirects.push_back(navigation_url_);
    params->should_update_history = true;
    if (same_document) {
      params->sandbox_flags = current_rfh->active_sandbox_flags();
      params->origin = current_rfh->GetLastCommittedOrigin();
    } else {
      params->sandbox_flags = request_->SandboxFlagsToCommit();
      params->origin =
          origin_.value_or(request_->GetOriginForURLLoaderFactory());
    }
  }

  if (same_document) {
    // Same document navigations always retain the last HTTP status code.
    params->http_status_code = last_http_status_code;
  } else if (request_ && request_->commit_params().http_response_code != -1) {
    // If we have a valid HTTP response code in |request_|, use it.
    params->http_status_code = request_->commit_params().http_response_code;
  } else {
    // Otherwise, unit tests will never issue real network requests and thus
    // will never receive any HTTP response.
    params->http_status_code = 0;
  }

  CHECK(same_document || request_);

  params->feature_policy_header = std::move(feature_policy_header_);

  // Simulate Blink assigning a item sequence number and document sequence
  // number to the navigation.
  params->item_sequence_number = ++g_unique_identifier;
  if (same_document) {
    FrameNavigationEntry* current_entry =
        web_contents_->GetController().GetLastCommittedEntry()->GetFrameEntry(
            frame_tree_node_);
    params->document_sequence_number =
        current_entry->document_sequence_number();
  } else {
    params->document_sequence_number = ++g_unique_identifier;
  }

  // Simulate embedding token creation.
  if (!same_document)
    params->embedding_token = base::UnguessableToken::Create();

  params->page_state = page_state_.value_or(
      blink::PageState::CreateForTestingWithSequenceNumbers(
          navigation_url_, params->item_sequence_number,
          params->document_sequence_number));

  params->is_overriding_user_agent =
      request_ ? (request_->commit_params().is_overriding_user_agent &&
                  frame_tree_node_->IsMainFrame())
               : false;

  return params;
}

void NavigationSimulatorImpl::SetKeepLoading(bool keep_loading) {
  keep_loading_ = keep_loading;
}

void NavigationSimulatorImpl::StopLoading() {
  CHECK(render_frame_host_);
  render_frame_host_->SimulateLoadingCompleted(loading_scenario_);
}

void NavigationSimulatorImpl::
    SimulateUnloadCompletionCallbackForPreviousFrameIfNeeded(
        RenderFrameHostImpl* previous_rfh) {
  // Do not dispatch mojo::AgentSchedulingGroupHost::DidUnloadRenderFrame if the
  // navigation was committed in the same RenderFrameHost.
  if (previous_rfh == render_frame_host_)
    return;
  if (drop_unload_ack_)
    return;
  // The previous RenderFrameHost is not live, we will not attempt to unload
  // it.
  if (!previous_rfh->IsRenderFrameLive())
    return;
  // The previous RenderFrameHost entered the back-forward cache and hasn't been
  // requested to unload. The browser process do not expect
  // mojo::AgentSchedulingGroupHost::DidUnloadRenderFrame.
  if (previous_rfh->IsInBackForwardCache())
    return;
  previous_rfh->OnUnloadACK();
}

}  // namespace content
