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

#include <memory>

#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "content/browser/process_lock.h"
#include "content/browser/renderer_host/debug_urls.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/runtime_feature_state/runtime_feature_state_document_data.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_content_browser_client.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/mock_web_contents_observer.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_service.mojom.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/mock_commit_deferring_condition.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h"
#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_read_context.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom.h"
#include "ui/base/page_transition_types.h"
#include "url/scheme_host_port.h"
#include "url/url_constants.h"

namespace {

// Text to place in an HTML body. Should not contain any markup.
const char kBodyTextContent[] = "some plain text content";

}  // namespace

namespace content {

namespace {

// A test NavigationThrottle that will return pre-determined checks and run
// callbacks when the various NavigationThrottle methods are called. It is
// not instantiated directly but through a TestNavigationThrottleInstaller.
class TestNavigationThrottle : public NavigationThrottle {
 public:
  TestNavigationThrottle(
      NavigationHandle* handle,
      NavigationThrottle::ThrottleCheckResult will_start_result,
      NavigationThrottle::ThrottleCheckResult will_redirect_result,
      NavigationThrottle::ThrottleCheckResult will_fail_result,
      NavigationThrottle::ThrottleCheckResult will_process_result,
      NavigationThrottle::ThrottleCheckResult
          will_commit_without_url_loader_result,
      base::OnceClosure did_call_will_start,
      base::OnceClosure did_call_will_redirect,
      base::OnceClosure did_call_will_fail,
      base::OnceClosure did_call_will_process,
      base::OnceClosure did_call_will_commit_without_url_loader)
      : NavigationThrottle(handle),
        will_start_result_(will_start_result),
        will_redirect_result_(will_redirect_result),
        will_fail_result_(will_fail_result),
        will_process_result_(will_process_result),
        will_commit_without_url_loader_result_(
            will_commit_without_url_loader_result),
        did_call_will_start_(std::move(did_call_will_start)),
        did_call_will_redirect_(std::move(did_call_will_redirect)),
        did_call_will_fail_(std::move(did_call_will_fail)),
        did_call_will_process_(std::move(did_call_will_process)),
        did_call_will_commit_without_url_loader_(
            std::move(did_call_will_commit_without_url_loader)) {}
  ~TestNavigationThrottle() override = default;

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

  blink::mojom::RequestContextType request_context_type() {
    return request_context_type_;
  }

  // Expose Resume and Cancel to the installer.
  void ResumeNavigation() { Resume(); }

  void CancelNavigation(NavigationThrottle::ThrottleCheckResult result) {
    CancelDeferredNavigation(result);
  }

 private:
  // NavigationThrottle implementation.
  NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
    NavigationRequest* navigation_request =
        NavigationRequest::From(navigation_handle());
    CHECK_NE(blink::mojom::RequestContextType::UNSPECIFIED,
             navigation_request->request_context_type());
    request_context_type_ = navigation_request->request_context_type();

    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        std::move(did_call_will_start_));
    return will_start_result_;
  }

  NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override {
    NavigationRequest* navigation_request =
        NavigationRequest::From(navigation_handle());
    CHECK_EQ(request_context_type_, navigation_request->request_context_type());

    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        std::move(did_call_will_redirect_));
    return will_redirect_result_;
  }

  NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
    NavigationRequest* navigation_request =
        NavigationRequest::From(navigation_handle());
    CHECK_EQ(request_context_type_, navigation_request->request_context_type());

    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        std::move(did_call_will_fail_));
    return will_fail_result_;
  }

  NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
    NavigationRequest* navigation_request =
        NavigationRequest::From(navigation_handle());
    CHECK_EQ(request_context_type_, navigation_request->request_context_type());

    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        std::move(did_call_will_process_));
    return will_process_result_;
  }

  NavigationThrottle::ThrottleCheckResult WillCommitWithoutUrlLoader()
      override {
    NavigationRequest* navigation_request =
        NavigationRequest::From(navigation_handle());
    CHECK_NE(blink::mojom::RequestContextType::UNSPECIFIED,
             navigation_request->request_context_type());
    request_context_type_ = navigation_request->request_context_type();

    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, std::move(did_call_will_commit_without_url_loader_));
    return will_commit_without_url_loader_result_;
  }

  NavigationThrottle::ThrottleCheckResult will_start_result_;
  NavigationThrottle::ThrottleCheckResult will_redirect_result_;
  NavigationThrottle::ThrottleCheckResult will_fail_result_;
  NavigationThrottle::ThrottleCheckResult will_process_result_;
  NavigationThrottle::ThrottleCheckResult
      will_commit_without_url_loader_result_;
  base::OnceClosure did_call_will_start_;
  base::OnceClosure did_call_will_redirect_;
  base::OnceClosure did_call_will_fail_;
  base::OnceClosure did_call_will_process_;
  base::OnceClosure did_call_will_commit_without_url_loader_;
  blink::mojom::RequestContextType request_context_type_ =
      blink::mojom::RequestContextType::UNSPECIFIED;
};

// Installs a TestNavigationThrottle either on all following requests or on
// requests with an expected starting URL, and allows waiting for various
// NavigationThrottle related events. Waiting works only for the immediately
// next navigation. New instances are needed to wait for further navigations.
class TestNavigationThrottleInstaller : public WebContentsObserver {
 public:
  enum Method {
    WILL_START_REQUEST,
    WILL_REDIRECT_REQUEST,
    WILL_FAIL_REQUEST,
    WILL_PROCESS_RESPONSE,
    WILL_COMMIT_WITHOUT_URL_LOADER,
  };

  TestNavigationThrottleInstaller(
      WebContents* web_contents,
      NavigationThrottle::ThrottleCheckResult will_start_result,
      NavigationThrottle::ThrottleCheckResult will_redirect_result,
      NavigationThrottle::ThrottleCheckResult will_fail_result,
      NavigationThrottle::ThrottleCheckResult will_process_result,
      NavigationThrottle::ThrottleCheckResult
          will_commit_without_url_loader_result,
      const GURL& expected_start_url = GURL())
      : WebContentsObserver(web_contents),
        will_start_result_(will_start_result),
        will_redirect_result_(will_redirect_result),
        will_fail_result_(will_fail_result),
        will_process_result_(will_process_result),
        will_commit_without_url_loader_result_(
            will_commit_without_url_loader_result),
        expected_start_url_(expected_start_url) {}
  ~TestNavigationThrottleInstaller() override = default;

  // Installs a TestNavigationThrottle whose |method| method will return
  // |result|. All other methods will return NavigationThrottle::PROCEED.
  static std::unique_ptr<TestNavigationThrottleInstaller> CreateForMethod(
      WebContents* web_contents,
      Method method,
      NavigationThrottle::ThrottleCheckResult result) {
    NavigationThrottle::ThrottleCheckResult will_start_result =
        NavigationThrottle::PROCEED;
    auto will_redirect_result = will_start_result;
    auto will_fail_result = will_start_result;
    auto will_process_result = will_start_result;
    auto will_commit_without_url_loader_result = will_start_result;

    switch (method) {
      case WILL_START_REQUEST:
        will_start_result = result;
        break;
      case WILL_REDIRECT_REQUEST:
        will_redirect_result = result;
        break;
      case WILL_FAIL_REQUEST:
        will_fail_result = result;
        break;
      case WILL_PROCESS_RESPONSE:
        will_process_result = result;
        break;
      case WILL_COMMIT_WITHOUT_URL_LOADER:
        will_commit_without_url_loader_result = result;
        break;
    }

    return std::make_unique<TestNavigationThrottleInstaller>(
        web_contents, will_start_result, will_redirect_result, will_fail_result,
        will_process_result, will_commit_without_url_loader_result);
  }

  TestNavigationThrottle* navigation_throttle() { return navigation_throttle_; }

  void WaitForThrottleWillStart() {
    if (will_start_called_)
      return;
    will_start_loop_runner_ = new MessageLoopRunner();
    will_start_loop_runner_->Run();
    will_start_loop_runner_ = nullptr;
  }

  void WaitForThrottleWillRedirect() {
    if (will_redirect_called_)
      return;
    will_redirect_loop_runner_ = new MessageLoopRunner();
    will_redirect_loop_runner_->Run();
    will_redirect_loop_runner_ = nullptr;
  }

  void WaitForThrottleWillFail() {
    if (will_fail_called_)
      return;
    will_fail_loop_runner_ = new MessageLoopRunner();
    will_fail_loop_runner_->Run();
    will_fail_loop_runner_ = nullptr;
  }

  void WaitForThrottleWillProcess() {
    if (will_process_called_)
      return;
    will_process_loop_runner_ = new MessageLoopRunner();
    will_process_loop_runner_->Run();
    will_process_loop_runner_ = nullptr;
  }

  void WaitForThrottleWillCommitWithoutUrlLoader() {
    if (will_commit_without_url_loader_called_) {
      return;
    }
    will_commit_without_url_loader_loop_runner_ = new MessageLoopRunner();
    will_commit_without_url_loader_loop_runner_->Run();
    will_commit_without_url_loader_loop_runner_ = nullptr;
  }

  void Continue(NavigationThrottle::ThrottleCheckResult result) {
    ASSERT_NE(NavigationThrottle::DEFER, result.action());
    if (result.action() == NavigationThrottle::PROCEED)
      navigation_throttle()->ResumeNavigation();
    else
      navigation_throttle()->CancelNavigation(result);
  }

  int will_start_called() { return will_start_called_; }
  int will_redirect_called() { return will_redirect_called_; }
  int will_fail_called() { return will_fail_called_; }
  int will_process_called() { return will_process_called_; }
  int will_commit_without_url_loader_called() {
    return will_commit_without_url_loader_called_;
  }

  int install_count() { return install_count_; }

 protected:
  virtual void DidCallWillStartRequest() {
    will_start_called_++;
    if (will_start_loop_runner_)
      will_start_loop_runner_->Quit();
  }

  virtual void DidCallWillRedirectRequest() {
    will_redirect_called_++;
    if (will_redirect_loop_runner_)
      will_redirect_loop_runner_->Quit();
  }

  virtual void DidCallWillFailRequest() {
    will_fail_called_++;
    if (will_fail_loop_runner_)
      will_fail_loop_runner_->Quit();
  }

  virtual void DidCallWillProcessResponse() {
    will_process_called_++;
    if (will_process_loop_runner_)
      will_process_loop_runner_->Quit();
  }

  virtual void DidCallWillCommitWithoutUrlLoader() {
    will_commit_without_url_loader_called_++;
    if (will_commit_without_url_loader_loop_runner_) {
      will_commit_without_url_loader_loop_runner_->Quit();
    }
  }

 private:
  void DidStartNavigation(NavigationHandle* handle) override {
    if (!expected_start_url_.is_empty() &&
        handle->GetURL() != expected_start_url_)
      return;

    std::unique_ptr<NavigationThrottle> throttle(new TestNavigationThrottle(
        handle, will_start_result_, will_redirect_result_, will_fail_result_,
        will_process_result_, will_commit_without_url_loader_result_,
        base::BindOnce(
            &TestNavigationThrottleInstaller::DidCallWillStartRequest,
            weak_factory_.GetWeakPtr()),
        base::BindOnce(
            &TestNavigationThrottleInstaller::DidCallWillRedirectRequest,
            weak_factory_.GetWeakPtr()),
        base::BindOnce(&TestNavigationThrottleInstaller::DidCallWillFailRequest,
                       weak_factory_.GetWeakPtr()),
        base::BindOnce(
            &TestNavigationThrottleInstaller::DidCallWillProcessResponse,
            weak_factory_.GetWeakPtr()),
        base::BindOnce(
            &TestNavigationThrottleInstaller::DidCallWillCommitWithoutUrlLoader,
            weak_factory_.GetWeakPtr())));
    navigation_throttle_ = static_cast<TestNavigationThrottle*>(throttle.get());
    handle->RegisterThrottleForTesting(std::move(throttle));
    ++install_count_;
  }

  void DidFinishNavigation(NavigationHandle* handle) override {
    if (!navigation_throttle_)
      return;

    if (handle == navigation_throttle_->navigation_handle())
      navigation_throttle_ = nullptr;
  }

  NavigationThrottle::ThrottleCheckResult will_start_result_;
  NavigationThrottle::ThrottleCheckResult will_redirect_result_;
  NavigationThrottle::ThrottleCheckResult will_fail_result_;
  NavigationThrottle::ThrottleCheckResult will_process_result_;
  NavigationThrottle::ThrottleCheckResult
      will_commit_without_url_loader_result_;
  int will_start_called_ = 0;
  int will_redirect_called_ = 0;
  int will_fail_called_ = 0;
  int will_process_called_ = 0;
  int will_commit_without_url_loader_called_ = 0;
  raw_ptr<TestNavigationThrottle> navigation_throttle_ = nullptr;
  int install_count_ = 0;
  scoped_refptr<MessageLoopRunner> will_start_loop_runner_;
  scoped_refptr<MessageLoopRunner> will_redirect_loop_runner_;
  scoped_refptr<MessageLoopRunner> will_fail_loop_runner_;
  scoped_refptr<MessageLoopRunner> will_process_loop_runner_;
  scoped_refptr<MessageLoopRunner> will_commit_without_url_loader_loop_runner_;
  GURL expected_start_url_;

  // The throttle installer can be deleted before all tasks posted by its
  // throttles are run, so it must be referenced via weak pointers.
  base::WeakPtrFactory<TestNavigationThrottleInstaller> weak_factory_{this};
};

// Same as above, but installs NavigationThrottles that do not directly return
// the pre-programmed check results, but first DEFER the navigation at each
// stage and then resume/cancel asynchronously.
class TestDeferringNavigationThrottleInstaller
    : public TestNavigationThrottleInstaller {
 public:
  TestDeferringNavigationThrottleInstaller(
      WebContents* web_contents,
      NavigationThrottle::ThrottleCheckResult will_start_result,
      NavigationThrottle::ThrottleCheckResult will_redirect_result,
      NavigationThrottle::ThrottleCheckResult will_fail_result,
      NavigationThrottle::ThrottleCheckResult will_process_result,
      NavigationThrottle::ThrottleCheckResult
          will_commit_without_url_loader_result,
      GURL expected_start_url = GURL())
      : TestNavigationThrottleInstaller(web_contents,
                                        NavigationThrottle::DEFER,
                                        NavigationThrottle::DEFER,
                                        NavigationThrottle::DEFER,
                                        NavigationThrottle::DEFER,
                                        NavigationThrottle::DEFER,
                                        expected_start_url),
        will_start_deferred_result_(will_start_result),
        will_redirect_deferred_result_(will_redirect_result),
        will_fail_deferred_result_(will_fail_result),
        will_process_deferred_result_(will_process_result),
        will_commit_without_url_loader_result_(
            will_commit_without_url_loader_result) {}

 protected:
  void DidCallWillStartRequest() override {
    TestNavigationThrottleInstaller::DidCallWillStartRequest();
    Continue(will_start_deferred_result_);
  }

  void DidCallWillRedirectRequest() override {
    TestNavigationThrottleInstaller::DidCallWillStartRequest();
    Continue(will_redirect_deferred_result_);
  }

  void DidCallWillFailRequest() override {
    TestNavigationThrottleInstaller::DidCallWillStartRequest();
    Continue(will_fail_deferred_result_);
  }

  void DidCallWillProcessResponse() override {
    TestNavigationThrottleInstaller::DidCallWillStartRequest();
    Continue(will_process_deferred_result_);
  }

  void DidCallWillCommitWithoutUrlLoader() override {
    TestNavigationThrottleInstaller::DidCallWillCommitWithoutUrlLoader();
    Continue(will_commit_without_url_loader_result_);
  }

 private:
  NavigationThrottle::ThrottleCheckResult will_start_deferred_result_;
  NavigationThrottle::ThrottleCheckResult will_redirect_deferred_result_;
  NavigationThrottle::ThrottleCheckResult will_fail_deferred_result_;
  NavigationThrottle::ThrottleCheckResult will_process_deferred_result_;
  NavigationThrottle::ThrottleCheckResult
      will_commit_without_url_loader_result_;
};

// Records all navigation start URLs from the WebContents.
class NavigationStartUrlRecorder : public WebContentsObserver {
 public:
  explicit NavigationStartUrlRecorder(WebContents* web_contents)
      : WebContentsObserver(web_contents) {}

  void DidStartNavigation(NavigationHandle* navigation_handle) override {
    urls_.push_back(navigation_handle->GetURL());
  }

  const std::vector<GURL>& urls() const { return urls_; }

 private:
  std::vector<GURL> urls_;
};

void ExpectChildFrameSetAsCollapsedInFTN(Shell* shell, bool expect_collapsed) {
  // Check if the frame should be collapsed in theory as per FTN.
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  ASSERT_EQ(1u, root->child_count());
  FrameTreeNode* child = root->child_at(0u);
  EXPECT_EQ(expect_collapsed, child->is_collapsed());
}

void ExpectChildFrameCollapsedInLayout(Shell* shell,
                                       const std::string& frame_id,
                                       bool expect_collapsed) {
  // Check if the frame is collapsed in practice.
  const char kScript[] = "document.getElementById(\"%s\").clientWidth;";
  int client_width =
      EvalJs(shell, base::StringPrintf(kScript, frame_id.c_str())).ExtractInt();
  EXPECT_EQ(expect_collapsed, !client_width) << client_width;
}

void ExpectChildFrameCollapsed(Shell* shell,
                               const std::string& frame_id,
                               bool expect_collapsed) {
  ExpectChildFrameSetAsCollapsedInFTN(shell, expect_collapsed);
  ExpectChildFrameCollapsedInLayout(shell, frame_id, expect_collapsed);
}

}  // namespace

class NavigationRequestBrowserTest : public ContentBrowserTest {
 protected:
  void SetUpOnMainThread() override {
    host_resolver()->AddRule("*", "127.0.0.1");
    SetupCrossSiteRedirector(embedded_test_server());
    ASSERT_TRUE(embedded_test_server()->Start());
  }

  // Installs a NavigationThrottle whose |method| method will return a
  // ThrottleCheckResult with |action|, net::ERR_BLOCKED_BY_CLIENT and
  // a custom error page. Navigates to |url|, checks that the navigation
  // committed and that the custom error page is being shown.
  void InstallThrottleAndTestNavigationCommittedWithErrorPage(
      const GURL& url,
      NavigationThrottle::ThrottleAction action,
      TestNavigationThrottleInstaller::Method method) {
    auto installer = TestNavigationThrottleInstaller::CreateForMethod(
        shell()->web_contents(), method,
        NavigationThrottle::ThrottleCheckResult(
            action, net::ERR_BLOCKED_BY_CLIENT,
            base::StringPrintf("<html><body>%s</body><html>",
                               kBodyTextContent)));

    NavigationHandleObserver observer(shell()->web_contents(), url);

    EXPECT_FALSE(NavigateToURL(shell(), url));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());

    content::RenderFrameHost* rfh =
        shell()->web_contents()->GetPrimaryMainFrame();
    EXPECT_EQ(kBodyTextContent, EvalJs(rfh, "document.body.textContent"));
  }
};

class NavigationRequestDownloadBrowserTest
    : public NavigationRequestBrowserTest {
 protected:
  void SetUpOnMainThread() override {
    NavigationRequestBrowserTest::SetUpOnMainThread();

    // Set up a test download directory, in order to prevent prompting for
    // handling downloads.
    ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
    ShellDownloadManagerDelegate* delegate =
        static_cast<ShellDownloadManagerDelegate*>(
            shell()
                ->web_contents()
                ->GetBrowserContext()
                ->GetDownloadManagerDelegate());
    delegate->SetDownloadBehaviorForTesting(downloads_directory_.GetPath());
  }

 private:
  base::ScopedTempDir downloads_directory_;
};

// Ensure that PageTransition is properly set on the NavigationHandle.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, VerifyPageTransition) {
  {
    // Test browser initiated navigation, which should have a PageTransition as
    // if it came from the omnibox.
    GURL url(embedded_test_server()->GetURL("/title1.html"));
    NavigationHandleObserver observer(shell()->web_contents(), url);
    ui::PageTransition expected_transition = ui::PageTransitionFromInt(
        ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);

    EXPECT_TRUE(NavigateToURL(shell(), url));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_EQ(url, observer.last_committed_url());
    EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
        observer.page_transition(), expected_transition));
  }

  {
    // Test navigating to a page with subframe. The subframe will have
    // PageTransition of type AUTO_SUBFRAME.
    GURL url(
        embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html"));
    NavigationHandleObserver observer(
        shell()->web_contents(),
        embedded_test_server()->GetURL("/cross-site/baz.com/title1.html"));
    ui::PageTransition expected_transition =
        ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_SUBFRAME);

    EXPECT_TRUE(NavigateToURL(shell(), url));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title1.html"),
              observer.last_committed_url());
    EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
        observer.page_transition(), expected_transition));
    EXPECT_FALSE(observer.is_main_frame());
  }
}

// Ensure that the following methods on NavigationHandle behave correctly:
// * IsInMainFrame
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, VerifyFrameTree) {
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
  GURL b_url(embedded_test_server()->GetURL(
      "b.com", "/cross_site_iframe_factory.html?b(c())"));
  GURL c_url(embedded_test_server()->GetURL(
      "c.com", "/cross_site_iframe_factory.html?c()"));

  NavigationHandleObserver main_observer(shell()->web_contents(), main_url);
  NavigationHandleObserver b_observer(shell()->web_contents(), b_url);
  NavigationHandleObserver c_observer(shell()->web_contents(), c_url);

  EXPECT_TRUE(NavigateToURL(shell(), main_url));

  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();

  // Verify the main frame.
  EXPECT_TRUE(main_observer.has_committed());
  EXPECT_FALSE(main_observer.is_error());
  EXPECT_EQ(main_url, main_observer.last_committed_url());
  EXPECT_TRUE(main_observer.is_main_frame());
  EXPECT_EQ(root->frame_tree_node_id(), main_observer.frame_tree_node_id());

  // Verify the b.com frame.
  EXPECT_TRUE(b_observer.has_committed());
  EXPECT_FALSE(b_observer.is_error());
  EXPECT_EQ(b_url, b_observer.last_committed_url());
  EXPECT_FALSE(b_observer.is_main_frame());
  EXPECT_EQ(root->child_at(0)->frame_tree_node_id(),
            b_observer.frame_tree_node_id());

  // Verify the c.com frame.
  EXPECT_TRUE(c_observer.has_committed());
  EXPECT_FALSE(c_observer.is_error());
  EXPECT_EQ(c_url, c_observer.last_committed_url());
  EXPECT_FALSE(c_observer.is_main_frame());
  EXPECT_EQ(root->child_at(0)->child_at(0)->frame_tree_node_id(),
            c_observer.frame_tree_node_id());
}

// Ensure that the WasRedirected() method on NavigationHandle behaves correctly.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, VerifyRedirect) {
  {
    GURL url(embedded_test_server()->GetURL("/title1.html"));
    NavigationHandleObserver observer(shell()->web_contents(), url);

    EXPECT_TRUE(NavigateToURL(shell(), url));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_FALSE(observer.was_redirected());
  }

  {
    GURL url(embedded_test_server()->GetURL("/cross-site/baz.com/title1.html"));
    GURL final_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
    NavigationHandleObserver observer(shell()->web_contents(), url);

    EXPECT_TRUE(
        NavigateToURL(shell(), url, final_url /* expected_commit_url */));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_TRUE(observer.was_redirected());
  }
}

// Ensure that we can read and write to the browser process's copy of the blink
// runtime-enabled features via NavigationRequest's method
// GetMutableRuntimeFeatureStateContext() during commit. Then ensure that its
// values are persisted to the RenderFrameHostImpl's read-only context.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RuntimeFeatureStatePersisted) {
  // Sets up the NavigationRequest where we can begin accessing the
  // RuntimeFeatureStateContext class.
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  TestNavigationManager manager(shell()->web_contents(), url);

  // Begin loading our url and wait for the request to start.
  shell()->LoadURL(url);
  EXPECT_TRUE(manager.WaitForRequestStart());

  // Ensure we can get and set values in RuntimeFeatureStateContext.
  blink::RuntimeFeatureStateContext& context =
      NavigationRequest::From(manager.GetNavigationHandle())
          ->GetMutableRuntimeFeatureStateContext();
  bool is_test_feature_enabled(context.IsTestFeatureEnabled());
  context.SetTestFeatureEnabled(!is_test_feature_enabled);
  EXPECT_EQ(context.IsTestFeatureEnabled(), !is_test_feature_enabled);

  // Check the override value map as well.
  base::flat_map<::blink::mojom::RuntimeFeatureState, bool>
      expected_feature_overrides = context.GetFeatureOverrides();
  EXPECT_EQ(expected_feature_overrides
                [blink::mojom::RuntimeFeatureState::kTestFeature],
            !is_test_feature_enabled);

  // Continue with the navigation until completion.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_TRUE(manager.was_successful());

  // Check that the changes were saved to the RenderFrameHost.
  RuntimeFeatureStateDocumentData* document_data =
      RuntimeFeatureStateDocumentData::GetForCurrentDocument(
          shell()->web_contents()->GetPrimaryMainFrame());
  EXPECT_TRUE(document_data);
  blink::RuntimeFeatureStateReadContext read_context =
      document_data->runtime_feature_state_read_context();
  EXPECT_EQ(expected_feature_overrides, read_context.GetFeatureOverrides());
}

// Similar to RuntimeFeatureStatePersisted but ensures that even for
// runtime-enabled feature values that are equivalent to the previous state.
// This is important to persist as it helps the renderer determine force-enabled
// and force-disabled values.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RuntimeFeatureStatePersistedForSameValue) {
  // Sets up the NavigationRequest where we can begin accessing the
  // RuntimeFeatureStateContext class.
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  TestNavigationManager manager(shell()->web_contents(), url);

  // Begin loading our url and wait for the request to start.
  shell()->LoadURL(url);
  EXPECT_TRUE(manager.WaitForRequestStart());

  // Ensure we can set values in RuntimeFeatureStateContext that are
  // equivalent to the feature's previous state.
  blink::RuntimeFeatureStateContext& context =
      NavigationRequest::From(manager.GetNavigationHandle())
          ->GetMutableRuntimeFeatureStateContext();
  bool is_test_feature_enabled(context.IsTestFeatureEnabled());
  context.SetTestFeatureEnabled(is_test_feature_enabled);
  EXPECT_EQ(context.IsTestFeatureEnabled(), is_test_feature_enabled);

  // Check the override value map as well.
  base::flat_map<::blink::mojom::RuntimeFeatureState, bool>
      expected_feature_overrides = context.GetFeatureOverrides();
  EXPECT_EQ(expected_feature_overrides
                [blink::mojom::RuntimeFeatureState::kTestFeature],
            is_test_feature_enabled);

  // Continue with the navigation until completion.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_TRUE(manager.was_successful());

  // Check that the changes were saved to the RenderFrameHost's feature
  // overrides.
  RuntimeFeatureStateDocumentData* document_data =
      RuntimeFeatureStateDocumentData::GetForCurrentDocument(
          shell()->web_contents()->GetPrimaryMainFrame());
  EXPECT_TRUE(document_data);
  blink::RuntimeFeatureStateReadContext read_context =
      document_data->runtime_feature_state_read_context();
  EXPECT_EQ(expected_feature_overrides, read_context.GetFeatureOverrides());
}

// Similar to RuntimeFeatureStatePersisted but ensures that even for
// runtime-enabled feature values are cleared across redirects.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RuntimeFeatureStateClearOnRedirect) {
  // Sets up the NavigationRequest where we can begin accessing the
  // RuntimeFeatureStateContext class.
  GURL redirect_url(
      embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
  TestNavigationManager redirect_manager(shell()->web_contents(), redirect_url);
  shell()->LoadURL(redirect_url);

  EXPECT_TRUE(redirect_manager.WaitForRequestStart());

  // Set a feature value we expect to be cleared upon redirect.
  blink::RuntimeFeatureStateContext& context =
      NavigationRequest::From(redirect_manager.GetNavigationHandle())
          ->GetMutableRuntimeFeatureStateContext();
  bool is_test_feature_enabled(context.IsTestFeatureEnabled());
  context.SetTestFeatureEnabled(!is_test_feature_enabled);
  EXPECT_FALSE(context.GetFeatureOverrides().empty());

  redirect_manager.ResumeNavigation();
  EXPECT_TRUE(redirect_manager.WaitForResponse());

  // Ensure NavigationRequest's new RuntimeFeatureStateContext is clear
  const blink::RuntimeFeatureStateContext& new_context =
      NavigationRequest::From(redirect_manager.GetNavigationHandle())
          ->GetRuntimeFeatureStateContext();
  EXPECT_TRUE(new_context.GetFeatureOverrides().empty());

  // Continue with the navigation until completion.
  ASSERT_TRUE(redirect_manager.WaitForNavigationFinished());
  EXPECT_TRUE(redirect_manager.was_successful());

  // Ensure that the changes made to the features before redirect do not
  // persist to the read context.
  RuntimeFeatureStateDocumentData* document_data =
      RuntimeFeatureStateDocumentData::GetForCurrentDocument(
          shell()->web_contents()->GetPrimaryMainFrame());
  EXPECT_TRUE(document_data);
  blink::RuntimeFeatureStateReadContext read_context =
      document_data->runtime_feature_state_read_context();
  EXPECT_TRUE(read_context.GetFeatureOverrides().empty());
}

// Ensure that a certificate error results in a committed navigation with
// the appropriate error code on the handle.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, VerifyCertErrorFailure) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
  ASSERT_TRUE(https_server.Start());
  GURL url(https_server.GetURL("/title1.html"));

  NavigationHandleObserver observer(shell()->web_contents(), url);

  EXPECT_FALSE(NavigateToURL(shell(), url));

  EXPECT_TRUE(observer.has_committed());
  EXPECT_TRUE(observer.is_error());
  EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, observer.net_error_code());
}

// Ensure that the IsRendererInitiated() method on NavigationHandle behaves
// correctly.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, VerifyRendererInitiated) {
  {
    // Test browser initiated navigation.
    GURL url(embedded_test_server()->GetURL("/title1.html"));
    NavigationHandleObserver observer(shell()->web_contents(), url);

    EXPECT_TRUE(NavigateToURL(shell(), url));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_FALSE(observer.is_renderer_initiated());
  }

  {
    // Test a main frame + subframes navigation.
    GURL main_url(embedded_test_server()->GetURL(
        "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
    GURL b_url(embedded_test_server()->GetURL(
        "b.com", "/cross_site_iframe_factory.html?b(c())"));
    GURL c_url(embedded_test_server()->GetURL(
        "c.com", "/cross_site_iframe_factory.html?c()"));

    NavigationHandleObserver main_observer(shell()->web_contents(), main_url);
    NavigationHandleObserver b_observer(shell()->web_contents(), b_url);
    NavigationHandleObserver c_observer(shell()->web_contents(), c_url);

    EXPECT_TRUE(NavigateToURL(shell(), main_url));

    // Verify that the main frame navigation is not renderer initiated.
    EXPECT_TRUE(main_observer.has_committed());
    EXPECT_FALSE(main_observer.is_error());
    EXPECT_FALSE(main_observer.is_renderer_initiated());

    // Verify that the subframe navigations are renderer initiated.
    EXPECT_TRUE(b_observer.has_committed());
    EXPECT_FALSE(b_observer.is_error());
    EXPECT_TRUE(b_observer.is_renderer_initiated());
    EXPECT_TRUE(c_observer.has_committed());
    EXPECT_FALSE(c_observer.is_error());
    EXPECT_TRUE(c_observer.is_renderer_initiated());
  }

  {
    // Test a pushState navigation.
    GURL url(embedded_test_server()->GetURL(
        "a.com", "/cross_site_iframe_factory.html?a(a())"));
    EXPECT_TRUE(NavigateToURL(shell(), url));

    FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                              ->GetPrimaryFrameTree()
                              .root();

    NavigationHandleObserver observer(
        shell()->web_contents(),
        embedded_test_server()->GetURL("a.com", "/bar"));
    EXPECT_TRUE(
        ExecJs(root->child_at(0), "window.history.pushState({}, '', 'bar');"));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_TRUE(observer.is_renderer_initiated());
  }
}

// Ensure that methods on NavigationHandle behave correctly with an iframe that
// navigates to its srcdoc attribute.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, VerifySrcdoc) {
  GURL url(embedded_test_server()->GetURL(
      "/frame_tree/page_with_srcdoc_frame.html"));
  NavigationHandleObserver observer(shell()->web_contents(),
                                    GURL("about:srcdoc"));

  EXPECT_TRUE(NavigateToURL(shell(), url));

  EXPECT_TRUE(observer.has_committed());
  EXPECT_FALSE(observer.is_error());
  EXPECT_TRUE(observer.last_committed_url().IsAboutSrcdoc());
}

// Ensure that the IsSameDocument() method on NavigationHandle behaves
// correctly.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, VerifySameDocument) {
  GURL url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(a())"));
  EXPECT_TRUE(NavigateToURL(shell(), url));

  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  {
    NavigationHandleObserver observer(
        shell()->web_contents(),
        embedded_test_server()->GetURL("a.com", "/foo"));
    EXPECT_TRUE(
        ExecJs(root->child_at(0), "window.history.pushState({}, '', 'foo');"));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_TRUE(observer.is_same_document());
  }
  {
    NavigationHandleObserver observer(
        shell()->web_contents(),
        embedded_test_server()->GetURL("a.com", "/bar"));
    EXPECT_TRUE(ExecJs(root->child_at(0),
                       "window.history.replaceState({}, '', 'bar');"));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_TRUE(observer.is_same_document());
  }
  {
    NavigationHandleObserver observer(
        shell()->web_contents(),
        embedded_test_server()->GetURL("a.com", "/bar#frag"));
    EXPECT_TRUE(ExecJs(root->child_at(0), "window.location.replace('#frag');"));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_TRUE(observer.is_same_document());
  }

  GURL about_blank_url(url::kAboutBlankURL);
  {
    NavigationHandleObserver observer(shell()->web_contents(), about_blank_url);
    EXPECT_TRUE(ExecJs(
        root, "document.body.appendChild(document.createElement('iframe'));"));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_FALSE(observer.is_same_document());
    EXPECT_EQ(about_blank_url, observer.last_committed_url());
  }
  {
    NavigationHandleObserver observer(shell()->web_contents(), about_blank_url);
    EXPECT_TRUE(NavigateToURLFromRenderer(root->child_at(0), about_blank_url));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_FALSE(observer.is_same_document());
    EXPECT_EQ(about_blank_url, observer.last_committed_url());
  }
}

// Ensure that a NavigationThrottle can cancel the navigation at navigation
// start.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ThrottleCancelStart) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  GURL redirect_url(
      embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
  NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::CANCEL,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

  EXPECT_FALSE(NavigateToURL(shell(), redirect_url));

  EXPECT_FALSE(observer.has_committed());
  EXPECT_TRUE(observer.is_error());

  // The navigation should have been canceled before being redirected.
  EXPECT_FALSE(observer.was_redirected());
  EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url);
}

// Ensure that a NavigationThrottle can cancel the navigation when a navigation
// is redirected.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ThrottleCancelRedirect) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  // A navigation with a redirect should be canceled.
  {
    GURL redirect_url(
        embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
    NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::CANCEL, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

    EXPECT_FALSE(NavigateToURL(shell(), redirect_url));

    EXPECT_FALSE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());
    EXPECT_TRUE(observer.was_redirected());
    EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url);
  }

  // A navigation without redirects should be successful.
  {
    GURL no_redirect_url(embedded_test_server()->GetURL("/title2.html"));
    NavigationHandleObserver observer(shell()->web_contents(), no_redirect_url);
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::CANCEL, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

    EXPECT_TRUE(NavigateToURL(shell(), no_redirect_url));

    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_FALSE(observer.was_redirected());
    EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), no_redirect_url);
  }
}

// Ensure that a NavigationThrottle can respond CANCEL when a navigation fails.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ThrottleCancelFailure) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
  ASSERT_TRUE(https_server.Start());
  GURL url(https_server.GetURL("/title1.html"));

  // A navigation with a cert error failure should be canceled. CANCEL has a
  // default net error of ERR_ABORTED, which should prevent the navigation from
  // committing.
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::CANCEL,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

    NavigationHandleObserver observer(shell()->web_contents(), url);

    EXPECT_FALSE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());

    EXPECT_FALSE(NavigateToURL(shell(), url));

    EXPECT_FALSE(installer.will_fail_called());
    EXPECT_FALSE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());
    EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
  }

  // A navigation with a cert error failure should be canceled.
  // A custom net error should result in a committed error page.
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED,
        NavigationThrottle::ThrottleCheckResult(NavigationThrottle::CANCEL,
                                                net::ERR_CERT_DATE_INVALID),
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

    NavigationHandleObserver observer(shell()->web_contents(), url);

    EXPECT_FALSE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());

    EXPECT_FALSE(NavigateToURL(shell(), url));

    EXPECT_TRUE(installer.will_fail_called());
    EXPECT_TRUE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());
    EXPECT_EQ(net::ERR_CERT_DATE_INVALID, observer.net_error_code());
  }

  // A navigation without a cert error should be successful, without calling
  // WillFailRequest() on the throttle. (We set the failure method response to
  // CANCEL, but that shouldn't matter if the test passes.)
  {
    url = embedded_test_server()->GetURL("/title2.html");
    NavigationHandleObserver observer(shell()->web_contents(), url);
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::CANCEL,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

    EXPECT_TRUE(NavigateToURL(shell(), url));

    EXPECT_FALSE(installer.will_fail_called());
    EXPECT_FALSE(observer.is_error());
  }
}

// Ensure that a NavigationThrottle can cancel the navigation when the response
// is received.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ThrottleCancelResponse) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  GURL redirect_url(
      embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
  NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::CANCEL, NavigationThrottle::PROCEED);

  EXPECT_FALSE(NavigateToURL(shell(), redirect_url));

  EXPECT_FALSE(observer.has_committed());
  EXPECT_TRUE(observer.is_error());
  // The navigation should have been redirected first, and then canceled when
  // the response arrived.
  EXPECT_TRUE(observer.was_redirected());
  EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url);
}

// Ensure that a NavigationThrottle can cancel the navigation when committing
// without a URLLoader.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       ThrottleCancelCommitWithoutUrlLoader) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  GURL about_blank_url(url::kAboutBlankURL);
  NavigationHandleObserver observer(shell()->web_contents(), about_blank_url);
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::CANCEL_AND_IGNORE);

  EXPECT_FALSE(NavigateToURL(shell(), about_blank_url));

  EXPECT_FALSE(observer.has_committed());
  EXPECT_TRUE(observer.is_error());
  EXPECT_FALSE(observer.was_redirected());
  EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url);
}

// Ensure that a NavigationThrottle can defer and resume the navigation at
// navigation start, navigation redirect and response received.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ThrottleDefer) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  GURL redirect_url(
      embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
  TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
  NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::DEFER,
      NavigationThrottle::DEFER, NavigationThrottle::DEFER,
      NavigationThrottle::DEFER, NavigationThrottle::DEFER);

  shell()->LoadURL(redirect_url);

  // Wait for WillStartRequest.
  installer.WaitForThrottleWillStart();
  EXPECT_EQ(1, installer.will_start_called());
  EXPECT_EQ(0, installer.will_redirect_called());
  EXPECT_EQ(0, installer.will_fail_called());
  EXPECT_EQ(0, installer.will_process_called());
  EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
  installer.navigation_throttle()->ResumeNavigation();

  // Wait for WillRedirectRequest.
  installer.WaitForThrottleWillRedirect();
  EXPECT_EQ(1, installer.will_start_called());
  EXPECT_EQ(1, installer.will_redirect_called());
  EXPECT_EQ(0, installer.will_fail_called());
  EXPECT_EQ(0, installer.will_process_called());
  EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
  installer.navigation_throttle()->ResumeNavigation();

  // Wait for WillProcessResponse.
  installer.WaitForThrottleWillProcess();
  EXPECT_EQ(1, installer.will_start_called());
  EXPECT_EQ(1, installer.will_redirect_called());
  EXPECT_EQ(0, installer.will_fail_called());
  EXPECT_EQ(1, installer.will_process_called());
  EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
  installer.navigation_throttle()->ResumeNavigation();

  // Wait for the end of the navigation.
  navigation_observer.Wait();

  EXPECT_TRUE(observer.has_committed());
  EXPECT_TRUE(observer.was_redirected());
  EXPECT_FALSE(observer.is_error());
  EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
            GURL(embedded_test_server()->GetURL("bar.com", "/title2.html")));
}

// Ensure that a NavigationThrottle can defer and resume the navigation at
// navigation start and navigation failure.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ThrottleDeferFailure) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
  ASSERT_TRUE(https_server.Start());
  GURL failure_url(https_server.GetURL("/title1.html"));

  TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
  NavigationHandleObserver observer(shell()->web_contents(), failure_url);
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::DEFER,
      NavigationThrottle::DEFER, NavigationThrottle::DEFER,
      NavigationThrottle::DEFER, NavigationThrottle::DEFER);

  shell()->LoadURL(failure_url);

  // Wait for WillStartRequest.
  installer.WaitForThrottleWillStart();
  EXPECT_EQ(1, installer.will_start_called());
  EXPECT_EQ(0, installer.will_redirect_called());
  EXPECT_EQ(0, installer.will_fail_called());
  EXPECT_EQ(0, installer.will_process_called());
  EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
  installer.navigation_throttle()->ResumeNavigation();

  // Wait for WillFailRequest.
  installer.WaitForThrottleWillFail();
  EXPECT_EQ(1, installer.will_start_called());
  EXPECT_EQ(0, installer.will_redirect_called());
  EXPECT_EQ(1, installer.will_fail_called());
  EXPECT_EQ(0, installer.will_process_called());
  EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
  installer.navigation_throttle()->ResumeNavigation();

  // Wait for the end of the navigation.
  navigation_observer.Wait();

  EXPECT_TRUE(observer.has_committed());
  EXPECT_TRUE(observer.is_error());
  EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, observer.net_error_code());
}

// Ensure that a NavigationThrottle can defer and resume the navigation when
// navigating without a URLLoader. This test covers multiple types of
// navigations that do not require a URLLoader (same-document navigations and
// about:blank).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       ThrottleDeferCommitWithoutUrlLoader) {
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  GURL url_fragment(embedded_test_server()->GetURL("/title1.html#id_1"));
  GURL about_blank_url(url::kAboutBlankURL);

  // Perform a new-document navigation (setup).
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), url);
    EXPECT_TRUE(NavigateToURL(shell(), url));
    EXPECT_EQ(1, installer.will_start_called());
    EXPECT_EQ(1, installer.will_process_called());
    EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
    EXPECT_FALSE(observer.is_same_document());
  }

  // Same-document navigation
  {
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
    NavigationHandleObserver observer(shell()->web_contents(), url_fragment);
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER);

    shell()->LoadURL(url_fragment);

    // Wait for WillCommitWithoutUrlLoader.
    installer.WaitForThrottleWillCommitWithoutUrlLoader();
    EXPECT_EQ(0, installer.will_start_called());
    EXPECT_EQ(0, installer.will_redirect_called());
    EXPECT_EQ(0, installer.will_fail_called());
    EXPECT_EQ(0, installer.will_process_called());
    EXPECT_EQ(1, installer.will_commit_without_url_loader_called());
    installer.navigation_throttle()->ResumeNavigation();

    // Wait for the end of the navigation.
    navigation_observer.Wait();

    EXPECT_TRUE(observer.is_same_document());
    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.was_redirected());
    EXPECT_FALSE(observer.is_error());
    EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), url_fragment);
  }

  // about:blank
  {
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
    NavigationHandleObserver observer(shell()->web_contents(), about_blank_url);
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER);

    shell()->LoadURL(about_blank_url);

    // Wait for WillCommitWithoutUrlLoader.
    installer.WaitForThrottleWillCommitWithoutUrlLoader();
    EXPECT_EQ(0, installer.will_start_called());
    EXPECT_EQ(0, installer.will_redirect_called());
    EXPECT_EQ(0, installer.will_fail_called());
    EXPECT_EQ(0, installer.will_process_called());
    EXPECT_EQ(1, installer.will_commit_without_url_loader_called());
    installer.navigation_throttle()->ResumeNavigation();

    // Wait for the end of the navigation.
    navigation_observer.Wait();

    EXPECT_FALSE(observer.is_same_document());
    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.was_redirected());
    EXPECT_FALSE(observer.is_error());
    EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), about_blank_url);
  }
}

// Ensure that a NavigationThrottle can defer and cancel the navigation when
// navigating without a URLLoader. This test covers multiple types of
// navigations that do not require a URLLoader (same-document navigations and
// about:blank).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       ThrottleDeferAndCancelCommitWithoutUrlLoader) {
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  GURL url_fragment(embedded_test_server()->GetURL("/title1.html#id_1"));
  GURL about_blank_url(url::kAboutBlankURL);

  // Perform a new-document navigation (setup).
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), url);
    EXPECT_TRUE(NavigateToURL(shell(), url));
    EXPECT_EQ(1, installer.will_start_called());
    EXPECT_EQ(1, installer.will_process_called());
    EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
    EXPECT_FALSE(observer.is_same_document());
  }

  // Same-document navigation
  {
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
    NavigationHandleObserver observer(shell()->web_contents(), url_fragment);
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER);

    shell()->LoadURL(url_fragment);

    // Wait for WillCommitWithoutUrlLoader.
    installer.WaitForThrottleWillCommitWithoutUrlLoader();
    EXPECT_EQ(0, installer.will_start_called());
    EXPECT_EQ(0, installer.will_redirect_called());
    EXPECT_EQ(0, installer.will_fail_called());
    EXPECT_EQ(0, installer.will_process_called());
    EXPECT_EQ(1, installer.will_commit_without_url_loader_called());

    // Cancel the deferred navigation.
    installer.navigation_throttle()->CancelNavigation(
        NavigationThrottle::CANCEL_AND_IGNORE);

    // Wait for the end of the navigation.
    navigation_observer.Wait();

    EXPECT_TRUE(observer.is_same_document());
    EXPECT_FALSE(observer.has_committed());
    EXPECT_FALSE(observer.was_redirected());
    EXPECT_TRUE(observer.is_error());
  }

  // about:blank
  {
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
    NavigationHandleObserver observer(shell()->web_contents(), about_blank_url);
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER,
        NavigationThrottle::DEFER, NavigationThrottle::DEFER);

    shell()->LoadURL(about_blank_url);

    // Wait for WillCommitWithoutUrlLoader.
    installer.WaitForThrottleWillCommitWithoutUrlLoader();
    EXPECT_EQ(0, installer.will_start_called());
    EXPECT_EQ(0, installer.will_redirect_called());
    EXPECT_EQ(0, installer.will_fail_called());
    EXPECT_EQ(0, installer.will_process_called());
    EXPECT_EQ(1, installer.will_commit_without_url_loader_called());

    // Cancel the deferred navigation.
    installer.navigation_throttle()->CancelNavigation(
        NavigationThrottle::CANCEL_AND_IGNORE);

    // Wait for the end of the navigation.
    navigation_observer.Wait();

    EXPECT_FALSE(observer.is_same_document());
    EXPECT_FALSE(observer.has_committed());
    EXPECT_FALSE(observer.was_redirected());
    EXPECT_TRUE(observer.is_error());
  }
}

// Ensure that a NavigationThrottle can block the navigation and collapse the
// frame owner both on request start as well as after a redirect. Plus, ensure
// that the frame is restored on the subsequent non-error-page navigation.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ThrottleBlockAndCollapse) {
  const char kChildFrameId[] = "child0";
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/frame_tree/page_with_one_frame.html"));
  GURL blocked_subframe_url(embedded_test_server()->GetURL(
      "a.com", "/cross-site/baz.com/title1.html"));
  GURL allowed_subframe_url(embedded_test_server()->GetURL(
      "a.com", "/cross-site/baz.com/title2.html"));
  GURL allowed_subframe_final_url(
      embedded_test_server()->GetURL("baz.com", "/title2.html"));

  // Exercise both synchronous and deferred throttle check results, and both on
  // WillStartRequest and on WillRedirectRequest.
  const struct {
    NavigationThrottle::ThrottleAction will_start_result;
    NavigationThrottle::ThrottleAction will_redirect_result;
    bool deferred_block;
  } kTestCases[] = {
      {NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
       NavigationThrottle::PROCEED, false},
      {NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
       NavigationThrottle::PROCEED, true},
      {NavigationThrottle::PROCEED,
       NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, false},
      {NavigationThrottle::PROCEED,
       NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, true},
  };

  for (const auto& test_case : kTestCases) {
    SCOPED_TRACE(::testing::Message() << test_case.will_start_result << ", "
                                      << test_case.will_redirect_result << ", "
                                      << test_case.deferred_block);

    std::unique_ptr<TestNavigationThrottleInstaller>
        subframe_throttle_installer;
    if (test_case.deferred_block) {
      subframe_throttle_installer =
          std::make_unique<TestDeferringNavigationThrottleInstaller>(
              shell()->web_contents(), test_case.will_start_result,
              test_case.will_redirect_result, NavigationThrottle::PROCEED,
              NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
              blocked_subframe_url);
    } else {
      subframe_throttle_installer =
          std::make_unique<TestNavigationThrottleInstaller>(
              shell()->web_contents(), test_case.will_start_result,
              test_case.will_redirect_result, NavigationThrottle::PROCEED,
              NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
              blocked_subframe_url);
    }

    {
      SCOPED_TRACE("Initial navigation blocked on main frame load.");
      NavigationHandleObserver subframe_observer(shell()->web_contents(),
                                                 blocked_subframe_url);

      ASSERT_TRUE(NavigateToURL(shell(), main_url));
      EXPECT_TRUE(subframe_observer.is_error());
      EXPECT_TRUE(subframe_observer.has_committed());
      EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, subframe_observer.net_error_code());
      ExpectChildFrameCollapsed(shell(), kChildFrameId,
                                true /* expect_collapsed */);
    }

    {
      SCOPED_TRACE("Subsequent subframe navigation is allowed.");
      NavigationHandleObserver subframe_observer(shell()->web_contents(),
                                                 allowed_subframe_url);

      ASSERT_TRUE(NavigateIframeToURL(shell()->web_contents(), kChildFrameId,
                                      allowed_subframe_url));
      EXPECT_TRUE(subframe_observer.has_committed());
      EXPECT_FALSE(subframe_observer.is_error());
      EXPECT_EQ(allowed_subframe_final_url,
                subframe_observer.last_committed_url());
      ExpectChildFrameCollapsed(shell(), kChildFrameId,
                                false /* expect_collapsed */);
    }

    {
      SCOPED_TRACE("Subsequent subframe navigation is blocked.");
      NavigationHandleObserver subframe_observer(shell()->web_contents(),
                                                 blocked_subframe_url);

      ASSERT_TRUE(NavigateIframeToURL(shell()->web_contents(), kChildFrameId,
                                      blocked_subframe_url));

      EXPECT_TRUE(subframe_observer.has_committed());
      EXPECT_TRUE(subframe_observer.is_error());
      EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, subframe_observer.net_error_code());
      ExpectChildFrameCollapsed(shell(), kChildFrameId,
                                true /* expect_collapsed */);
    }
  }
}

// BLOCK_REQUEST_AND_COLLAPSE should block the navigation in legacy <frame>'s,
// but should not collapse the <frame> element itself for legacy reasons.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       ThrottleBlockAndCollapse_LegacyFrameNotCollapsed) {
  const char kChildFrameId[] = "child0";
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/frame_tree/legacy_frameset.html"));
  GURL blocked_subframe_url(
      embedded_test_server()->GetURL("a.com", "/title1.html"));
  GURL allowed_subframe_url(
      embedded_test_server()->GetURL("a.com", "/title2.html"));

  TestNavigationThrottleInstaller subframe_throttle_installer(
      shell()->web_contents(), NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      blocked_subframe_url);

  {
    SCOPED_TRACE("Initial navigation blocked on main frame load.");
    NavigationHandleObserver subframe_observer(shell()->web_contents(),
                                               blocked_subframe_url);

    ASSERT_TRUE(NavigateToURL(shell(), main_url));
    EXPECT_TRUE(subframe_observer.is_error());
    EXPECT_TRUE(subframe_observer.has_committed());
    EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, subframe_observer.net_error_code());
    ExpectChildFrameSetAsCollapsedInFTN(shell(), true /* expect_collapsed */);
    ExpectChildFrameCollapsedInLayout(shell(), kChildFrameId,
                                      false /* expect_collapsed */);
  }

  {
    SCOPED_TRACE("Subsequent subframe navigation is allowed.");
    NavigationHandleObserver subframe_observer(shell()->web_contents(),
                                               allowed_subframe_url);

    ASSERT_TRUE(NavigateIframeToURL(shell()->web_contents(), kChildFrameId,
                                    allowed_subframe_url));
    EXPECT_TRUE(subframe_observer.has_committed());
    EXPECT_FALSE(subframe_observer.is_error());
    EXPECT_EQ(allowed_subframe_url, subframe_observer.last_committed_url());
    ExpectChildFrameCollapsed(shell(), kChildFrameId,
                              false /* expect_collapsed */);
  }
}

// Checks that the RequestContextType value is properly set.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       VerifyRequestContextTypeForFrameTree) {
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
  GURL b_url(embedded_test_server()->GetURL(
      "b.com", "/cross_site_iframe_factory.html?b(c())"));
  GURL c_url(embedded_test_server()->GetURL(
      "c.com", "/cross_site_iframe_factory.html?c()"));

  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
  TestNavigationManager main_manager(shell()->web_contents(), main_url);
  TestNavigationManager b_manager(shell()->web_contents(), b_url);
  TestNavigationManager c_manager(shell()->web_contents(), c_url);
  NavigationStartUrlRecorder url_recorder(shell()->web_contents());

  // Starts and verifies the main frame navigation.
  shell()->LoadURL(main_url);
  EXPECT_TRUE(main_manager.WaitForRequestStart());
  // For each navigation a new throttle should have been installed.
  EXPECT_EQ(1, installer.install_count());
  // Checks the only URL recorded so far is the one expected for the main frame.
  EXPECT_EQ(main_url, url_recorder.urls().back());
  EXPECT_EQ(1ul, url_recorder.urls().size());
  // Checks the main frame RequestContextType.
  EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
            installer.navigation_throttle()->request_context_type());

  // Ditto for frame b navigation.
  ASSERT_TRUE(main_manager.WaitForNavigationFinished());
  EXPECT_TRUE(b_manager.WaitForRequestStart());
  EXPECT_EQ(2, installer.install_count());
  EXPECT_EQ(b_url, url_recorder.urls().back());
  EXPECT_EQ(2ul, url_recorder.urls().size());
  EXPECT_EQ(blink::mojom::RequestContextType::IFRAME,
            installer.navigation_throttle()->request_context_type());

  // Ditto for frame c navigation.
  ASSERT_TRUE(b_manager.WaitForNavigationFinished());
  EXPECT_TRUE(c_manager.WaitForRequestStart());
  EXPECT_EQ(3, installer.install_count());
  EXPECT_EQ(c_url, url_recorder.urls().back());
  EXPECT_EQ(3ul, url_recorder.urls().size());
  EXPECT_EQ(blink::mojom::RequestContextType::IFRAME,
            installer.navigation_throttle()->request_context_type());

  // Lets the final navigation finish so that we conclude running the
  // RequestContextType checks that happen in TestNavigationThrottle.
  ASSERT_TRUE(c_manager.WaitForNavigationFinished());
  // Confirms the last navigation did finish.
  EXPECT_FALSE(installer.navigation_throttle());
}

// Checks that the RequestContextType value is properly set for an hyper-link.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       VerifyHyperlinkRequestContextType) {
  GURL link_url(embedded_test_server()->GetURL("/title2.html"));
  GURL document_url(embedded_test_server()->GetURL("/simple_links.html"));

  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
  TestNavigationManager link_manager(shell()->web_contents(), link_url);
  NavigationStartUrlRecorder url_recorder(shell()->web_contents());

  // Navigate to a page with a link.
  EXPECT_TRUE(NavigateToURL(shell(), document_url));
  EXPECT_EQ(document_url, url_recorder.urls().back());
  EXPECT_EQ(1ul, url_recorder.urls().size());

  // Starts the navigation from a link click and then check it.
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  EXPECT_EQ(true, EvalJs(shell(), "clickSameSiteLink();"));
  EXPECT_TRUE(link_manager.WaitForRequestStart());
  EXPECT_EQ(link_url, url_recorder.urls().back());
  EXPECT_EQ(2ul, url_recorder.urls().size());
  EXPECT_EQ(blink::mojom::RequestContextType::HYPERLINK,
            installer.navigation_throttle()->request_context_type());

  // Finishes the last navigation.
  ASSERT_TRUE(link_manager.WaitForNavigationFinished());
  EXPECT_FALSE(installer.navigation_throttle());
}

// Checks that the RequestContextType value is properly set for an form (POST).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       VerifyFormRequestContextType) {
  GURL document_url(
      embedded_test_server()->GetURL("/session_history/form.html"));
  GURL post_url(embedded_test_server()->GetURL("/echotitle"));

  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
  TestNavigationManager post_manager(shell()->web_contents(), post_url);
  NavigationStartUrlRecorder url_recorder(shell()->web_contents());

  // Navigate to a page with a form.
  EXPECT_TRUE(NavigateToURL(shell(), document_url));
  EXPECT_EQ(document_url, url_recorder.urls().back());
  EXPECT_EQ(1ul, url_recorder.urls().size());

  // Executes the form POST navigation and then check it.
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  GURL submit_url("javascript:submitForm('isubmit')");
  shell()->LoadURL(submit_url);
  EXPECT_TRUE(post_manager.WaitForRequestStart());
  EXPECT_EQ(post_url, url_recorder.urls().back());
  EXPECT_EQ(2ul, url_recorder.urls().size());
  EXPECT_EQ(blink::mojom::RequestContextType::FORM,
            installer.navigation_throttle()->request_context_type());

  // Finishes the last navigation.
  ASSERT_TRUE(post_manager.WaitForNavigationFinished());
  EXPECT_FALSE(installer.navigation_throttle());
}

// Checks that the error code is properly set on the NavigationHandle when a
// NavigationThrottle cancels.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       ErrorCodeOnThrottleCancelNavigation) {
  const GURL kUrl = embedded_test_server()->GetURL("/title1.html");
  const GURL kRedirectingUrl =
      embedded_test_server()->GetURL("/server-redirect?" + kUrl.spec());

  {
    // Set up a NavigationThrottle that will cancel the navigation in
    // WillStartRequest.
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::CANCEL_AND_IGNORE,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), kUrl);

    // Try to navigate to the url. The navigation should be canceled and the
    // NavigationHandle should have the right error code.
    EXPECT_FALSE(NavigateToURL(shell(), kUrl));
    EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
  }

  {
    // Set up a NavigationThrottle that will cancel the navigation in
    // WillRedirectRequest.
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::CANCEL_AND_IGNORE, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), kRedirectingUrl);

    // Try to navigate to the url. The navigation should be canceled and the
    // NavigationHandle should have the right error code.
    EXPECT_FALSE(NavigateToURL(shell(), kRedirectingUrl));
    EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
  }

  {
    // Set up a NavigationThrottle that will cancel the navigation in
    // WillProcessResponse.
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::CANCEL_AND_IGNORE, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), kUrl);

    // Try to navigate to the url. The navigation should be canceled and the
    // NavigationHandle should have the right error code.
    EXPECT_FALSE(NavigateToURL(shell(), kUrl));
    EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
  }

  {
    // Set up a NavigationThrottle that will block the navigation in
    // WillStartRequest.
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::BLOCK_REQUEST,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), kUrl);

    // Try to navigate to the url. The navigation should be canceled and the
    // NavigationHandle should have the right error code.
    EXPECT_FALSE(NavigateToURL(shell(), kUrl));
    EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, observer.net_error_code());
  }

  // Set up a NavigationThrottle that will block the navigation in
  // WillRedirectRequest.
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::BLOCK_REQUEST, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
  NavigationHandleObserver observer(shell()->web_contents(), kRedirectingUrl);

  // Try to navigate to the url. The navigation should be canceled and the
  // NavigationHandle should have the right error code.
  EXPECT_FALSE(NavigateToURL(shell(), kRedirectingUrl));
  EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, observer.net_error_code());
}

// Checks that there's no UAF if NavigationRequest::WillStartRequest cancels the
// navigation.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       CancelNavigationInWillStartRequest) {
  const GURL kUrl1 = embedded_test_server()->GetURL("/title1.html");
  const GURL kUrl2 = embedded_test_server()->GetURL("/title2.html");
  // First make a successful commit, as this issue only reproduces when there
  // are existing entries (i.e. when NavigationControllerImpl::GetVisibleEntry
  // has safe_to_show_pending=false).
  EXPECT_TRUE(NavigateToURL(shell(), kUrl1));

  // To take the path that doesn't run beforeunload, so that
  // NavigationControllerImpl::NavigateToPendingEntry is on the botttom of the
  // stack when NavigationRequest::WillStartRequest is called.
  CrashTab(shell()->web_contents());

  // Set up a NavigationThrottle that will cancel the navigation in
  // WillStartRequest.
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::CANCEL_AND_IGNORE,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

  EXPECT_FALSE(NavigateToURL(shell(), kUrl2));
}

// Verify that a cross-process navigation in a frame for which the current
// renderer process is not live will not result in leaking a
// RenderProcessHost. See https://crbug.com/949977.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       NoLeakFromStartingSiteInstance) {
  IsolateOriginsForTesting(embedded_test_server(), shell()->web_contents(),
                           {"b.com"});

  GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html");
  EXPECT_TRUE(NavigateToURL(shell(), url_a));

  // Kill the a.com process, to test what happens with the next navigation.
  scoped_refptr<SiteInstance> site_instance_a =
      shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance();
  EXPECT_TRUE(site_instance_a->HasProcess());
  RenderProcessHost* process_1 = site_instance_a->GetProcess();
  RenderProcessHostWatcher process_exit_observer_1(
      process_1, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
  RenderProcessHostWatcher rph_gone_observer_1(
      process_1, content::RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
  process_1->Shutdown(RESULT_CODE_KILLED);
  process_exit_observer_1.Wait();

  // Start to navigate the sad tab to another site.
  GURL url_b = embedded_test_server()->GetURL("b.com", "/title2.html");
  TestNavigationManager navigation_b(shell()->web_contents(), url_b);
  shell()->web_contents()->GetController().LoadURL(
      url_b, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  EXPECT_TRUE(navigation_b.WaitForRequestStart());

  // The starting SiteInstance should be the SiteInstance of the current
  // RenderFrameHost.
  scoped_refptr<SiteInstance> starting_site_instance =
      navigation_b.GetNavigationHandle()->GetStartingSiteInstance();
  EXPECT_EQ(shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance(),
            starting_site_instance);
  if (ShouldSkipEarlyCommitPendingForCrashedFrame()) {
    EXPECT_EQ(GURL("http://a.com"), starting_site_instance->GetSiteURL());
  } else {
    // Because of the sad tab, this is actually the b.com SiteInstance, which
    // commits immediately after starting the navigation and has a process.
    EXPECT_EQ(GURL("http://b.com"), starting_site_instance->GetSiteURL());
  }
  EXPECT_TRUE(starting_site_instance->HasProcess());

  // In https://crbug.com/949977, we used the a.com SiteInstance here and didn't
  // have a process, and an observer called GetProcess, creating a process. This
  // RPH never went away, even after the SiteInstance was gone. Simulate this
  // by creating a new RPH for site_instance_a directly. Note that the actual
  // process may not get created (only if the spare process is in use), so wait
  // for RPH destruction rather than process exit.
  RenderProcessHost* rph_2 = site_instance_a->GetProcess();
  RenderProcessHostWatcher process_exit_observer_2(
      rph_2, content::RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
  ASSERT_TRUE(navigation_b.WaitForNavigationFinished());

  // Ensure RPH 1 is destroyed, which happens at commit time even before the fix
  // for the bug.
  rph_gone_observer_1.Wait();

  // Navigate to another process. This isn't necessary to trigger the original
  // leak (when the starting SiteInstance was a.com), but it lets the test
  // finish in the case that the starting SiteInstance is b.com, since b.com's
  // process goes away with this navigation.
  // TODO(creis): There's still a slight risk that other buggy code could find
  // site_instance_a and call GetProcess() on it, causing a leak. We'll add a
  // backup fix and test for that in a followup CL.
  GURL url_c = embedded_test_server()->GetURL("c.com", "/title1.html");
  EXPECT_TRUE(NavigateToURL(shell()->web_contents(), url_c));

  // Remove all references to site_instance_a so that we can be sure its process
  // gets cleaned up. Pruning the NavigationEntry for url_a on the tab simulates
  // closing the tab (from that SiteInstance's perspective).
  site_instance_a = nullptr;
  starting_site_instance = nullptr;
  shell()->web_contents()->GetController().PruneAllButLastCommitted();

  // Wait for rph_2 to exit when it's not used. This wouldn't happen when the
  // bug was present.
  process_exit_observer_2.Wait();
}

// Specialized test that verifies the NavigationHandle gets the HTTPS upgraded
// URL from the very beginning of the navigation.
class NavigationRequestHttpsUpgradeBrowserTest
    : public NavigationRequestBrowserTest {
 public:
  void CheckHttpsUpgradedIframeNavigation(const GURL& start_url,
                                          const GURL& iframe_secure_url) {
    ASSERT_TRUE(start_url.SchemeIs(url::kHttpScheme));
    ASSERT_TRUE(iframe_secure_url.SchemeIs(url::kHttpsScheme));

    NavigationStartUrlRecorder url_recorder(shell()->web_contents());
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    TestNavigationManager navigation_manager(shell()->web_contents(),
                                             iframe_secure_url);

    // Load the page and wait for the frame load with the expected URL.
    // Note: if the test times out while waiting then a navigation to
    // iframe_secure_url never happened and the expected upgrade may not be
    // working.
    shell()->LoadURL(start_url);
    EXPECT_TRUE(navigation_manager.WaitForRequestStart());

    // The main frame should have finished navigating while the iframe should
    // have just started.
    EXPECT_EQ(2, installer.will_start_called());
    EXPECT_EQ(0, installer.will_redirect_called());
    EXPECT_EQ(1, installer.will_process_called());

    // Check the correct start URLs have been registered.
    EXPECT_EQ(iframe_secure_url, url_recorder.urls().back());
    EXPECT_EQ(start_url, url_recorder.urls().front());
    EXPECT_EQ(2ul, url_recorder.urls().size());
  }
};

// Tests that the start URL is HTTPS upgraded for a same site navigation.
IN_PROC_BROWSER_TEST_F(NavigationRequestHttpsUpgradeBrowserTest,
                       StartUrlIsHttpsUpgradedSameSite) {
  GURL start_url(embedded_test_server()->GetURL(
      "example.com", "/https_upgrade_same_site.html"));

  // Builds the expected upgraded same site URL.
  GURL::Replacements replace_scheme;
  replace_scheme.SetSchemeStr("https");
  GURL cross_site_iframe_secure_url =
      embedded_test_server()
          ->GetURL("example.com", "/title1.html")
          .ReplaceComponents(replace_scheme);

  CheckHttpsUpgradedIframeNavigation(start_url, cross_site_iframe_secure_url);
}

// Tests that the start URL is HTTPS upgraded for a cross site navigation.
IN_PROC_BROWSER_TEST_F(NavigationRequestHttpsUpgradeBrowserTest,
                       StartUrlIsHttpsUpgradedCrossSite) {
  GURL start_url(
      embedded_test_server()->GetURL("/https_upgrade_cross_site.html"));
  GURL cross_site_iframe_secure_url("https://other.com/title1.html");

  CheckHttpsUpgradedIframeNavigation(start_url, cross_site_iframe_secure_url);
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       BrowserInitiatedMainFrameReload) {
  GURL url = embedded_test_server()->GetURL("/hello.html");
  EXPECT_TRUE(NavigateToURL(shell(), url));

  NavigationHandleObserver handle_observer(shell()->web_contents(), url);
  TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
  shell()->Reload();
  navigation_observer.Wait();

  EXPECT_EQ(handle_observer.reload_type(), ReloadType::NORMAL);
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       BrowserInitiatedSubFrameReload) {
  GURL url = embedded_test_server()->GetURL("/page_with_iframe.html");
  EXPECT_TRUE(NavigateToURL(shell(), url));

  NavigationHandleObserver handle_observer(
      shell()->web_contents(), embedded_test_server()->GetURL("/title1.html"));
  TestNavigationObserver navigation_observer(shell()->web_contents(), 1);

  RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetPrimaryMainFrame());
  ASSERT_EQ(1u, main_frame->child_count());
  FrameTreeNode* child = main_frame->child_at(0u);
  auto* navigation_controller = static_cast<NavigationControllerImpl*>(
      &shell()->web_contents()->GetController());
  navigation_controller->ReloadFrame(child);
  navigation_observer.Wait();

  EXPECT_EQ(handle_observer.reload_type(), ReloadType::NORMAL);
  EXPECT_FALSE(handle_observer.is_main_frame());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RendererInitiatedMainFrameReload) {
  GURL url = embedded_test_server()->GetURL("/hello.html");
  EXPECT_TRUE(NavigateToURL(shell(), url));
  NavigationHandleObserver observer(shell()->web_contents(), url);
  EXPECT_TRUE(ExecJs(shell(), "location.reload();"));
  EXPECT_EQ(observer.reload_type(), ReloadType::NORMAL);
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RendererInitiatedSubFrameReload) {
  GURL url = embedded_test_server()->GetURL("/page_with_iframe.html");
  EXPECT_TRUE(NavigateToURL(shell(), url));

  NavigationHandleObserver handle_observer(
      shell()->web_contents(), embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(ExecJs(shell(),
                     "document.getElementById('test_iframe')."
                     "contentWindow.location.reload();"));
  EXPECT_EQ(handle_observer.reload_type(), ReloadType::NORMAL);
  EXPECT_FALSE(handle_observer.is_main_frame());
}

// Ensure that browser-initiated same-document navigations are detected and
// don't issue network requests.  See crbug.com/663777.
// Browser-initiated same-document navigations should trigger a
// WillCommitWithoutUrlLoader() callback, instead of the WillStartRequest()
// and WillProcessResponse() callbacks used when there is a network request.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       SameDocumentBrowserInitiatedNoReload) {
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  GURL url_fragment_1(embedded_test_server()->GetURL("/title1.html#id_1"));
  GURL url_fragment_2(embedded_test_server()->GetURL("/title1.html#id_2"));

  // 1) Perform a new-document navigation.
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), url);
    EXPECT_TRUE(NavigateToURL(shell(), url));
    EXPECT_EQ(1, installer.will_start_called());
    EXPECT_EQ(1, installer.will_process_called());
    EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
    EXPECT_FALSE(observer.is_same_document());
  }

  // 2) Perform a same-document navigation by adding a fragment.
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), url_fragment_1);
    EXPECT_TRUE(NavigateToURL(shell(), url_fragment_1));
    EXPECT_EQ(0, installer.will_start_called());
    EXPECT_EQ(0, installer.will_process_called());
    EXPECT_EQ(1, installer.will_commit_without_url_loader_called());
    EXPECT_TRUE(observer.is_same_document());
  }

  // 3) Perform a same-document navigation by modifying the fragment.
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), url_fragment_2);
    EXPECT_TRUE(NavigateToURL(shell(), url_fragment_2));
    EXPECT_EQ(0, installer.will_start_called());
    EXPECT_EQ(0, installer.will_process_called());
    EXPECT_EQ(1, installer.will_commit_without_url_loader_called());
    EXPECT_TRUE(observer.is_same_document());
  }

  // 4) Redo the last navigation, but this time it should trigger a reload.
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), url_fragment_2);
    EXPECT_TRUE(NavigateToURL(shell(), url_fragment_2));
    EXPECT_EQ(1, installer.will_start_called());
    EXPECT_EQ(1, installer.will_process_called());
    EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
    EXPECT_FALSE(observer.is_same_document());
  }

  // 5) Perform a new-document navigation by removing the fragment.
  {
    TestNavigationThrottleInstaller installer(
        shell()->web_contents(), NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
    NavigationHandleObserver observer(shell()->web_contents(), url);
    EXPECT_TRUE(NavigateToURL(shell(), url));
    EXPECT_EQ(1, installer.will_start_called());
    EXPECT_EQ(1, installer.will_process_called());
    EXPECT_EQ(0, installer.will_commit_without_url_loader_called());
    EXPECT_FALSE(observer.is_same_document());
  }
}

class NavigationRequestHostResolutionFailureTest : public ContentBrowserTest {
 protected:
  void SetUpOnMainThread() override {
    host_resolver()->AddSimulatedTimeoutFailure("*");
    ASSERT_TRUE(embedded_test_server()->Start());
  }
};

IN_PROC_BROWSER_TEST_F(NavigationRequestHostResolutionFailureTest,
                       HostResolutionFailure) {
  GURL url(embedded_test_server()->GetURL("example.com", "/title1.html"));

  NavigationHandleObserver observer(shell()->web_contents(), url);

  EXPECT_FALSE(NavigateToURL(shell(), url));

  EXPECT_TRUE(observer.has_committed());
  EXPECT_TRUE(observer.is_error());
  EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, observer.net_error_code());
  EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.resolve_error_info().error);
}

// Record and list the navigations that are started and finished.
class NavigationLogger : public WebContentsObserver {
 public:
  explicit NavigationLogger(WebContents* web_contents)
      : WebContentsObserver(web_contents) {}

  void DidStartNavigation(NavigationHandle* navigation_handle) override {
    started_navigation_urls_.push_back(navigation_handle->GetURL());
  }

  void DidRedirectNavigation(NavigationHandle* navigation_handle) override {
    redirected_navigation_urls_.push_back(navigation_handle->GetURL());
  }

  void DidFinishNavigation(NavigationHandle* navigation_handle) override {
    finished_navigation_urls_.push_back(navigation_handle->GetURL());
  }

  const std::vector<GURL>& started_navigation_urls() const {
    return started_navigation_urls_;
  }
  const std::vector<GURL>& redirected_navigation_urls() const {
    return redirected_navigation_urls_;
  }
  const std::vector<GURL>& finished_navigation_urls() const {
    return finished_navigation_urls_;
  }

 private:
  std::vector<GURL> started_navigation_urls_;
  std::vector<GURL> redirected_navigation_urls_;
  std::vector<GURL> finished_navigation_urls_;
};

// Verifies that when a navigation is blocked after a redirect, the renderer
// doesn't try to commit an error page to the pre-redirect URL. This would cause
// a NavigationHandle mismatch and a new NavigationHandle creation to commit
// the error page. This test makes sure that only one NavigationHandle is used
// for committing the error page. See https://crbug.com/695421
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, BlockedOnRedirect) {
  const GURL kUrl = embedded_test_server()->GetURL("/title1.html");
  const GURL kRedirectingUrl =
      embedded_test_server()->GetURL("/server-redirect?" + kUrl.spec());

  // Set up a NavigationThrottle that will block the navigation in
  // WillRedirectRequest.
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::BLOCK_REQUEST, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
  NavigationHandleObserver observer(shell()->web_contents(), kRedirectingUrl);
  NavigationLogger logger(shell()->web_contents());

  // Try to navigate to the url. The navigation should be canceled and the
  // NavigationHandle should have the right error code.
  EXPECT_FALSE(NavigateToURL(shell(), kRedirectingUrl));
  // EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, observer.net_error_code());

  // Only one navigation is expected to happen.
  std::vector<GURL> started_navigation = {kRedirectingUrl};
  EXPECT_EQ(started_navigation, logger.started_navigation_urls());

  std::vector<GURL> finished_navigation = {kUrl};
  EXPECT_EQ(finished_navigation, logger.finished_navigation_urls());
}

// Tests that when a navigation starts while there's an existing one, the first
// one has the right error code set on its navigation handle.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ErrorCodeOnCancel) {
  GURL slow_url = embedded_test_server()->GetURL("/slow?60");
  NavigationHandleObserver observer(shell()->web_contents(), slow_url);
  shell()->LoadURL(slow_url);

  GURL url2(embedded_test_server()->GetURL("/title1.html"));
  TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
  shell()->LoadURL(url2);
  same_tab_observer.Wait();

  EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
}

// Tests that when a renderer-initiated request redirects to a URL that the
// renderer can't access, the right error code is set on the NavigationHandle.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ErrorCodeOnRedirect) {
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), url));

  GURL redirect_url =
      embedded_test_server()->GetURL(std::string("/server-redirect?") +
                                     blink::kChromeUINetworkErrorsListingURL);
  NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
  TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
  EXPECT_TRUE(ExecJs(shell(), base::StringPrintf("location.href = '%s';",
                                                 redirect_url.spec().c_str())));
  same_tab_observer.Wait();
  EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, observer.net_error_code());
}

// Test to verify that error pages caused by NavigationThrottle blocking a
// request in the main frame from being made are properly committed in a
// separate error page process.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       ErrorPageBlockedNavigation) {
  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  GURL blocked_url(embedded_test_server()->GetURL("bar.com", "/title2.html"));

  {
    NavigationHandleObserver observer(shell()->web_contents(), start_url);
    EXPECT_TRUE(NavigateToURL(shell(), start_url));
    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
  }

  scoped_refptr<SiteInstance> site_instance =
      shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance();

  auto installer = std::make_unique<TestNavigationThrottleInstaller>(
      shell()->web_contents(), NavigationThrottle::BLOCK_REQUEST,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

  {
    // A blocked, renderer-initiated navigation in the main frame should commit
    // an error page in a new process.
    NavigationHandleObserver observer(shell()->web_contents(), blocked_url);
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
    EXPECT_TRUE(
        ExecJs(shell(), base::StringPrintf("location.href = '%s'",
                                           blocked_url.spec().c_str())));
    navigation_observer.Wait();
    EXPECT_TRUE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());
    if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
      EXPECT_NE(
          site_instance,
          shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance());
      EXPECT_EQ(kUnreachableWebDataURL, shell()
                                            ->web_contents()
                                            ->GetPrimaryMainFrame()
                                            ->GetSiteInstance()
                                            ->GetSiteURL());
    } else {
      EXPECT_EQ(
          site_instance,
          shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance());
    }
  }

  {
    // Reloading the blocked document from the browser process still ends up
    // in the error page process.
    int process_id =
        shell()->web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
    NavigationHandleObserver observer(shell()->web_contents(), blocked_url);
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);

    shell()->Reload();
    navigation_observer.Wait();
    EXPECT_TRUE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());
    if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
      EXPECT_EQ(kUnreachableWebDataURL, shell()
                                            ->web_contents()
                                            ->GetPrimaryMainFrame()
                                            ->GetSiteInstance()
                                            ->GetSiteURL());
      EXPECT_EQ(process_id, shell()
                                ->web_contents()
                                ->GetPrimaryMainFrame()
                                ->GetProcess()
                                ->GetID());
    } else if (AreAllSitesIsolatedForTesting()) {
      EXPECT_NE(
          site_instance,
          shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance());
    } else {
      EXPECT_EQ(
          site_instance,
          shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance());
    }
  }

  installer.reset();

  {
    // With the throttle uninstalled, going back should return to |start_url| in
    // the same process, and clear the error page.
    NavigationHandleObserver observer(shell()->web_contents(), start_url);
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);

    shell()->GoBackOrForward(-1);
    navigation_observer.Wait();
    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
    EXPECT_EQ(
        site_instance,
        shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance());
  }

  installer = std::make_unique<TestNavigationThrottleInstaller>(
      shell()->web_contents(), NavigationThrottle::BLOCK_REQUEST,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

  {
    // A blocked, browser-initiated navigation should commit an error page in a
    // different process.
    NavigationHandleObserver observer(shell()->web_contents(), blocked_url);
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);

    EXPECT_FALSE(NavigateToURL(shell(), blocked_url));

    navigation_observer.Wait();
    EXPECT_TRUE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());
    EXPECT_NE(
        site_instance,
        shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance());
    if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
      EXPECT_EQ(kUnreachableWebDataURL, shell()
                                            ->web_contents()
                                            ->GetPrimaryMainFrame()
                                            ->GetSiteInstance()
                                            ->GetSiteURL());
    }
  }

  installer.reset();

  {
    // A blocked subframe navigation should commit an error page in the error
    // page process or stay in the same process, based on the isolation policy.
    EXPECT_TRUE(NavigateToURL(shell(), start_url));
    const std::string javascript =
        "var i = document.createElement('iframe');"
        "i.src = '" +
        blocked_url.spec() +
        "';"
        "document.body.appendChild(i);";

    installer = std::make_unique<TestNavigationThrottleInstaller>(
        shell()->web_contents(), NavigationThrottle::BLOCK_REQUEST,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

    content::RenderFrameHost* rfh =
        shell()->web_contents()->GetPrimaryMainFrame();
    scoped_refptr<SiteInstance> initial_site_instance = rfh->GetSiteInstance();
    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
    ASSERT_TRUE(content::ExecJs(rfh, javascript));
    navigation_observer.Wait();

    FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                              ->GetPrimaryFrameTree()
                              .root();
    ASSERT_EQ(1u, root->child_count());
    FrameTreeNode* child = root->child_at(0u);

    EXPECT_TRUE(IsExpectedSubframeErrorTransition(
        initial_site_instance.get(),
        child->current_frame_host()->GetSiteInstance()));
  }
}

// Test to verify that error pages caused by network error or other
// recoverable error are properly committed in the process for the
// destination URL.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, ErrorPageNetworkError) {
  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  GURL error_url(embedded_test_server()->GetURL("/close-socket"));
  EXPECT_NE(start_url.host(), error_url.host());
  GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE, base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));

  {
    NavigationHandleObserver observer(shell()->web_contents(), start_url);
    EXPECT_TRUE(NavigateToURL(shell(), start_url));
    EXPECT_TRUE(observer.has_committed());
    EXPECT_FALSE(observer.is_error());
  }

  scoped_refptr<SiteInstance> site_instance =
      shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance();
  {
    NavigationHandleObserver observer(shell()->web_contents(), error_url);
    EXPECT_FALSE(NavigateToURL(shell(), error_url));
    EXPECT_TRUE(observer.has_committed());
    EXPECT_TRUE(observer.is_error());
    EXPECT_NE(
        site_instance,
        shell()->web_contents()->GetPrimaryMainFrame()->GetSiteInstance());
    if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
      EXPECT_EQ(kUnreachableWebDataURL, shell()
                                            ->web_contents()
                                            ->GetPrimaryMainFrame()
                                            ->GetSiteInstance()
                                            ->GetSiteURL());
    }
  }
}

class ReadyToCommitObserver : public WebContentsObserver {
 public:
  explicit ReadyToCommitObserver(WebContents* web_contents) {
    WebContentsObserver::Observe(web_contents);
  }

  bool ReadyToCommitNavigationWasCalled() const {
    return ready_to_commit_navigation_called_;
  }

 protected:
  void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override {
    ready_to_commit_navigation_called_ = true;
  }

  bool ready_to_commit_navigation_called_ = false;
};

// Ensure that adding a deferring condition that's already satisfied when
// checked (i.e. can return synchronously) doesn't block commit.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       SynchronouslyCompleteCommitDeferringCondition) {
  GURL simple_url(embedded_test_server()->GetURL("/simple_page.html"));

  TestNavigationManager manager(shell()->web_contents(), simple_url);
  WebContents* web_contents = shell()->web_contents();
  ReadyToCommitObserver observer(web_contents);

  MockCommitDeferringConditionInstaller installer(
      simple_url, CommitDeferringCondition::Result::kProceed);

  shell()->LoadURL(simple_url);
  ASSERT_TRUE(manager.WaitForResponse());
  manager.ResumeNavigation();

  // Ready to commit should be reached synchronously after a response.
  EXPECT_TRUE(installer.condition().WasInvoked());
  EXPECT_TRUE(observer.ReadyToCommitNavigationWasCalled());
  EXPECT_TRUE(manager.GetNavigationHandle()->IsWaitingToCommit());

  ASSERT_TRUE(manager.WaitForNavigationFinished());
}

// Ensure asynchronously deferring conditions block the navigation when it's
// ready to commit.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       AsyncCommitDeferringCondition) {
  GURL simple_url(embedded_test_server()->GetURL("/simple_page.html"));

  TestNavigationManager manager(shell()->web_contents(), simple_url);
  WebContents* web_contents = shell()->web_contents();

  MockCommitDeferringConditionInstaller installer1(
      simple_url, CommitDeferringCondition::Result::kDefer);
  MockCommitDeferringConditionInstaller installer2(
      simple_url, CommitDeferringCondition::Result::kDefer);

  ReadyToCommitObserver observer(web_contents);

  shell()->LoadURL(simple_url);
  ASSERT_TRUE(manager.WaitForResponse());
  manager.ResumeNavigation();

  NavigationRequest* request =
      static_cast<NavigationRequest*>(manager.GetNavigationHandle());

  // The navigation should not have proceeded through to ReadyToCommit because
  // the first condition is deferring it. The second condition should not be
  // checked until the first is resolved.
  EXPECT_LT(request->state(), NavigationRequest::READY_TO_COMMIT);
  EXPECT_FALSE(observer.ReadyToCommitNavigationWasCalled());
  EXPECT_TRUE(installer1.condition().WasInvoked());
  EXPECT_FALSE(installer2.condition().WasInvoked());
  EXPECT_TRUE(request->IsCommitDeferringConditionDeferredForTesting());

  // Resume from the first condition. This should now block on the second
  // condition.
  installer1.condition().CallResumeClosure();
  EXPECT_LT(request->state(), NavigationRequest::READY_TO_COMMIT);
  EXPECT_FALSE(observer.ReadyToCommitNavigationWasCalled());
  EXPECT_TRUE(installer2.condition().WasInvoked());

  // Resuming from the second condition should now resume the navigaiton. This
  // should call ReadyToCommit and commit the navigation.
  installer2.condition().CallResumeClosure();
  EXPECT_TRUE(observer.ReadyToCommitNavigationWasCalled());
  EXPECT_EQ(request->state(), NavigationRequest::READY_TO_COMMIT);
  EXPECT_FALSE(request->IsCommitDeferringConditionDeferredForTesting());
  ASSERT_TRUE(manager.WaitForNavigationFinished());
}

// Ensure a navigation can be cancelled while an asynchronously deferring
// condition is blocking commit.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       CancelWhileCommitDeferred) {
  GURL simple_url(embedded_test_server()->GetURL("/simple_page.html"));

  TestNavigationManager manager(shell()->web_contents(), simple_url);
  WebContents* web_contents = shell()->web_contents();

  MockCommitDeferringConditionInstaller installer1(
      simple_url, CommitDeferringCondition::Result::kDefer);

  // We'll cancel the navigation while the first condition is deferred so this
  // is added only to make sure it's never invoked.
  MockCommitDeferringConditionInstaller installer2(
      simple_url, CommitDeferringCondition::Result::kDefer);

  shell()->LoadURL(simple_url);
  ASSERT_TRUE(manager.WaitForResponse());
  manager.ResumeNavigation();

  NavigationRequest* request =
      static_cast<NavigationRequest*>(manager.GetNavigationHandle());

  // The navigation should have passed all checks but is now deferred from
  // committing by |condition|.
  EXPECT_LT(request->state(), NavigationRequest::READY_TO_COMMIT);
  EXPECT_TRUE(installer1.condition().WasInvoked());
  EXPECT_TRUE(request->IsCommitDeferringConditionDeferredForTesting());

  // While the commit is deferred, cancel the navigation. This should delete
  // the navigation request.
  EXPECT_FALSE(installer1.condition().IsDestroyed());
  web_contents->Stop();
  ASSERT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_EQ(manager.GetNavigationHandle(), nullptr);
  EXPECT_TRUE(installer1.condition().IsDestroyed());
  EXPECT_TRUE(installer2.condition().IsDestroyed());

  // Call resume on `installer1`'s condition, as could happen when e.g. the
  // renderer responds after the navigation is stopped. Make sure we don't
  // crash.
  installer1.condition().CallResumeClosure();

  EXPECT_FALSE(installer2.condition().WasInvoked());
}

// Ensure throttles registered by tests using RegisterThrottleForTesting() are
// executed after those registered by the WebContents' browser client (i.e. how
// non-test throttles are normally registered).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RegisterThrottleForTestingIsLast) {
  WebContents* web_contents = shell()->web_contents();
  GURL simple_url(embedded_test_server()->GetURL("/simple_page.html"));

  TestNavigationThrottle* client_throttle = nullptr;

  // Set the client to register a TestNavigationThrottle that defers in
  // WillStartRequest. We'll save a pointer to this throttle in
  // |client_throttle| when its registered.
  content::ShellContentBrowserClient::Get()
      ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting(
          [&client_throttle](content::NavigationHandle* handle)
              -> std::vector<std::unique_ptr<content::NavigationThrottle>> {
            std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
            std::unique_ptr<TestNavigationThrottle> throttle(
                new TestNavigationThrottle(
                    handle, NavigationThrottle::DEFER,
                    NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
                    NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
                    base::DoNothing(), base::DoNothing(), base::DoNothing(),
                    base::DoNothing(), base::DoNothing()));
            client_throttle = throttle.get();
            throttles.push_back(std::move(throttle));
            return throttles;
          }));

  // Add another similar throttle using the installer which will use
  // RegisterThrottleForTesting and registers throttles in DidStartNavigation,
  // before browser client throttles are registered.
  TestNavigationThrottleInstaller test_throttle_installer(
      web_contents, NavigationThrottle::DEFER, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED);

  // Start navigating.
  TestNavigationManager manager(shell()->web_contents(), simple_url);
  shell()->LoadURL(simple_url);
  auto* handle = manager.GetNavigationHandle();
  auto* runner =
      NavigationRequest::From(handle)->GetNavigationThrottleRunnerForTesting();

  // The navigation should have been deferred by one of our throttles. Ensure
  // it's the client throttle since we explicitly want test throttles to
  // execute after all others.
  ASSERT_TRUE(handle->IsDeferredForTesting());
  ASSERT_NE(client_throttle, nullptr);
  EXPECT_EQ(runner->GetDeferringThrottle(), client_throttle);

  // Now when we resume we should get deferred by the other throttle. This
  // should be the throttle installed via RegisterThrottleForTesting.
  client_throttle->ResumeNavigation();
  ASSERT_TRUE(handle->IsDeferredForTesting());
  EXPECT_EQ(runner->GetDeferringThrottle(),
            test_throttle_installer.navigation_throttle());

  // Finish the navigation.
  test_throttle_installer.navigation_throttle()->ResumeNavigation();
  ASSERT_TRUE(manager.WaitForNavigationFinished());
}

// Tests the case where a browser-initiated navigation to a normal webpage is
// blocked (net::ERR_BLOCKED_BY_CLIENT) while departing from a privileged WebUI
// page (chrome://gpu). It is a security risk for the error page to commit in
// the privileged process.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, BlockedRequestAfterWebUI) {
  GURL web_ui_url(GetWebUIURL("gpu"));
  WebContents* web_contents = shell()->web_contents();

  // Navigate to the initial page.
  EXPECT_FALSE(web_contents->GetPrimaryMainFrame()->GetEnabledBindings() &
               BINDINGS_POLICY_WEB_UI);
  EXPECT_TRUE(NavigateToURL(shell(), web_ui_url));
  EXPECT_TRUE(web_contents->GetPrimaryMainFrame()->GetEnabledBindings() &
              BINDINGS_POLICY_WEB_UI);
  scoped_refptr<SiteInstance> web_ui_process = web_contents->GetSiteInstance();

  // Start a new, non-webUI navigation that will be blocked by a
  // NavigationThrottle.
  GURL blocked_url("http://blocked-by-throttle.example.cc");
  TestNavigationThrottleInstaller installer(
      web_contents, NavigationThrottle::BLOCK_REQUEST,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
  NavigationHandleObserver commit_observer(web_contents, blocked_url);
  EXPECT_FALSE(NavigateToURL(shell(), blocked_url));
  NavigationEntry* last_committed =
      web_contents->GetController().GetLastCommittedEntry();
  EXPECT_TRUE(last_committed);
  EXPECT_EQ(blocked_url, last_committed->GetVirtualURL());
  EXPECT_EQ(PAGE_TYPE_ERROR, last_committed->GetPageType());
  EXPECT_NE(web_ui_process.get(), web_contents->GetSiteInstance());
  EXPECT_TRUE(commit_observer.has_committed());
  EXPECT_TRUE(commit_observer.is_error());
  EXPECT_FALSE(commit_observer.is_renderer_initiated());
}

// Redirects to renderer debug URLs caused problems.
// See https://crbug.com/728398.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RedirectToRendererDebugUrl) {
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), url));

  const GURL kTestUrls[] = {GURL("javascript:window.alert('hello')"),
                            GURL(blink::kChromeUIBadCastCrashURL),
                            GURL(blink::kChromeUICrashURL),
                            GURL(blink::kChromeUIDumpURL),
                            GURL(blink::kChromeUIKillURL),
                            GURL(blink::kChromeUIHangURL),
                            GURL(blink::kChromeUIShorthangURL),
                            GURL(blink::kChromeUIMemoryExhaustURL)};

  for (const auto& test_url : kTestUrls) {
    SCOPED_TRACE(testing::Message() << "renderer_debug_url = " << test_url);

    GURL redirecting_url =
        embedded_test_server()->GetURL("/server-redirect?" + test_url.spec());

    NavigationHandleObserver observer(shell()->web_contents(), redirecting_url);
    NavigationLogger logger(shell()->web_contents());

    // Try to navigate to the url. The navigation should be canceled and the
    // NavigationHandle should have the right error code.  Note that javascript
    // URLS use ERR_ABORTED rather than ERR_UNSAFE_REDIRECT due to
    // https://crbug.com/941653.
    EXPECT_FALSE(NavigateToURL(shell(), redirecting_url));
    int expected_err_code = test_url.SchemeIs("javascript")
                                ? net::ERR_ABORTED
                                : net::ERR_UNSAFE_REDIRECT;
    EXPECT_EQ(expected_err_code, observer.net_error_code());

    // Both WebContentsObserver::{DidStartNavigation, DidFinishNavigation}
    // are called, but no WebContentsObserver::DidRedirectNavigation.
    std::vector<GURL> started_navigation = {redirecting_url};
    std::vector<GURL> redirected_navigation;  // Empty.
    std::vector<GURL> finished_navigation = {redirecting_url};
    EXPECT_EQ(started_navigation, logger.started_navigation_urls());
    EXPECT_EQ(redirected_navigation, logger.redirected_navigation_urls());
    EXPECT_EQ(finished_navigation, logger.finished_navigation_urls());
  }
}

// Check that iframe with embedded credentials are blocked.
// See https://crbug.com/755892.
// TODO(crbug.com/1262910): Enable the test again.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       DISABLED_BlockCredentialedSubresources) {
  const struct {
    GURL main_url;
    GURL iframe_url;
    bool blocked;
  } kTestCases[] = {
      // Normal case with no credential in neither of the urls.
      {GURL("http://a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://a.com/title1.html"), false},

      // Username in the iframe, but nothing in the main frame.
      {GURL("http://a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://user@a.com/title1.html"), true},

      // Username and password in the iframe, but none in the main frame.
      {GURL("http://a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://user:pass@a.com/title1.html"), true},

      // Username and password in the main frame, but none in the iframe.
      {GURL("http://user:pass@a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://a.com/title1.html"), false},

      // Same usernames in both frames.
      // Relative URLs on top-level pages that were loaded with embedded
      // credentials should load correctly.
      {GURL("http://user@a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://user@a.com/title1.html"), false},

      // Same usernames and passwords in both frames.
      // Relative URLs on top-level pages that were loaded with embedded
      // credentials should load correctly.
      {GURL("http://user:pass@a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://user:pass@a.com/title1.html"), false},

      // Different usernames.
      {GURL("http://user@a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://wrong@a.com/title1.html"), true},

      // Different passwords.
      {GURL("http://user:pass@a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://user:wrong@a.com/title1.html"), true},

      // Different usernames and same passwords.
      {GURL("http://user:pass@a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://wrong:pass@a.com/title1.html"), true},

      // Different origins.
      {GURL("http://user:pass@a.com/frame_tree/page_with_one_frame.html"),
       GURL("http://user:pass@b.com/title1.html"), true},
  };
  for (const auto& test_case : kTestCases) {
    // Modify the URLs port to use the embedded test server's port.
    std::string port_str(base::NumberToString(embedded_test_server()->port()));
    GURL::Replacements set_port;
    set_port.SetPortStr(port_str);
    GURL main_url(test_case.main_url.ReplaceComponents(set_port));
    GURL iframe_url_final(test_case.iframe_url.ReplaceComponents(set_port));
    GURL iframe_url_with_redirect = GURL(embedded_test_server()->GetURL(
        "/server-redirect?" + iframe_url_final.spec()));

    ASSERT_TRUE(NavigateToURL(shell(), main_url));

    // Blocking the request must work, even after a redirect.
    for (bool redirect : {false, true}) {
      const GURL& iframe_url =
          redirect ? iframe_url_with_redirect : iframe_url_final;
      SCOPED_TRACE(::testing::Message()
                   << std::endl
                   << "- main_url = " << main_url << std::endl
                   << "- iframe_url = " << iframe_url << std::endl);
      NavigationHandleObserver subframe_observer(shell()->web_contents(),
                                                 iframe_url);
      TestNavigationThrottleInstaller installer(
          shell()->web_contents(), NavigationThrottle::PROCEED,
          NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
          NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

      NavigateIframeToURL(shell()->web_contents(), "child0", iframe_url);

      FrameTreeNode* root =
          static_cast<WebContentsImpl*>(shell()->web_contents())
              ->GetPrimaryFrameTree()
              .root();
      ASSERT_EQ(1u, root->child_count());
      if (test_case.blocked) {
        EXPECT_EQ(redirect, !!installer.will_start_called());
        EXPECT_FALSE(installer.will_process_called());
        EXPECT_FALSE(subframe_observer.has_committed());
        EXPECT_TRUE(subframe_observer.last_committed_url().is_empty());
        EXPECT_NE(iframe_url_final, root->child_at(0u)->current_url());
      } else {
        EXPECT_TRUE(installer.will_start_called());
        EXPECT_TRUE(installer.will_process_called());
        EXPECT_TRUE(subframe_observer.has_committed());
        EXPECT_EQ(iframe_url_final, subframe_observer.last_committed_url());
        EXPECT_EQ(iframe_url_final, root->child_at(0u)->current_url());
      }
    }
  }
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, StartToCommitMetrics) {
  enum class FrameType {
    kMain,
    kSub,
  };
  enum class ProcessType {
    kCross,
    kSame,
  };
  enum class TransitionType {
    kNew,
    kReload,
    kBackForward,
  };

  // Uses the provided ProcessType, FrameType, and TransitionType expected for
  // this navigation to generate all combinations of Navigation.StartToCommit
  // metrics.
  auto check_navigation = [](const base::HistogramTester& histograms,
                             ProcessType process_type, FrameType frame_type,
                             TransitionType transition_type) {
    const std::map<FrameType, std::string> kFrameSuffixes = {
        {FrameType::kMain, ".MainFrame"}, {FrameType::kSub, ".Subframe"}};
    const std::map<ProcessType, std::string> kProcessSuffixes = {
        {ProcessType::kCross, ".CrossProcess"},
        {ProcessType::kSame, ".SameProcess"}};
    const std::map<TransitionType, std::string> kTransitionSuffixes = {
        {TransitionType::kNew, ".NewNavigation"},
        {TransitionType::kReload, ".Reload"},
        {TransitionType::kBackForward, ".BackForward"},
    };

    // Add the suffix to all existing histogram names, and append the results to
    // |names|.
    std::vector<std::string> names{"Navigation.StartToCommit"};
    auto add_suffix = [&names](std::vector<std::string> suffixes) {
      size_t original_size = names.size();
      for (size_t i = 0; i < original_size; i++) {
        for (const std::string& suffix : suffixes)
          names.push_back(names[i] + suffix);
      }
    };
    add_suffix({kProcessSuffixes.at(process_type)});
    add_suffix({kFrameSuffixes.at(frame_type)});
    add_suffix({kTransitionSuffixes.at(transition_type),
                ".ForegroundProcessPriority"});

    // Check that all generated histogram names are logged exactly once.
    for (const auto& name : names) {
      histograms.ExpectTotalCount(name, 1);
    }

    // Check that no additional histograms with the StartToCommit prefix were
    // logged.
    base::HistogramTester::CountsMap counts =
        histograms.GetTotalCountsForPrefix("Navigation.StartToCommit");
    int32_t total_counts = 0;
    for (const auto& it : counts) {
      total_counts += it.second;
    }
    EXPECT_EQ(static_cast<int32_t>(names.size()), total_counts);
  };

  // Main frame tests.
  IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
  EXPECT_TRUE(
      NavigateToURL(shell(), embedded_test_server()->GetURL("/hello.html")));
  {
    base::HistogramTester histograms;
    GURL url(embedded_test_server()->GetURL("/title1.html"));
    EXPECT_TRUE(NavigateToURL(shell(), url));
    check_navigation(histograms, ProcessType::kSame, FrameType::kMain,
                     TransitionType::kNew);
  }
  {
    base::HistogramTester histograms;
    GURL url(embedded_test_server()->GetURL("b.com", "/title1.html"));
    EXPECT_TRUE(NavigateToURL(shell(), url));
    check_navigation(histograms, ProcessType::kCross, FrameType::kMain,
                     TransitionType::kNew);
  }
  {
    base::HistogramTester histograms;
    ReloadBlockUntilNavigationsComplete(shell(), 1);
    check_navigation(histograms, ProcessType::kSame, FrameType::kMain,
                     TransitionType::kReload);
  }
  {
    base::HistogramTester histograms;
    TestNavigationObserver nav_observer(shell()->web_contents());
    shell()->GoBackOrForward(-1);
    nav_observer.Wait();
    check_navigation(histograms, ProcessType::kCross, FrameType::kMain,
                     TransitionType::kBackForward);
  }
  {
    base::HistogramTester histograms;
    TestNavigationObserver nav_observer(shell()->web_contents());
    shell()->GoBackOrForward(-1);
    nav_observer.Wait();
    check_navigation(histograms, ProcessType::kSame, FrameType::kMain,
                     TransitionType::kBackForward);
  }
  {
    base::HistogramTester histograms;
    int previous_process_id =
        shell()->web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
    EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
    bool process_changed =
        (previous_process_id !=
         shell()->web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID());
    check_navigation(histograms,
                     process_changed ? ProcessType::kCross : ProcessType::kSame,
                     FrameType::kMain, TransitionType::kNew);
  }

  // Subframe tests. All of these tests just navigate a frame within
  // page_with_iframe.html.
  EXPECT_TRUE(NavigateToURL(
      shell(), embedded_test_server()->GetURL("/page_with_iframe.html")));
  FrameTreeNode* first_child =
      static_cast<WebContentsImpl*>(shell()->web_contents())
          ->GetPrimaryFrameTree()
          .root()
          ->child_at(0);
  {
    base::HistogramTester histograms;
    EXPECT_TRUE(NavigateToURLFromRenderer(
        first_child, embedded_test_server()->GetURL("c.com", "/title1.html")));
    check_navigation(histograms, ProcessType::kCross, FrameType::kSub,
                     TransitionType::kNew);
  }
  {
    base::HistogramTester histograms;
    TestFrameNavigationObserver nav_observer(first_child);
    EXPECT_TRUE(ExecJs(first_child, "location.reload();"));
    nav_observer.Wait();
    // location.reload triggers the PAGE_TRANSITION_AUTO_SUBFRAME which
    // corresponds to NewNavigation.
    check_navigation(histograms, ProcessType::kSame, FrameType::kSub,
                     TransitionType::kNew);
  }
  {
    base::HistogramTester histograms;
    shell()->GoBackOrForward(-1);
    EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
    // History back triggers the PAGE_TRANSITION_AUTO_SUBFRAME which corresponds
    // to NewNavigation.
    check_navigation(histograms, ProcessType::kCross, FrameType::kSub,
                     TransitionType::kNew);
  }
  EXPECT_TRUE(NavigateToURLFromRenderer(
      first_child, embedded_test_server()->GetURL("/simple_links.html")));
  {
    base::HistogramTester histograms;
    TestFrameNavigationObserver nav_observer(first_child);
    EXPECT_TRUE(ExecJs(first_child, "clickSameSiteLink();"));
    nav_observer.Wait();
    // Link clicking will trigger PAGE_TRANSITION_MANUAL_SUBFRAME which
    // corresponds to NewNavigation.
    check_navigation(histograms, ProcessType::kSame, FrameType::kSub,
                     TransitionType::kNew);
  }
}

// Verify that the TimeToReadyToCommit2 metrics are correctly logged for
// SameProcess vs CrossProcess as well as MainFrame vs Subframe cases.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       TimeToReadyToCommitMetrics) {
  EXPECT_TRUE(
      NavigateToURL(shell(), embedded_test_server()->GetURL("/hello.html")));

  // Check that only SameProcess version is logged and not CrossProcess.
  {
    base::HistogramTester histograms;
    GURL url(embedded_test_server()->GetURL("/title1.html"));
    EXPECT_TRUE(NavigateToURL(shell(), url));

    base::HistogramTester::CountsMap expected_counts = {
        {"Navigation.TimeToReadyToCommit2.MainFrame", 1},
        {"Navigation.TimeToReadyToCommit2.MainFrame.NewNavigation", 1},
        {"Navigation.TimeToReadyToCommit2.NewNavigation", 1},
        {"Navigation.TimeToReadyToCommit2.SameProcess", 1},
        {"Navigation.TimeToReadyToCommit2.SameProcess.NewNavigation", 1}};
    EXPECT_THAT(
        histograms.GetTotalCountsForPrefix("Navigation.TimeToReadyToCommit2."),
        testing::ContainerEq(expected_counts));
  }

  // Navigate cross-process and ensure that only CrossProcess is logged.
  {
    base::HistogramTester histograms;
    GURL url(embedded_test_server()->GetURL("a.com", "/title2.html"));
    EXPECT_TRUE(NavigateToURL(shell(), url));

    base::HistogramTester::CountsMap expected_counts = {
        {"Navigation.TimeToReadyToCommit2.MainFrame", 1},
        {"Navigation.TimeToReadyToCommit2.MainFrame.NewNavigation", 1},
        {"Navigation.TimeToReadyToCommit2.NewNavigation", 1},
        {"Navigation.TimeToReadyToCommit2.CrossProcess", 1},
        {"Navigation.TimeToReadyToCommit2.CrossProcess.NewNavigation", 1}};
    EXPECT_THAT(
        histograms.GetTotalCountsForPrefix("Navigation.TimeToReadyToCommit2."),
        testing::ContainerEq(expected_counts));
  }

  // Add a new subframe.
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  EXPECT_TRUE(ExecJs(
      root, "document.body.appendChild(document.createElement('iframe'));"));

  // Navigate subframe cross-site and ensure Subframe metrics are logged.
  {
    base::HistogramTester histograms;
    GURL url(embedded_test_server()->GetURL("b.com", "/title3.html"));
    EXPECT_TRUE(NavigateToURLFromRenderer(root->child_at(0), url));

    std::string navigation_type =
        AreAllSitesIsolatedForTesting() ? "CrossProcess" : "SameProcess";
    base::HistogramTester::CountsMap expected_counts = {
        {"Navigation.TimeToReadyToCommit2.Subframe", 1},
        {"Navigation.TimeToReadyToCommit2.Subframe.NewNavigation", 1},
        {"Navigation.TimeToReadyToCommit2.NewNavigation", 1},
        {base::StringPrintf("Navigation.TimeToReadyToCommit2.%s",
                            navigation_type.c_str()),
         1},
        {base::StringPrintf("Navigation.TimeToReadyToCommit2.%s.NewNavigation",
                            navigation_type.c_str()),
         1}};
    EXPECT_THAT(
        histograms.GetTotalCountsForPrefix("Navigation.TimeToReadyToCommit2."),
        testing::ContainerEq(expected_counts));
  }
}

IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest, IsDownload) {
  GURL url(embedded_test_server()->GetURL("/download-test1.lib"));
  NavigationHandleObserver observer(shell()->web_contents(), url);
  EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(), url));
  EXPECT_FALSE(observer.has_committed());
  EXPECT_TRUE(observer.is_download());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest,
                       DownloadFalseForHtmlResponse) {
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  NavigationHandleObserver observer(shell()->web_contents(), url);
  EXPECT_TRUE(NavigateToURL(shell(), url));
  EXPECT_TRUE(observer.has_committed());
  EXPECT_FALSE(observer.is_download());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest,
                       DownloadFalseFor404) {
  GURL url(embedded_test_server()->GetURL("/page404.html"));
  NavigationHandleObserver observer(shell()->web_contents(), url);
  EXPECT_TRUE(NavigateToURL(shell(), url));
  EXPECT_TRUE(observer.has_committed());
  EXPECT_FALSE(observer.is_download());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest,
                       DownloadFalseForFailedNavigation) {
  GURL url(embedded_test_server()->GetURL("/download-test1.lib"));
  NavigationHandleObserver observer(shell()->web_contents(), url);
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::CANCEL,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

  EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(), url));
  EXPECT_FALSE(observer.has_committed());
  EXPECT_TRUE(observer.is_error());
  EXPECT_FALSE(observer.is_download());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest,
                       RedirectToDownload) {
  GURL redirect_url(
      embedded_test_server()->GetURL("/cross-site/bar.com/download-test1.lib"));
  NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
  EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(), redirect_url));
  EXPECT_FALSE(observer.has_committed());
  EXPECT_TRUE(observer.was_redirected());
  EXPECT_TRUE(observer.is_download());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest,
                       RedirectToDownloadFails) {
  GURL redirect_url(
      embedded_test_server()->GetURL("/cross-site/bar.com/download-test1.lib"));
  NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(), NavigationThrottle::PROCEED,
      NavigationThrottle::CANCEL, NavigationThrottle::PROCEED,
      NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);

  EXPECT_FALSE(NavigateToURL(shell(), redirect_url));

  EXPECT_FALSE(observer.has_committed());
  EXPECT_FALSE(observer.is_download());
  EXPECT_TRUE(observer.is_error());
  EXPECT_TRUE(observer.was_redirected());
}

// Set of tests that check the various NavigationThrottle events can be used
// with custom error pages.
class NavigationRequestThrottleResultWithErrorPageBrowserTest
    : public NavigationRequestBrowserTest,
      public ::testing::WithParamInterface<NavigationThrottle::ThrottleAction> {
};

IN_PROC_BROWSER_TEST_P(NavigationRequestThrottleResultWithErrorPageBrowserTest,
                       WillStartRequest) {
  NavigationThrottle::ThrottleAction action = GetParam();

  if (action == NavigationThrottle::CANCEL_AND_IGNORE) {
    // There is no support for CANCEL_AND_IGNORE and a custom error page.
    return;
  }

  if (action == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
    // This can only be returned from sub frame navigations.
    return;
  }

  if (action == NavigationThrottle::PROCEED ||
      action == NavigationThrottle::DEFER) {
    // Neither is relevant for what we want to test i.e. error pages.
    return;
  }

  if (action == NavigationThrottle::BLOCK_RESPONSE) {
    // BLOCK_RESPONSE can't be used with WillStartRequest.
    return;
  }

  GURL url(embedded_test_server()->GetURL("/title1.html"));
  InstallThrottleAndTestNavigationCommittedWithErrorPage(
      url, action, TestNavigationThrottleInstaller::WILL_START_REQUEST);
}

IN_PROC_BROWSER_TEST_P(NavigationRequestThrottleResultWithErrorPageBrowserTest,
                       WillRedirectRequest) {
  NavigationThrottle::ThrottleAction action = GetParam();

  if (action == NavigationThrottle::CANCEL_AND_IGNORE) {
    // There is no support for CANCEL_AND_IGNORE and a custom error page.
    return;
  }

  if (action == NavigationThrottle::PROCEED ||
      action == NavigationThrottle::DEFER) {
    // Neither is relevant for what we want to test i.e. error pages.
    return;
  }

  if (action == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
    // This can only be returned from sub frame navigations.
    return;
  }

  if (action == NavigationThrottle::BLOCK_RESPONSE) {
    // BLOCK_RESPONSE can't be used with WillRedirectRequest.
    return;
  }

  GURL url(embedded_test_server()->GetURL("/cross-site/foo.com/title1.html"));
  InstallThrottleAndTestNavigationCommittedWithErrorPage(
      url, action, TestNavigationThrottleInstaller::WILL_REDIRECT_REQUEST);
}

IN_PROC_BROWSER_TEST_P(NavigationRequestThrottleResultWithErrorPageBrowserTest,
                       WillFailRequest) {
  NavigationThrottle::ThrottleAction action = GetParam();

  if (action == NavigationThrottle::PROCEED ||
      action == NavigationThrottle::DEFER) {
    // Neither is relevant for what we want to test i.e. error pages.
    return;
  }

  if (action == NavigationThrottle::BLOCK_REQUEST ||
      action == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
    // BLOCK_REQUEST, BLOCK_REQUEST_AND_COLLAPSE, can't be used with
    // WillFailRequest.
    return;
  }

  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
  ASSERT_TRUE(https_server.Start());

  const GURL url = https_server.GetURL("/title1.html");
  InstallThrottleAndTestNavigationCommittedWithErrorPage(
      url, action, TestNavigationThrottleInstaller::WILL_FAIL_REQUEST);
}

IN_PROC_BROWSER_TEST_P(NavigationRequestThrottleResultWithErrorPageBrowserTest,
                       WillProcessResponse) {
  NavigationThrottle::ThrottleAction action = GetParam();

  if (action == NavigationThrottle::CANCEL_AND_IGNORE) {
    // There is no support for CANCEL_AND_IGNORE and a custom error page.
    return;
  }

  if (action == NavigationThrottle::PROCEED ||
      action == NavigationThrottle::DEFER) {
    // Neither is relevant for what we want to test i.e. error pages.
    return;
  }

  if (action == NavigationThrottle::BLOCK_REQUEST ||
      action == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
    // BLOCK_REQUEST and BLOCK_REQUEST_AND_COLLAPSE can't be used with
    // WillProcessResponse.
    return;
  }

  GURL url(embedded_test_server()->GetURL("/title1.html"));
  InstallThrottleAndTestNavigationCommittedWithErrorPage(
      url, action, TestNavigationThrottleInstaller::WILL_PROCESS_RESPONSE);
}

INSTANTIATE_TEST_SUITE_P(
    All,
    NavigationRequestThrottleResultWithErrorPageBrowserTest,
    testing::Range(NavigationThrottle::ThrottleAction::FIRST,
                   NavigationThrottle::ThrottleAction::LAST));

// The set of tests...
// * NavigationRequestDownloadBrowserTest.AllowedResourceDownloaded
// * NavigationRequestDownloadBrowserTest.AllowedResourceNotDownloaded
// * NavigationRequestDownloadBrowserTest.Disallowed
//
// ...covers every combination of possible states for:
// * CommonNavigationParams::download_policy (allow vs disallow)
// * NavigationHandle::IsDownload()
//
// Download policies that enumerate allowed / disallowed options are not tested
// here.
IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest,
                       AllowedResourceDownloaded) {
  GURL simple_url(embedded_test_server()->GetURL("/simple_page.html"));

  TestNavigationManager manager(shell()->web_contents(), simple_url);
  NavigationHandleObserver handle_observer(shell()->web_contents(), simple_url);

  // Download is allowed.
  shell()->LoadURL(simple_url);
  EXPECT_TRUE(manager.WaitForRequestStart());
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryMainFrame()
                            ->frame_tree_node();
  EXPECT_TRUE(root->navigation_request()
                  ->common_params()
                  .download_policy.IsDownloadAllowed());

  // The response is not handled as a download.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_FALSE(handle_observer.is_download());
}

// See NavigationRequestDownloadBrowserTest.AllowedResourceNotDownloaded
IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest,
                       AllowedResourceNotDownloaded) {
  GURL download_url(embedded_test_server()->GetURL("/download-test1.lib"));

  TestNavigationManager manager(shell()->web_contents(), download_url);
  NavigationHandleObserver handle_observer(shell()->web_contents(),
                                           download_url);

  // Download is allowed.
  shell()->LoadURL(download_url);
  EXPECT_TRUE(manager.WaitForRequestStart());
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryMainFrame()
                            ->frame_tree_node();
  EXPECT_TRUE(root->navigation_request()
                  ->common_params()
                  .download_policy.IsDownloadAllowed());

  // The response is handled as a download.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_TRUE(handle_observer.is_download());
}

// See NavigationRequestDownloadBrowserTest.AllowedResourceNotDownloaded
IN_PROC_BROWSER_TEST_F(NavigationRequestDownloadBrowserTest, Disallowed) {
  GURL download_url(embedded_test_server()->GetURL("/download-test1.lib"));

  // An URL is allowed to be a download iff it is not a view-source URL.
  GURL view_source_url =
      GURL(content::kViewSourceScheme + std::string(":") + download_url.spec());

  NavigationHandleObserver handle_observer(shell()->web_contents(),
                                           download_url);
  TestNavigationManager manager(shell()->web_contents(), download_url);

  // Download is not allowed.
  shell()->LoadURL(view_source_url);
  EXPECT_TRUE(manager.WaitForRequestStart());
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryMainFrame()
                            ->frame_tree_node();
  EXPECT_TRUE(
      root->navigation_request()->common_params().download_policy.IsType(
          blink::NavigationDownloadType::kViewSource));
  EXPECT_FALSE(root->navigation_request()
                   ->common_params()
                   .download_policy.IsDownloadAllowed());

  // The response is not handled as a download.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_FALSE(handle_observer.is_download());
}

class NavigationRequestBackForwardBrowserTest
    : public NavigationRequestBrowserTest,
      public WebContentsObserver {
 protected:
  void SetUpOnMainThread() override {
    NavigationRequestBrowserTest::SetUpOnMainThread();

    WebContentsObserver::Observe(shell()->web_contents());
  }

  void DidFinishNavigation(NavigationHandle* navigation_handle) override {
    if (navigation_handle->HasCommitted()) {
      offsets_.push_back(navigation_handle->GetNavigationEntryOffset());
    }
  }

  std::vector<int64_t> offsets_;
};

IN_PROC_BROWSER_TEST_F(NavigationRequestBackForwardBrowserTest,
                       NavigationEntryOffsets) {
  const GURL url1(embedded_test_server()->GetURL("/title1.html"));
  const GURL url2(embedded_test_server()->GetURL("/title2.html"));
  const GURL url3(embedded_test_server()->GetURL("/title3.html"));

  EXPECT_TRUE(NavigateToURL(shell(), url1));
  // The navigation entries are:
  // [*url1].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->Reload();
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [*url1].

  EXPECT_TRUE(NavigateToURL(shell(), url2));
  // The navigation entries are:
  // [url1, *url2].

  EXPECT_TRUE(NavigateToURL(shell(), url3));
  // The navigation entries are:
  // [url1, url2, *url3].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->GoBackOrForward(-1);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [url1, *url2, url3].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->GoBackOrForward(-1);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [*url1, url2, url3].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->GoBackOrForward(1);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [url1, *url2, url3].

  // Navigations 1, 3, 4 are regular navigations.
  // Navigation 2 is a reload.
  // Navigaations 5 and 6 are back navigations.
  // Navigation 7 is a forward navigation.
  EXPECT_THAT(offsets_, testing::ElementsAre(1, 0, 1, 1, -1, -1, 1));
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBackForwardBrowserTest,
                       NavigationEntryOffsetsForSubframes) {
  const GURL url1(embedded_test_server()->GetURL("/title1.html"));
  const GURL url1_fragment1(
      embedded_test_server()->GetURL("/title1.html#id_1"));
  const GURL url2(embedded_test_server()->GetURL(
      "b.com", "/frame_tree/page_with_one_frame.html"));
  const char kChildFrameId[] = "child0";

  EXPECT_TRUE(NavigateToURL(shell(), url1));
  // The navigation entries are:
  // [*url1].

  EXPECT_TRUE(NavigateToURL(shell(), url1_fragment1));
  // The navigation entries are:
  // [url1, *url1_fragment1].

  EXPECT_TRUE(NavigateToURL(shell(), url2));
  // The navigation entries are:
  // [url1, url1_fragment1, *url2(subframe)].

  EXPECT_TRUE(
      NavigateIframeToURL(shell()->web_contents(), kChildFrameId, url1));
  // The navigation entries are:
  // [url1, url1_fragment1, url2(subframe), *url2(url1)].

  EXPECT_TRUE(NavigateToURL(shell(), url1));
  // The navigation entries are:
  // [url1, url1_fragment1, url2(subframe), url2(url1), *url1].

  {
    // We are waiting for two navigations here: main frame and subframe.
    // However, when back/forward cache is enabled, back navigation to a page
    // with subframes will not trigger a subframe navigation (since the
    // subframe is cached with the page).
    TestNavigationObserver navigation_observer(
        shell()->web_contents(), IsBackForwardCacheEnabled() ? 1 : 2);
    shell()->GoBackOrForward(-1);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [url1, url1_fragment1, url2(subframe), *url2(url1), url1].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->GoBackOrForward(-1);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [url1, url1_fragment1, *url2(subframe), url2(url1), url1].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->GoBackOrForward(-1);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [url1, *url1_fragment1, url2(subframe), url2(url1), url1].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->GoBackOrForward(-1);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [*url1, url1_fragment1, url2(subframe), url2(url1), url1].

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    shell()->GoBackOrForward(4);
    navigation_observer.WaitForNavigationFinished();
  }
  // The navigation entries are:
  // [url1, url1_fragment1, url2(subframe), url2(url1), *url1].

  // New navigations have offset 1, back navigations have offset -1 and the last
  // navigations have offset 3 as requested.
  // Note that all subframe navigations have offset 1 regardless of whether they
  // result in a new entry being generated or not.
  if (IsBackForwardCacheEnabled()) {
    // When back/forward cache is enabled, back navigation to a page with
    // subframes will not trigger a subframe navigation (since the subframe is
    // cached with the page and won't need to be reconstructed/navigated).
    EXPECT_THAT(offsets_,
                testing::ElementsAre(1, 1, 1, 0, 1, 1, -1, -1, -1, -1, 4));
  } else {
    EXPECT_THAT(offsets_,
                testing::ElementsAre(1, 1, 1, 0, 1, 1, -1, 1, -1, -1, -1, 4));
  }
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBackForwardBrowserTest,
                       NavigationEntryLimit) {
  const GURL url1(embedded_test_server()->GetURL("/title1.html"));

  static_cast<NavigationControllerImpl*>(
      &shell()->web_contents()->GetController())
      ->set_max_entry_count_for_testing(3);

  for (int i = 0; i < 5; ++i) {
    EXPECT_TRUE(NavigateToURL(shell(), url1));
  }

  // Expect that the offsets are still 1 even when we hit the entry count limit.
  EXPECT_THAT(offsets_, testing::ElementsAre(1, 1, 1, 1, 1));
}

IN_PROC_BROWSER_TEST_F(NavigationRequestBackForwardBrowserTest,
                       LocationReplace) {
  const GURL url1(embedded_test_server()->GetURL("/title1.html"));

  EXPECT_TRUE(NavigateToURL(shell(), url1));
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();

  {
    TestNavigationObserver navigation_observer(shell()->web_contents());
    EXPECT_TRUE(ExecJs(root, "window.location.replace('#frag');"));
    navigation_observer.WaitForNavigationFinished();
  }

  // The second navigation replaces the current navigation entry and should have
  // offset of zero.
  EXPECT_THAT(offsets_, testing::ElementsAre(1, 0));
}

// Tests that the correct net::AuthChallengeInfo is exposed from the
// NavigationHandle when the page requests authentication.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest, AuthChallengeInfo) {
  GURL url(embedded_test_server()->GetURL("/auth-basic"));
  NavigationHandleObserver observer(shell()->web_contents(), url);
  EXPECT_TRUE(NavigateToURL(shell(), url));
  EXPECT_TRUE(observer.has_committed());
  ASSERT_TRUE(observer.auth_challenge_info().has_value());
  EXPECT_FALSE(observer.auth_challenge_info()->is_proxy);
  EXPECT_EQ(url::SchemeHostPort(url),
            observer.auth_challenge_info()->challenger);
  EXPECT_EQ("basic", observer.auth_challenge_info()->scheme);
  EXPECT_EQ("testrealm", observer.auth_challenge_info()->realm);
  EXPECT_EQ("Basic realm=\"testrealm\"",
            observer.auth_challenge_info()->challenge);
  EXPECT_EQ("/auth-basic", observer.auth_challenge_info()->path);
}

class TestMixedContentWebContentsDelegate : public WebContentsDelegate {
 public:
  TestMixedContentWebContentsDelegate() = default;
  TestMixedContentWebContentsDelegate(
      const TestMixedContentWebContentsDelegate&) = delete;
  TestMixedContentWebContentsDelegate& operator=(
      const TestMixedContentWebContentsDelegate&) = delete;

  bool passive_insecure_content_found() {
    return passive_insecure_content_found_;
  }

  // WebContentsDelegate:
  void PassiveInsecureContentFound(const GURL& resource_url) override {
    passive_insecure_content_found_ = true;
  }

 private:
  bool passive_insecure_content_found_ = false;
};

// Tests that an iframe with a non-webby scheme is not treated as mixed
// content. See https://crbug.com/621131.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       NonWebbyIframeIsNotMixedContent) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(https_server.Start());

  GURL url(https_server.GetURL("/title1.html"));
  ASSERT_TRUE(NavigateToURL(shell(), url));

  // Inject a test delegate to observe when mixed content is detected.
  WebContents* contents = shell()->web_contents();
  TestMixedContentWebContentsDelegate test_delegate;
  contents->SetDelegate(&test_delegate);

  // Insert an iframe and navigate it to a non-webby scheme. It shouldn't be
  // treated as mixed content.
  GURL non_webby_url("foo://bar");
  TestNavigationObserver observer(contents);
  ASSERT_NE(false,
            EvalJs(contents,
                   JsReplace("var iframe = document.createElement('iframe');"
                             "iframe.src = $1;"
                             "document.body.appendChild(iframe);",
                             non_webby_url)));
  observer.Wait();
  EXPECT_FALSE(test_delegate.passive_insecure_content_found());
}

// Tests that a NavigationRequest's RFH can be retrieved during a synchronous
// renderer commit same-document navigation (regardless of whether the
// navigation commits or not).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       GetRFHDuringSyncRendererCommitSameDocumentNavigation) {
  const GURL url(embedded_test_server()->GetURL("/title1.html"));
  const GURL same_doc_url(embedded_test_server()->GetURL("/title1.html#foo"));

  EXPECT_TRUE(NavigateToURL(shell(), url));
  WebContents* web_contents = shell()->web_contents();

  // Test sync-renderer-commit same-document navigation that commits.
  {
    TestNavigationManager navigation_manager(web_contents, same_doc_url);
    testing::NiceMock<MockWebContentsObserver> observer(web_contents);
    EXPECT_CALL(observer, DidFinishNavigation(testing::_))
        .WillOnce(testing::Invoke([](NavigationHandle* navigation_handle) {
          NavigationRequest* request =
              NavigationRequest::From(navigation_handle);
          EXPECT_TRUE(request->is_synchronous_renderer_commit());
          EXPECT_TRUE(navigation_handle->GetRenderFrameHost());
        }));
    EXPECT_TRUE(ExecJs(web_contents, "location.href = '#foo';"));
    ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
  }

  EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
  WebContents* popup = nullptr;
  {
    WebContentsAddedObserver popup_observer;
    ASSERT_TRUE(
        ExecJs(web_contents,
               JsReplace("var w = window.open($1, 'my-popup')", GURL())));
    popup = popup_observer.GetWebContents();
  }
  // Test sync-renderer-commit same-document navigation that doesn't commit.
  {
    testing::NiceMock<MockWebContentsObserver> observer(popup);
    EXPECT_CALL(observer, DidFinishNavigation(testing::_))
        .WillOnce(testing::Invoke([](NavigationHandle* navigation_handle) {
          NavigationRequest* request =
              NavigationRequest::From(navigation_handle);
          EXPECT_TRUE(request->is_synchronous_renderer_commit());
          EXPECT_TRUE(navigation_handle->GetRenderFrameHost());
        }));
    TestNavigationManager navigation_manager(popup, GURL("about:blank#foo"));
    EXPECT_TRUE(
        ExecJs(web_contents, "w.history.replaceState({}, '', '#foo');"));
    ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
  }
}

// Tests that a NavigationRequest's RFH can be retrieved during a synchronous
// renderer commit initial-about-blank navigation (regardless of whether the
// navigation commits or not).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       GetRFHDuringInitialAboutBlankNavigation) {
  EXPECT_TRUE(
      NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
  WebContentsImpl* web_contents =
      static_cast<WebContentsImpl*>(shell()->web_contents());

  // Test initial-about-blank navigation that commits.
  {
    testing::NiceMock<MockWebContentsObserver> observer(web_contents);
    EXPECT_CALL(observer, DidFinishNavigation(testing::_))
        .WillOnce(testing::Invoke([](NavigationHandle* navigation_handle) {
          NavigationRequest* request =
              NavigationRequest::From(navigation_handle);
          EXPECT_TRUE(request->is_synchronous_renderer_commit());
          EXPECT_TRUE(navigation_handle->GetRenderFrameHost());
        }));
    CreateSubframe(web_contents, "subframe", GURL(),
                   /*wait_for_navigation*/ true);
  }

  WebContentsImpl* popup = nullptr;
  {
    WebContentsAddedObserver popup_observer;
    ASSERT_TRUE(
        ExecJs(web_contents,
               JsReplace("var w = window.open($1, 'my-popup')", GURL())));
    popup = static_cast<WebContentsImpl*>(popup_observer.GetWebContents());
  }
  // Test initial-about-blank navigation that doesn't commit.
  {
    testing::NiceMock<MockWebContentsObserver> observer(popup);
    EXPECT_CALL(observer, DidFinishNavigation(testing::_))
        .WillOnce(testing::Invoke([](NavigationHandle* navigation_handle) {
          NavigationRequest* request =
              NavigationRequest::From(navigation_handle);
          EXPECT_TRUE(request->is_synchronous_renderer_commit());
          EXPECT_TRUE(navigation_handle->GetRenderFrameHost());
        }));
    CreateSubframe(popup, "popup_subframe", GURL(),
                   /*wait_for_navigation*/ true);
  }
}

// Verify that when navigating to a site that doesn't require a dedicated
// process from a initial siteless SiteInstance, the SiteInstance sets its site
// at ready-to-commit time (rather than at DidCommitNavigation time).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       SiteIsSetAtResponseTimeWithoutSiteIsolation) {
  // A custom ContentBrowserClient to turn off strict site isolation.
  class NoSiteIsolationContentBrowserClient
      : public ContentBrowserTestContentBrowserClient {
   public:
    bool ShouldEnableStrictSiteIsolation() override { return false; }
  } no_site_isolation_client;

  // The test should start in a blank shell with a siteless SiteInstance.
  EXPECT_FALSE(
      static_cast<SiteInstanceImpl*>(shell()->web_contents()->GetSiteInstance())
          ->HasSite());

  // Start a navigation and wait for response.  Note that this won't require a
  // dedicated process due to the custom ContentBrowserClient.
  GURL main_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
  TestNavigationManager manager(shell()->web_contents(), main_url);
  shell()->web_contents()->GetController().LoadURL(
      main_url, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
  EXPECT_TRUE(manager.WaitForResponse());

  // At this point, the navigation should be processing the response but not
  // committed yet. It should have already determined the final
  // RenderFrameHost, which should just be the initial RenderFrameHost.
  NavigationRequest* request =
      static_cast<NavigationRequest*>(manager.GetNavigationHandle());
  EXPECT_EQ(request->state(), NavigationRequest::WILL_PROCESS_RESPONSE);
  EXPECT_EQ(shell()->web_contents()->GetPrimaryMainFrame(),
            request->GetRenderFrameHost());

  // The navigation will stay in the initial SiteInstance, and that
  // SiteInstance's site should now be set.
  EXPECT_TRUE(
      static_cast<SiteInstanceImpl*>(shell()->web_contents()->GetSiteInstance())
          ->HasSite());

  // The process should also be considered used at this point.
  EXPECT_FALSE(
      shell()->web_contents()->GetPrimaryMainFrame()->GetProcess()->IsUnused());

  // Ensure the navigation finishes before we restore the ContentBrowserClient
  // which would turn strict site isolation back on.  Otherwise, the navigation
  // commit may fail citadel protection checks at test teardown.
  EXPECT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_TRUE(manager.was_successful());
}

// Check that a subframe can load an error page with an about:srcdoc URL, and
// that the origin does not inherit the parent's origin (i.e., behaves like all
// error pages) in this case.  In practice, this path may be taken by the heavy
// ads intervention (for an example, see the
// HeavyAdInterventionEnabled_ErrorPageLoaded test).
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       OriginForSrcdocErrorPageInSubframe) {
  // Start on a page with a blank subframe.
  GURL start_url =
      embedded_test_server()->GetURL("a.test", "/page_with_blank_iframe.html");
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  // Do a srcdoc navigation in the subframe.
  EXPECT_TRUE(
      ExecJs(shell(), "document.querySelector('iframe').srcdoc='foo';"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  RenderFrameHostImpl* subframe_rfh = root->child_at(0)->current_frame_host();
  EXPECT_EQ(GURL("about:srcdoc"), subframe_rfh->GetLastCommittedURL());

  // Navigate the subframe to a post-commit error page, reusing its current
  // srcdoc URL.  A post-commit error page provides a way to reach an error
  // page for a srcdoc subframe; note that it isn't possible to use
  // NavigationThrottles to block srcdoc navigations, since throttles don't
  // currently run in that case.
  TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
  shell()->web_contents()->GetController().LoadPostCommitErrorPage(
      subframe_rfh, subframe_rfh->GetLastCommittedURL(), "error_page_contents");
  navigation_observer.Wait();
  EXPECT_FALSE(navigation_observer.last_navigation_succeeded());

  // Verify that the origin of the srcdoc frame's parent wasn't inherited and
  // also wasn't used for the precursor.  The error page's origin should be
  // opaque without a valid precursor.
  url::Origin origin =
      root->child_at(0)->current_frame_host()->GetLastCommittedOrigin();
  EXPECT_TRUE(origin.opaque());
  EXPECT_FALSE(origin.GetTupleOrPrecursorTupleIfOpaque().IsValid());
}

// Verify that when navigation 1, which starts in an initial siteless
// SiteInstance and results in an error page, races with navigation 2, which
// requires a dedicated process and wants to reuse an existing process,
// navigation 2 does not incorrectly reuse navigation 1's process.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       ErrorPageMarksProcessAsUsed) {
  // The scenario in this test originally led to a site isolation bypass only
  // when error page isolation for main frames is turned off.  Do this via a
  // custom ContentBrowserClient.
  class NoErrorPageIsolationContentBrowserClient
      : public ContentBrowserTestContentBrowserClient {
   public:
    bool ShouldIsolateErrorPage(bool in_main_frame) override { return false; }
  } no_error_isolation_client;

  // Set the process limit to 1.  This will force main frame navigations to
  // attempt to reuse existing processes.
  RenderProcessHost::SetMaxRendererProcessCount(1);

  // The test should start in a blank shell with a siteless SiteInstance.
  EXPECT_FALSE(
      static_cast<SiteInstanceImpl*>(shell()->web_contents()->GetSiteInstance())
          ->HasSite());

  // Set up a foo.com URL which will fail to load.
  GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  std::unique_ptr<URLLoaderInterceptor> interceptor =
      URLLoaderInterceptor::SetupRequestFailForURL(foo_url,
                                                   net::ERR_CONNECTION_REFUSED);

  // Set up a throttle that will be used to wait for WillFailRequest() and then
  // defer the navigation.
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(),
      NavigationThrottle::PROCEED /* will_start_result */,
      NavigationThrottle::PROCEED /* will_redirect_result */,
      NavigationThrottle::DEFER /* will_fail_result */,
      NavigationThrottle::PROCEED /* will_process_result */,
      NavigationThrottle::PROCEED /* will_commit_without_url_loader_result */);

  // Start a navigation to foo.com that will result in an error.
  shell()->web_contents()->GetController().LoadURL(
      foo_url, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());

  // Wait for WillFailRequest(). After this point, we will have picked the
  // final RenderFrameHost for the error page.
  installer.WaitForThrottleWillFail();

  // Create a new tab and navigate it to a different site.  Ensure this site
  // requires a dedicated process, even on Android.
  GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  policy->AddFutureIsolatedOrigins(
      {url::Origin::Create(bar_url)},
      ChildProcessSecurityPolicy::IsolatedOriginSource::TEST);
  Shell* new_shell = CreateBrowser();
  EXPECT_TRUE(NavigateToURL(new_shell, bar_url));

  // Resume the error page navigation.  It should be able to finish without
  // crashing.
  installer.navigation_throttle()->ResumeNavigation();
  EXPECT_FALSE(WaitForLoadStop(shell()->web_contents()));
  EXPECT_TRUE(
      shell()->web_contents()->GetPrimaryMainFrame()->IsErrorDocument());

  // Ensure that bar.com didn't reuse the foo.com error page process.
  EXPECT_NE(shell()->web_contents()->GetPrimaryMainFrame()->GetProcess(),
            new_shell->web_contents()->GetPrimaryMainFrame()->GetProcess());
}

// Check that a renderer-initiated navigation from an error page to about:blank
// honors the initiator origin when selecting the SiteInstance and process for
// about:blank.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       NavigateToAboutBlankFromErrorPage) {
  GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
  std::unique_ptr<URLLoaderInterceptor> url_interceptor =
      URLLoaderInterceptor::SetupRequestFailForURL(url, net::ERR_DNS_TIMED_OUT);

  // Start off with navigation to a.com, which results in an error page.
  WebContents* web_contents = shell()->web_contents();
  {
    TestNavigationObserver observer(web_contents);
    ASSERT_FALSE(NavigateToURL(shell(), url));
    EXPECT_FALSE(observer.last_navigation_succeeded());
    if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
      EXPECT_EQ(
          GURL(kUnreachableWebDataURL),
          web_contents->GetPrimaryMainFrame()->GetSiteInstance()->GetSiteURL());
    }
  }

  // Now, do a renderer-initiated navigation to about:blank out of the error
  // page. We don't expect error pages to normally do this, but this might
  // still be possible via DevTools or automation.
  GURL about_blank(url::kAboutBlankURL);
  {
    TestNavigationObserver observer(web_contents);
    EXPECT_TRUE(ExecJs(web_contents, "location = 'about:blank';"));
    observer.Wait();
    EXPECT_TRUE(observer.last_navigation_succeeded());
    EXPECT_EQ(about_blank, observer.last_navigation_url());
  }
  RenderFrameHostImpl* rfh =
      static_cast<RenderFrameHostImpl*>(web_contents->GetPrimaryMainFrame());
  EXPECT_NE(GURL(kUnreachableWebDataURL), rfh->GetSiteInstance()->GetSiteURL());

  // Note that the error page's origin was opaque with a.com as the precursor.
  // This becomes the initiator origin for the about:blank navigation, and it
  // should end up as the final origin for the blank document.  See
  // https://crbug.com/585649.
  EXPECT_TRUE(rfh->GetLastCommittedOrigin().opaque());
  EXPECT_EQ(
      "a.com",
      rfh->GetLastCommittedOrigin().GetTupleOrPrecursorTupleIfOpaque().host());

  // Because about:blank's origin is opaque with a.com as the precursor, its
  // SiteInstance and process should also correspond to a.com, rather than be
  // left unassigned/unused.
  //
  // This covers an interesting and rare corner case, where an about:blank
  // navigation can't use the source SiteInstance, which would normally keep it
  // in the initiator's process and SiteInstance.  This is because the
  // navigation originates from an error page process, which is incompatible
  // with a non-error navigation to about:blank.  In this case, a new
  // SiteInstance and process will be created, and they should still reflect
  // about:blank's committed origin, rather than end up in an unlocked process
  // and an unassigned SiteInstance. See https://crbug.com/1426928.
  EXPECT_FALSE(rfh->GetProcess()->IsUnused());
  if (AreAllSitesIsolatedForTesting()) {
    EXPECT_EQ("http://a.com/", rfh->GetSiteInstance()->GetSiteURL());
    EXPECT_TRUE(rfh->GetProcess()->GetProcessLock().is_locked_to_site());
    EXPECT_EQ("http://a.com/", rfh->GetProcess()->GetProcessLock().site_url());
  } else {
    EXPECT_TRUE(rfh->GetProcess()->GetProcessLock().allows_any_site());
  }
}

using CSPEmbeddedEnforcementBrowserTest = NavigationRequestBrowserTest;

IN_PROC_BROWSER_TEST_F(CSPEmbeddedEnforcementBrowserTest,
                       CheckCSPEmbeddedEnforcement) {
  // We need one initial navigation to set up everything.
  EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL(
                                         "www.example.org", "/empty.html")));

  struct TestCase {
    const char* name;
    const char* required_csp;
    const char* frame_url;
    const char* allow_csp_from;
    const char* returned_csp;
    bool expect_allow;
  } cases[] = {
      {
          "No required csp",
          "",
          "www.not-example.org",
          nullptr,
          nullptr,
          true,
      },
      {
          "Required csp - Same origin",
          "script-src 'none'",
          "www.example.org",
          nullptr,
          nullptr,
          true,
      },
      {
          "Required csp - Cross origin",
          "script-src 'none'",
          "www.not-example.org",
          nullptr,
          nullptr,
          false,
      },
      {
          "Required csp - Cross origin with Allow-CSP-From",
          "script-src 'none'",
          "www.not-example.org",
          "*",
          nullptr,
          true,
      },
      {
          "Required csp - Cross origin with wrong Allow-CSP-From",
          "script-src 'none'",
          "www.not-example.org",
          "www.another-example.org",
          nullptr,
          false,
      },
      {
          "Required csp - Cross origin with non-subsuming CSPs",
          "script-src 'none'",
          "www.not-example.org",
          nullptr,
          "style-src 'none'",
          false,
      },
      {
          "Required csp - Cross origin with subsuming CSPs",
          "script-src 'none'",
          "www.not-example.org",
          nullptr,
          "script-src 'none'",
          true,
      },
      {
          "Required csp - Cross origin with wrong Allow-CSP-From but subsuming "
          "CSPs",
          "script-src 'none'",
          "www.not-example.org",
          "www.another-example.org",
          "script-src 'none'",
          true,
      },
  };

  for (auto test : cases) {
    SCOPED_TRACE(test.name);

    std::string headers;
    if (test.returned_csp) {
      headers +=
          base::StringPrintf("Content-Security-Policy: %s&", test.returned_csp);
    }
    if (test.allow_csp_from) {
      headers += base::StringPrintf("Allow-CSP-From: %s&", test.allow_csp_from);
    }

    GURL frame_url = embedded_test_server()->GetURL(test.frame_url,
                                                    "/set-header?" + headers);
    content::TestNavigationManager observer(shell()->web_contents(), frame_url);

    EXPECT_TRUE(ExecJs(shell()->web_contents(),
                       JsReplace(R"(
      const iframe = document.createElement("iframe");
      iframe.src = $2;
      if ($1)
        iframe.csp = $1;
      document.body.appendChild(iframe);
    )",
                                 test.required_csp, frame_url)));

    ASSERT_TRUE(observer.WaitForNavigationFinished());
    EXPECT_EQ(test.expect_allow, observer.was_successful());
  }
}

class NavigationRequestFencedFrameBrowserTest
    : public NavigationRequestBrowserTest {
 public:
  NavigationRequestFencedFrameBrowserTest() = default;
  ~NavigationRequestFencedFrameBrowserTest() override = default;
  NavigationRequestFencedFrameBrowserTest(
      const NavigationRequestFencedFrameBrowserTest&) = delete;

  NavigationRequestFencedFrameBrowserTest& operator=(
      const NavigationRequestFencedFrameBrowserTest&) = delete;

  void SetUpOnMainThread() override {
    https_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
    https_server()->ServeFilesFromSourceDirectory(GetTestDataFilePath());
    net::test_server::RegisterDefaultHandlers(https_server());
    ASSERT_TRUE(https_server()->Start());
    NavigationRequestBrowserTest::SetUpOnMainThread();
  }

  content::test::FencedFrameTestHelper& fenced_frame_test_helper() {
    return fenced_frame_helper_;
  }

  net::EmbeddedTestServer* https_server() { return &https_server_; }

 private:
  content::test::FencedFrameTestHelper fenced_frame_helper_;
  net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
};

IN_PROC_BROWSER_TEST_F(
    NavigationRequestFencedFrameBrowserTest,
    ShouldRespectOutermostFrameCOEPParentAndChildOnInsecureContent) {
  // Navigate |untrustworthy_url| to test if a fenced frame sets the outermost
  // main frame's COEP.
  GURL untrustworthy_url =
      embedded_test_server()->GetURL("a.test", "/title1.html");
  EXPECT_TRUE(NavigateToURL(shell(), untrustworthy_url));

  // Create a fenced frame on an insecure content and its document should have
  // the COEP of the outermost main frame.
  GURL fenced_frame_url = embedded_test_server()->GetURL(
      "a.test",
      "/set-header?"
      "Supports-Loading-Mode: fenced-frame&"
      "Cross-Origin-Embedder-Policy: require-corp");
  content::RenderFrameHostImpl* fenced_frame_host =
      static_cast<content::RenderFrameHostImpl*>(
          fenced_frame_test_helper().CreateFencedFrame(
              shell()->web_contents()->GetPrimaryMainFrame(),
              fenced_frame_url));
  ASSERT_TRUE(fenced_frame_host);
  EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone,
            fenced_frame_host->cross_origin_embedder_policy().value);
}

IN_PROC_BROWSER_TEST_F(
    NavigationRequestFencedFrameBrowserTest,
    RespectOutermostFrameCOEPParentOnInsecureContentAndChildOnSecureContent) {
  // Navigate |untrustworthy_url| to test if a fenced frame sets the outermost
  // main frame's COEP.
  GURL untrustworthy_url =
      embedded_test_server()->GetURL("a.test", "/title1.html");
  EXPECT_TRUE(NavigateToURL(shell(), untrustworthy_url));

  // Create a fenced frame on a secure content and its document should have the
  // COEP of the outermost main frame.
  GURL fenced_frame_url =
      https_server()->GetURL("a.test",
                             "/set-header?"
                             "Supports-Loading-Mode: fenced-frame&"
                             "Cross-Origin-Embedder-Policy: require-corp");
  content::RenderFrameHostImpl* fenced_frame_host =
      static_cast<content::RenderFrameHostImpl*>(
          fenced_frame_test_helper().CreateFencedFrame(
              shell()->web_contents()->GetPrimaryMainFrame(),
              fenced_frame_url));
  ASSERT_TRUE(fenced_frame_host);
  EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone,
            fenced_frame_host->cross_origin_embedder_policy().value);
}

// Ensure that fenced frames don't enable the view source mode since navigations
// in fenced frames to view-sources URLs are blocked.
IN_PROC_BROWSER_TEST_F(NavigationRequestFencedFrameBrowserTest,
                       ViewSourceNavigation_FencedFrame) {
  EXPECT_TRUE(
      NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));

  GURL fenced_frame_url =
      embedded_test_server()->GetURL("/fenced_frames/title1.html");
  RenderFrameHost* fenced_frame_host =
      fenced_frame_test_helper().CreateFencedFrame(
          shell()->web_contents()->GetPrimaryMainFrame(), fenced_frame_url);
  EXPECT_NE(nullptr, fenced_frame_host);

  GURL view_source_url(kViewSourceScheme + std::string(":") +
                       fenced_frame_url.spec());
  WebContentsConsoleObserver console_observer(shell()->web_contents());
  console_observer.SetPattern("Not allowed to load local resource: " +
                              view_source_url.spec());

  // Attempt to navigate to a view source url in the fenced frame.
  EXPECT_EQ(view_source_url.spec(),
            EvalJs(fenced_frame_host,
                   JsReplace(R"({location.href = $1;})", view_source_url)));
  ASSERT_TRUE(console_observer.Wait());

  // Original page shouldn't navigate away.
  EXPECT_EQ(fenced_frame_url, fenced_frame_host->GetLastCommittedURL());
  EXPECT_FALSE(shell()
                   ->web_contents()
                   ->GetController()
                   .GetLastCommittedEntry()
                   ->IsViewSourceMode());
}

class NavigationRequestPrerenderBrowserTest
    : public NavigationRequestBrowserTest {
 public:
  NavigationRequestPrerenderBrowserTest() {
    prerender_helper_ =
        std::make_unique<test::PrerenderTestHelper>(base::BindRepeating(
            &NavigationRequestPrerenderBrowserTest::web_contents,
            base::Unretained(this)));
  }
  ~NavigationRequestPrerenderBrowserTest() override = default;

  NavigationRequestPrerenderBrowserTest(
      const NavigationRequestPrerenderBrowserTest&) = delete;
  NavigationRequestPrerenderBrowserTest& operator=(
      const NavigationRequestPrerenderBrowserTest&) = delete;

  void SetUpOnMainThread() override {
    NavigationRequestBrowserTest::SetUpOnMainThread();

    https_server_ = std::make_unique<net::EmbeddedTestServer>(
        net::EmbeddedTestServer::TYPE_HTTPS);
    https_server_->AddDefaultHandlers(GetTestDataFilePath());
    https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);

    ASSERT_TRUE(https_server()->Start());
  }

 protected:
  net::EmbeddedTestServer* https_server() { return https_server_.get(); }

  test::PrerenderTestHelper& prerender_helper() { return *prerender_helper_; }

  WebContents* web_contents() { return shell()->web_contents(); }

 private:
  std::unique_ptr<net::EmbeddedTestServer> https_server_;
  std::unique_ptr<test::PrerenderTestHelper> prerender_helper_;
};

IN_PROC_BROWSER_TEST_F(NavigationRequestPrerenderBrowserTest,
                       CoopCoepCheckWithPrerender) {
  GURL url(
      https_server()->GetURL("a.test",
                             "/set-header"
                             "?cross-origin-opener-policy: same-origin"
                             "&cross-origin-embedder-policy: require-corp"));

  // Navigate to a document that sets COOP and COEP.
  EXPECT_TRUE(NavigateToURL(shell(), url));
  content::RenderFrameHostImpl* primary_main_frame =
      static_cast<content::RenderFrameHostImpl*>(
          shell()->web_contents()->GetPrimaryMainFrame());

  EXPECT_EQ(network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep,
            primary_main_frame->cross_origin_opener_policy().value);
  EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp,
            primary_main_frame->cross_origin_embedder_policy().value);

  // Add a prerender.
  int host_id = prerender_helper().AddPrerender(
      https_server()->GetURL("a.test", "/title1.html?prerendering"));
  content::RenderFrameHostImpl* prerender_main_frame =
      static_cast<content::RenderFrameHostImpl*>(
          prerender_helper().GetPrerenderedMainFrameHost(host_id));

  // The prerender rfh's polices are none.
  EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone,
            prerender_main_frame->cross_origin_embedder_policy().value);
  EXPECT_EQ(network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone,
            prerender_main_frame->cross_origin_opener_policy().value);

  // Prerendering should not affect the primary rfh's polices.
  EXPECT_EQ(network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep,
            primary_main_frame->cross_origin_opener_policy().value);
  EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp,
            primary_main_frame->cross_origin_embedder_policy().value);
}

enum class TestMPArchType {
  kPrerender,
  kFencedFrame,
  kPortal,
};

class NavigationRequestMPArchBrowserTest
    : public NavigationRequestBrowserTest,
      public testing::WithParamInterface<TestMPArchType> {
 public:
  NavigationRequestMPArchBrowserTest() {
    switch (GetParam()) {
      case TestMPArchType::kPrerender:
        prerender_helper_ =
            std::make_unique<test::PrerenderTestHelper>(base::BindRepeating(
                &NavigationRequestMPArchBrowserTest::web_contents,
                base::Unretained(this)));
        break;

      case TestMPArchType::kFencedFrame:
        fenced_frame_helper_ =
            std::make_unique<content::test::FencedFrameTestHelper>();
        break;

      case TestMPArchType::kPortal:
        scoped_feature_list_.InitWithFeatures(
            /*enabled_features=*/{blink::features::kPortals,
                                  blink::features::kPortalsCrossOrigin},
            /*disabled_features=*/{});
        break;
    }
  }
  ~NavigationRequestMPArchBrowserTest() override = default;
  NavigationRequestMPArchBrowserTest(
      const NavigationRequestMPArchBrowserTest&) = delete;

  NavigationRequestMPArchBrowserTest& operator=(
      const NavigationRequestMPArchBrowserTest&) = delete;

 protected:
  test::PrerenderTestHelper& prerender_helper() { return *prerender_helper_; }

  test::FencedFrameTestHelper& fenced_frame_test_helper() {
    return *fenced_frame_helper_;
  }

  WebContents* web_contents() { return shell()->web_contents(); }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
  std::unique_ptr<test::PrerenderTestHelper> prerender_helper_;
  std::unique_ptr<test::FencedFrameTestHelper> fenced_frame_helper_;
};

INSTANTIATE_TEST_SUITE_P(All,
                         NavigationRequestMPArchBrowserTest,
                         ::testing::Values(TestMPArchType::kPrerender,
                                           TestMPArchType::kFencedFrame,
                                           TestMPArchType::kPortal));

IN_PROC_BROWSER_TEST_P(NavigationRequestMPArchBrowserTest,
                       ShouldNotUpdateHistory) {
  const auto get_observer = [&](WebContents* web_contents) {
    return DidFinishNavigationObserver(
        web_contents,
        base::BindLambdaForTesting([](NavigationHandle* navigation_handle) {
          DCHECK_EQ(navigation_handle->GetNavigatingFrameType(),
                    GetParam() == TestMPArchType::kPrerender
                        ? FrameType::kPrerenderMainFrame
                        : GetParam() == TestMPArchType::kFencedFrame
                              ? FrameType::kFencedFrameRoot
                              : FrameType::kPrimaryMainFrame);
          EXPECT_FALSE(navigation_handle->ShouldUpdateHistory());
        }));
  };

  {
    DidFinishNavigationObserver observer(
        web_contents(),
        base::BindLambdaForTesting([](NavigationHandle* navigation_handle) {
          DCHECK_EQ(navigation_handle->GetNavigatingFrameType(),
                    FrameType::kPrimaryMainFrame);
          EXPECT_TRUE(navigation_handle->ShouldUpdateHistory());
        }));

    // Navigate the primary page.
    EXPECT_TRUE(
        NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
  }
  {
    switch (GetParam()) {
      case TestMPArchType::kPrerender: {
        const auto prerender_observer = get_observer(web_contents());
        // Load a page in the prerender.
        prerender_helper().AddPrerender(
            embedded_test_server()->GetURL("/title1.html?prendering"));
        break;
      }

      case TestMPArchType::kFencedFrame: {
        const auto fenced_frame_observer = get_observer(web_contents());
        // Create a fenced frame.
        ASSERT_TRUE(fenced_frame_test_helper().CreateFencedFrame(
            web_contents()->GetPrimaryMainFrame(),
            embedded_test_server()->GetURL("/fenced_frames/title1.html")));
        break;
      }

      case TestMPArchType::kPortal: {
        GURL portal_url(embedded_test_server()->GetURL("/title1.html"));

        // Create a portal.
        const char script[] = R"(
           new Promise(async resolve => {
             let portal = document.createElement('portal');
             portal.src = $1;
             portal.onload = resolve;
             document.body.appendChild(portal);
           });
        )";
        ASSERT_TRUE(ExecJs(web_contents()->GetPrimaryMainFrame(),
                           content::JsReplace(script, portal_url)));
        break;
      }
    }
  }
}

// Tests that when trying to commit an error page for a failed navigation, but
// the renderer process of the error page crashed, the navigation won't commit
// and the browser won't crash.
// Regression test for https://crbug.com/1444360.
IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
                       RendererCrashedBeforeCommitErrorPage) {
  // Navigate to `url_a` first.
  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
  ASSERT_TRUE(NavigateToURL(shell(), url_a));

  // Set up an URLLoaderInterceptor which will cause future navigations to fail.
  auto url_loader_interceptor = std::make_unique<URLLoaderInterceptor>(
      base::BindRepeating([](URLLoaderInterceptor::RequestParams* params) {
        network::URLLoaderCompletionStatus status;
        status.error_code = net::ERR_NOT_IMPLEMENTED;
        params->client->OnComplete(status);
        return true;
      }));

  // Do a navigation to `url_b1` that will fail and commit an error page. This
  // is important so that the next error page navigation won't need to create a
  // speculative RenderFrameHost (unless RenderDocument is enabled) and won't
  // get cancelled earlier than commit time due to speculative RFH deletion.
  GURL url_b1(embedded_test_server()->GetURL("b.com", "/title1.html"));
  EXPECT_FALSE(NavigateToURL(shell(), url_b1));
  EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), url_b1);
  EXPECT_TRUE(
      shell()->web_contents()->GetPrimaryMainFrame()->IsErrorDocument());

  // For the next navigation, set up a throttle that will be used to wait for
  // WillFailRequest() and then defer the navigation, so that we can crash the
  // error page process first.
  TestNavigationThrottleInstaller installer(
      shell()->web_contents(),
      NavigationThrottle::PROCEED /* will_start_result */,
      NavigationThrottle::PROCEED /* will_redirect_result */,
      NavigationThrottle::DEFER /* will_fail_result */,
      NavigationThrottle::PROCEED /* will_process_result */,
      NavigationThrottle::PROCEED /* will_commit_without_url_loader_result */);

  // Start a navigation to `url_b2` that will also fail, but before it commits
  // an error page, cause the error page process to crash.
  GURL url_b2(embedded_test_server()->GetURL("b.com", "/title2.html"));
  TestNavigationManager manager(shell()->web_contents(), url_b2);
  shell()->LoadURL(url_b2);
  EXPECT_TRUE(manager.WaitForRequestStart());

  // Resume the navigation and wait for WillFailRequest(). After this point, we
  // will have picked the final RenderFrameHost & RenderProcessHost for the
  // failed navigation.
  manager.ResumeNavigation();
  installer.WaitForThrottleWillFail();

  // Kill the error page process. This will cause the navigation to `url_b2` to
  // return early in `NavigationRequest::ReadyToCommitNavigation()` and not
  // commit a new error page.
  RenderProcessHost* process_to_crash =
      manager.GetNavigationHandle()->GetRenderFrameHost()->GetProcess();
  ASSERT_TRUE(process_to_crash->IsInitializedAndNotDead());
  RenderProcessHostWatcher crash_observer(
      process_to_crash, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
  process_to_crash->Shutdown(0);
  crash_observer.Wait();
  ASSERT_FALSE(process_to_crash->IsInitializedAndNotDead());

  // Resume the navigation, which won't commit.
  if (!ShouldCreateNewHostForAllFrames()) {
    installer.navigation_throttle()->ResumeNavigation();
  }
  EXPECT_TRUE(manager.WaitForNavigationFinished());
  EXPECT_FALSE(WaitForLoadStop(shell()->web_contents()));

  // The tab stayed at `url_b1` as the `url_b2` navigation didn't commit.
  EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), url_b1);
}

namespace {

constexpr char kResponseBody[] = "response-body-contents";

// HTTP response template with adjustable header and body contents.
const char kResponseTemplate[] =
    "HTTP/1.1 200 OK\r\n"
    "%s"
    "\r\n"
    "%s";

// Test version of a NavigationThrottle that requests the response body.
class ResponseBodyNavigationThrottle : public NavigationThrottle {
 public:
  explicit ResponseBodyNavigationThrottle(NavigationHandle* handle)
      : NavigationThrottle(handle) {}
  ResponseBodyNavigationThrottle(const ResponseBodyNavigationThrottle&) =
      delete;
  ResponseBodyNavigationThrottle& operator=(
      const ResponseBodyNavigationThrottle&) = delete;
  ~ResponseBodyNavigationThrottle() override = default;

  NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
    // It is safe to use base::Unretained as the NavigationThrottle will not be
    // destroyed before the callback is called.
    navigation_handle()->GetResponseBody(
        base::BindOnce(&ResponseBodyNavigationThrottle::OnResponseBodyReady,
                       base::Unretained(this)));
    return NavigationThrottle::DEFER;
  }

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

  bool was_callback_called() const { return was_callback_called_; }

  const std::string& response_body() const { return response_body_; }

 private:
  void OnResponseBodyReady(const std::string& response_body) {
    was_callback_called_ = true;
    response_body_ = response_body;
    Resume();
  }

  bool was_callback_called_ = false;
  std::string response_body_;
};

}  // namespace

class NavigationRequestResponseBodyBrowserTest
    : public NavigationRequestBrowserTest {
 protected:
  void SetUpOnMainThread() override {
    host_resolver()->AddRule("*", "127.0.0.1");
  }
};

IN_PROC_BROWSER_TEST_F(NavigationRequestResponseBodyBrowserTest, Received) {
  net::test_server::ControllableHttpResponse response(embedded_test_server(),
                                                      "/target.html");
  ASSERT_TRUE(embedded_test_server()->Start());

  ResponseBodyNavigationThrottle* client_throttle = nullptr;

  // Set the client to register a ResponseBodyNavigationThrottle. Save a pointer
  // to this throttle in `client_throttle` on registration.
  content::ShellContentBrowserClient::Get()
      ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting(
          [&client_throttle](content::NavigationHandle* handle)
              -> std::vector<std::unique_ptr<content::NavigationThrottle>> {
            std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
            auto throttle =
                std::make_unique<ResponseBodyNavigationThrottle>(handle);
            client_throttle = throttle.get();
            throttles.push_back(std::move(throttle));
            return throttles;
          }));

  // Start navigating.
  GURL simple_url(embedded_test_server()->GetURL("/target.html"));
  TestNavigationManager manager(shell()->web_contents(), simple_url);
  shell()->LoadURL(simple_url);

  EXPECT_TRUE(manager.WaitForRequestStart());
  manager.ResumeNavigation();

  // Build the response with no headers and some body text.
  response.WaitForRequest();
  response.Send(base::StringPrintf(kResponseTemplate, "", kResponseBody));
  response.Done();
  ASSERT_TRUE(manager.WaitForResponse());
  ASSERT_NE(nullptr, client_throttle);
  EXPECT_TRUE(client_throttle->was_callback_called());
  EXPECT_EQ(kResponseBody, client_throttle->response_body());

  // Finish the navigation.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestResponseBodyBrowserTest,
                       ContentLengthZero) {
  net::test_server::ControllableHttpResponse response(embedded_test_server(),
                                                      "/target.html");
  ASSERT_TRUE(embedded_test_server()->Start());

  ResponseBodyNavigationThrottle* client_throttle = nullptr;

  // Set the client to register a ResponseBodyNavigationThrottle. Save a pointer
  // to this throttle in `client_throttle` on registration.
  content::ShellContentBrowserClient::Get()
      ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting(
          [&client_throttle](content::NavigationHandle* handle)
              -> std::vector<std::unique_ptr<content::NavigationThrottle>> {
            std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
            auto throttle =
                std::make_unique<ResponseBodyNavigationThrottle>(handle);
            client_throttle = throttle.get();
            throttles.push_back(std::move(throttle));
            return throttles;
          }));

  // Start navigating.
  GURL simple_url(embedded_test_server()->GetURL("/target.html"));
  TestNavigationManager manager(shell()->web_contents(), simple_url);
  shell()->LoadURL(simple_url);

  EXPECT_TRUE(manager.WaitForRequestStart());
  manager.ResumeNavigation();

  // Build the response with Content-Length: 0 and some body text.
  response.WaitForRequest();
  response.Send(base::StringPrintf(kResponseTemplate, "Content-Length: 0",
                                   kResponseBody));
  response.Done();
  ASSERT_TRUE(manager.WaitForResponse());
  ASSERT_NE(nullptr, client_throttle);
  EXPECT_TRUE(client_throttle->was_callback_called());
  // The received response body is empty due to the Content-Length value.
  EXPECT_EQ(std::string(), client_throttle->response_body());

  // Finish the navigation.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
}

IN_PROC_BROWSER_TEST_F(NavigationRequestResponseBodyBrowserTest,
                       BodyLargerThanDataPipeSize) {
  ASSERT_TRUE(embedded_test_server()->Start());

  ResponseBodyNavigationThrottle* client_throttle = nullptr;

  // Set the client to register a ResponseBodyNavigationThrottle. Save a pointer
  // to this throttle in `client_throttle` on registration.
  content::ShellContentBrowserClient::Get()
      ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting(
          [&client_throttle](content::NavigationHandle* handle)
              -> std::vector<std::unique_ptr<content::NavigationThrottle>> {
            std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
            auto throttle =
                std::make_unique<ResponseBodyNavigationThrottle>(handle);
            client_throttle = throttle.get();
            throttles.push_back(std::move(throttle));
            return throttles;
          }));

  // Start navigating to a page with a large body (>5 million characters).
  GURL simple_url(embedded_test_server()->GetURL("/long_response_body.html"));
  TestNavigationManager manager(shell()->web_contents(), simple_url);
  shell()->LoadURL(simple_url);

  ASSERT_TRUE(manager.WaitForResponse());
  ASSERT_NE(nullptr, client_throttle);
  EXPECT_TRUE(client_throttle->was_callback_called());
  // Ensure that the received response body contains text from the target page.
  EXPECT_NE(client_throttle->response_body().npos,
            client_throttle->response_body().find(
                "Test page with a long response body"));
  // The initial response body chunk may be smaller than the max data pipe size.
  EXPECT_LE(
      client_throttle->response_body().length(),
      network::features::GetDataPipeDefaultAllocationSize(
          network::features::DataPipeAllocationSize::kLargerSizeIfPossible));

  // Finish the navigation.
  ASSERT_TRUE(manager.WaitForNavigationFinished());
}

}  // namespace content
