chromium/content/browser/renderer_host/navigation_controller_impl_unittest.cc

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

#include "content/browser/renderer_host/navigation_controller_impl.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <memory>
#include <string>
#include <tuple>
#include <utility>

#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/browser_url_handler_impl.h"
#include "content/browser/renderer_host/frame_navigation_entry.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_entry_restore_context_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigator.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/common/frame.mojom.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/page_type.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/fake_local_frame.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/scoped_web_ui_controller_factory_registration.h"
#include "content/public/test/test_navigation_ui_data.h"
#include "content/public/test/test_utils.h"
#include "content/test/navigation_simulator_impl.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "skia/ext/platform_canvas.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/common/page/browsing_context_group_info.h"
#include "third_party/blink/public/common/page_state/page_state.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
#include "third_party/blink/public/mojom/frame/remote_frame.mojom.h"
#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"

Time;

namespace {

base::Time InMicrosecondsSinceEpoch(int64_t us) {}

// Creates an image with a 1x1 SkBitmap of the specified |color|.
gfx::Image CreateImage(SkColor color) {}

// Returns true if images |a| and |b| have the same pixel data.
bool DoImagesMatch(const gfx::Image& a, const gfx::Image& b) {}

class MockPageBroadcast : public blink::mojom::PageBroadcast {};

}  // namespace

namespace content {

// TimeSmoother tests ----------------------------------------------------------

// With no duplicates, GetSmoothedTime should be the identity
// function.
TEST(TimeSmoother, Basic) {}

// With a single duplicate and timestamps thereafter increasing by one
// microsecond, the smoothed time should always be one behind.
TEST(TimeSmoother, SingleDuplicate) {}

// With k duplicates and timestamps thereafter increasing by one
// microsecond, the smoothed time should always be k behind.
TEST(TimeSmoother, ManyDuplicates) {}

// If the clock jumps far back enough after a run of duplicates, it
// should immediately jump to that value.
TEST(TimeSmoother, ClockBackwardsJump) {}

// NavigationControllerTest ----------------------------------------------------

class NavigationControllerTest : public RenderViewHostImplTestHarness,
                                 public WebContentsObserver {};

class TestWebContentsDelegate : public WebContentsDelegate {};

// Observer that records the LoadCommittedDetails from the most recent commit.
class LoadCommittedDetailsObserver : public WebContentsObserver {};

// "Legacy" class that was used to run NavigationControllerTest with the now
// defunct --enable-browser-side-navigation flag.
// TODO(clamy): Make those regular NavigationControllerTests.
class NavigationControllerTestWithBrowserSideNavigation
    : public NavigationControllerTest {};

// -----------------------------------------------------------------------------

TEST_F(NavigationControllerTest, Defaults) {}

TEST_F(NavigationControllerTest, GoToOffset) {}

TEST_F(NavigationControllerTest, LoadURL) {}

namespace {

base::Time GetFixedTime(base::Time time) {}

}  // namespace

TEST_F(NavigationControllerTest, LoadURLSameTime) {}

void CheckNavigationEntryMatchLoadParams(
    const NavigationController::LoadURLParams& load_params,
    NavigationEntryImpl* entry) {}

TEST_F(NavigationControllerTest, LoadURLWithParams) {}

TEST_F(NavigationControllerTest, LoadURLWithParams_Reload) {}

TEST_F(NavigationControllerTest, LoadURLWithExtraParams_Data) {}

#if BUILDFLAG(IS_ANDROID)
TEST_F(NavigationControllerTest, LoadURLWithExtraParams_Data_Android) {
  NavigationControllerImpl& controller = controller_impl();
  GURL url("data:,");

  auto navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(url, contents());
  NavigationController::LoadURLParams load_url_params(url);
  load_url_params.load_type = NavigationController::LOAD_TYPE_DATA;
  load_url_params.base_url_for_data_url = GURL("http://foo");
  load_url_params.virtual_url_for_special_cases = GURL(url::kAboutBlankURL);
  load_url_params.data_url_as_string =
      base::MakeRefCounted<base::RefCountedString>(std::string("data:,data"));
  load_url_params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
  navigation->SetLoadURLParams(&load_url_params);
  navigation->Start();

  NavigationEntryImpl* entry = controller.GetPendingEntry();
  CheckNavigationEntryMatchLoadParams(load_url_params, entry);
}

TEST_F(NavigationControllerTest, LoadURLWithExtraParams_Pdf_Android) {
  NavigationControllerImpl& controller = controller_impl();
  GURL url("chrome-native://pdf/link?url=https%3A%2F%2Ffoo");

  auto navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(url, contents());
  NavigationController::LoadURLParams load_url_params(url);
  load_url_params.load_type = NavigationController::LOAD_TYPE_PDF_ANDROID;
  load_url_params.virtual_url_for_special_cases = GURL("https://foo");
  load_url_params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
  navigation->SetLoadURLParams(&load_url_params);
  navigation->Start();

  NavigationEntryImpl* entry = controller.GetPendingEntry();
  CheckNavigationEntryMatchLoadParams(load_url_params, entry);
}
#endif

TEST_F(NavigationControllerTest, KeepReloadTypeWhenCancelRepost) {}

TEST_F(NavigationControllerTest, LoadURLWithExtraParams_HttpPost) {}

// Tests what happens when the same page is loaded again.  Should not create a
// new session history entry. This is what happens when you press enter in the
// URL bar to reload: a pending entry is created and then it is discarded when
// the load commits (because WebCore didn't actually make a new entry).
TEST_F(NavigationControllerTest, LoadURL_SamePage) {}

// Tests loading a URL but discarding it before the load commits.
TEST_F(NavigationControllerTest, LoadURL_Discarded) {}

// Tests navigations that come in unrequested. This happens when the user
// navigates from the web page, and here we test that there is no pending entry.
TEST_F(NavigationControllerTest, LoadURL_NoPending) {}

// Tests navigating to a new URL when there is a new pending navigation that is
// not the one that just loaded. This will happen if the user types in a URL to
// somewhere slow, and then navigates the current page before the typed URL
// commits.
TEST_F(NavigationControllerTest, LoadURL_NewPending) {}

// Tests navigating to a new URL when there is a pending back/forward
// navigation. This will happen if the user hits back, but before that commits,
// they navigate somewhere new.
TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {}

// Tests navigating to a new URL when there is a pending back/forward
// navigation to a cross-process, privileged URL. This will happen if the user
// hits back, but before that commits, they navigate somewhere new.
TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {}

// Tests navigating to an existing URL when there is a pending new navigation.
// This will happen if the user enters a URL, but before that commits, the
// current page fires history.back().
TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {}

// Verify that a direct commit message from the renderer properly cancels a
// pending new navigation. This will happen if the user enters a URL, but
// before that commits, the current blank page reloads.
// Original bug: http://crbug.com/77507.
TEST_F(NavigationControllerTest, LoadURL_IgnorePreemptsPending) {}

// Tests that the pending entry state is correct after an abort.
// We do not want to clear the pending entry, so that the user doesn't
// lose a typed URL.  (See http://crbug.com/9682.)
TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) {}

// Tests that the pending URL is not visible during a renderer-initiated
// redirect and abort.  See http://crbug.com/83031.
TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {}

TEST_F(NavigationControllerTest, Reload) {}

// Tests what happens when a reload navigation produces a new page.
TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {}

// This test ensures that when a guest renderer reloads, the reload goes through
// without ending up in the "we have a wrong process for the URL" branch in
// NavigationControllerImpl::ReloadInternal.
TEST_F(NavigationControllerTest, ReloadWithGuest) {}

TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {}

// Test that certain non-persisted NavigationEntryImpl values get reset after
// commit.
TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {}

// Test that Redirects are preserved after a commit.
TEST_F(NavigationControllerTest, RedirectsAreNotResetByCommit) {}

// Tests that webkit preferences are updated when user agent override changes.
TEST_F(NavigationControllerTest, GoBackWithUserAgentOverrideChange) {}

// Tests what happens when we navigate back successfully
TEST_F(NavigationControllerTest, Back) {}

// Tests what happens when a back navigation produces a new page.
TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {}

// Receives a back message when there is a new pending navigation entry.
TEST_F(NavigationControllerTest, Back_NewPending) {}

// Tests what happens when we navigate forward successfully.
TEST_F(NavigationControllerTest, Forward) {}

// Tests what happens when a forward navigation produces a new page.
TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {}

// A redirect right off the bat should be a NEW_ENTRY.
TEST_F(NavigationControllerTest, ImmediateRedirect) {}

// If something is pumping the event loop in the browser process and is loading
// pages rapidly one after the other, there can be a race with two closely-
// spaced load requests. Once the first load request is sent, will the renderer
// be fast enough to get the load committed, send a DidCommitProvisionalLoad
// IPC, and have the browser process handle that IPC before the caller makes
// another load request, replacing the pending entry of the first request?
//
// This test is about what happens in such a race when that pending entry
// replacement happens. If it happens, and the first load had the same URL as
// the page before it, we must make sure that the replacement of the pending
// entry correctly results in an EXISTING_ENTRY classification.
//
// (This is a unit test rather than a browser test because it's not currently
// possible to force this sequence of events with a browser test.)
TEST_F(NavigationControllerTest,
       NavigationTypeClassification_ExistingEntryRace) {}

// Tests navigation via link click within a subframe. A new navigation entry
// should be created.
TEST_F(NavigationControllerTest, NewSubframe) {}

// Auto subframes are ones the page loads automatically like ads. They should
// not create new navigation entries.
// TODO(creis): Test updating entries for history auto subframe navigations.
TEST_F(NavigationControllerTest, AutoSubframe) {}

// Tests navigation and then going back to a subframe navigation.
TEST_F(NavigationControllerTest, BackSubframe) {}

TEST_F(NavigationControllerTest, LinkClick) {}

TEST_F(NavigationControllerTest, SameDocument) {}

TEST_F(NavigationControllerTest, SameDocument_Replace) {}

TEST_F(NavigationControllerTest, PushStateWithOnlyInitialEntry) {}

// Tests that we limit the number of navigation entries created correctly.
TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {}

// Tests that we can do a restore and navigate to the restored entries and
// everything is updated properly. This can be tricky since there is no
// SiteInstance for the entries created initially.
TEST_F(NavigationControllerTest, RestoreNavigate) {}

// Tests that we can still navigate to a restored entry after a different
// navigation fails and clears the pending entry.  http://crbug.com/90085
TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {}

TEST_F(NavigationControllerTest, RemoveEntry) {}

TEST_F(NavigationControllerTest, RemoveEntryWithPending) {}

// Ensure that renderer initiated pending entries get replaced, so that we
// don't show a stale virtual URL when a navigation commits.
// See http://crbug.com/266922.
TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {}

// Tests that the URLs for renderer-initiated navigations are not displayed to
// the user until the navigation commits, to prevent URL spoof attacks.
// See http://crbug.com/99016.
TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {}

// Tests that the URLs for renderer-initiated navigations in new tabs are
// displayed to the user before commit, as long as the initial about:blank
// page has not been modified.  If so, we must revert to showing about:blank.
// See http://crbug.com/9682.
TEST_F(NavigationControllerTest, ShowRendererURLInNewTabUntilModified) {}

// Tests that the URLs for browser-initiated navigations in new tabs are
// displayed to the user even after they fail, as long as the initial
// about:blank page has not been modified.  If so, we must revert to showing
// about:blank. See http://crbug.com/355537.
TEST_F(NavigationControllerTest, ShowBrowserURLAfterFailUntilModified) {}

// Tests that the URLs for renderer-initiated navigations in new tabs are
// displayed to the user even after they fail, as long as the initial
// about:blank page has not been modified.  If so, we must revert to showing
// about:blank. See http://crbug.com/355537.
TEST_F(NavigationControllerTest, ShowRendererURLAfterFailUntilModified) {}

// Tests that the URLs for renderer-initiated navigations in new tabs are
// displayed to the user after they got canceled, as long as the initial
// about:blank page has not been modified. If so, we must revert to showing
// about:blank. See http://crbug.com/355537.
TEST_F(NavigationControllerTest, ShowRendererURLAfterCancelUntilModified) {}

TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {}

// This test verifies that a subframe navigation that would qualify as
// same-document within the main frame, given its URL, has no impact on the
// main frame.
// Original bug: http://crbug.com/5585
TEST_F(NavigationControllerTest, SameSubframe) {}

// Make sure that on cloning a WebContentsImpl and going back needs_reload is
// false.
TEST_F(NavigationControllerTest, CloneAndGoBack) {}

// Make sure that reloading a cloned tab doesn't change its pending entry index.
// See http://crbug.com/234491.
TEST_F(NavigationControllerTest, CloneAndReload) {}

// Test requesting and triggering a lazy reload.
TEST_F(NavigationControllerTest, LazyReload) {}

// Test requesting and triggering a lazy reload when there's only the initial
// entry.
TEST_F(NavigationControllerTest, LazyReloadWithOnlyInitialEntry) {}

// Test requesting and triggering a lazy reload when there's only the initial
// entry and a pending entry.
TEST_F(NavigationControllerTest, LazyReloadWithOnlyInitialAndPendingEntry) {}

// Verify that a subframe navigation happening during an ongoing main frame
// navigation does not change the displayed URL.
// Original bug: http://crbug.com/43967
TEST_F(NavigationControllerTest, SubframeWhilePending) {}

// Test CopyStateFrom with 2 urls, the first selected and nothing in the target.
TEST_F(NavigationControllerTest, CopyStateFrom) {}

// Tests DeleteNavigationEntries.
TEST_F(NavigationControllerTest, DeleteNavigationEntries) {}

// Tests that navigations initiated from the page (with the history object)
// work as expected, creating pending entries.
TEST_F(NavigationControllerTest, HistoryNavigate) {}

// Test call to PruneAllButLastCommitted for the only entry.
TEST_F(NavigationControllerTest, PruneAllButLastCommittedForSingle) {}

// Test call to PruneAllButLastCommitted for first entry.
TEST_F(NavigationControllerTest, PruneAllButLastCommittedForFirst) {}

// Test call to PruneAllButLastCommitted for intermediate entry.
TEST_F(NavigationControllerTest, PruneAllButLastCommittedForIntermediate) {}

// Test call to PruneAllButLastCommitted for a pending entry that is not yet in
// the list of entries.
TEST_F(NavigationControllerTest, PruneAllButLastCommittedForPendingNotInList) {}

// Test to ensure that when we do a history navigation back to the current
// committed page (e.g., going forward to a slow-loading page, then pressing
// the back button), we just stop the navigation to prevent the throbber from
// running continuously. Otherwise, the RenderViewHost forces the throbber to
// start, but WebKit essentially ignores the navigation and never sends a
// message to stop the throbber.
TEST_F(NavigationControllerTest, StopOnHistoryNavigationToCurrentPage) {}

TEST_F(NavigationControllerTest, IsInitialNavigation) {}

// Check that the favicon is not reused across a client redirect.
// (crbug.com/28515)
TEST_F(NavigationControllerTest, ClearFaviconOnRedirect) {}

// Check that the favicon is not cleared for NavigationEntries which were
// previously navigated to.
TEST_F(NavigationControllerTest, BackNavigationDoesNotClearFavicon) {}

TEST_F(NavigationControllerTest, PushStateUpdatesTitleAndFavicon) {}

// Test that the navigation controller clears its session history when a
// navigation commits with the clear history list flag set.
TEST_F(NavigationControllerTest, ClearHistoryList) {}

// Tests that if a stale navigation comes back from the renderer, it is properly
// resurrected.
TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {}

// Tests that successive navigations with intermittent duplicate navigations
// are correctly marked as reload in the navigation controller.
// We test the cases where in a navigation is pending/committed before the new
// navigation is initiated.
// http://crbug.com/664319
TEST_F(NavigationControllerTest, MultipleNavigationsAndReload) {}

// Tests that NavigationUIData has been passed to the NavigationHandle.
TEST_F(NavigationControllerTest, MainFrameNavigationUIData) {}

// Tests that ReloadType has been passed to the NavigationHandle.
TEST_F(NavigationControllerTest, MainFrameNavigationReloadType) {}

// Tests calling LoadURLParams with NavigationUIData and for a sub frame.
TEST_F(NavigationControllerTest, SubFrameNavigationUIData) {}

bool SrcDocRewriter(GURL* url, BrowserContext* browser_context) {}

// Tests that receiving a request to navigate a subframe will not rewrite the
// subframe URL. Regression test for https://crbug.com/895065.
TEST_F(NavigationControllerTest, NoURLRewriteForSubframes) {}

// Test that if an empty WebContents is navigated via frame proxy with
// replacement, the NavigationRequest does specifies replacement, to replace the
// initial entry.
TEST_F(NavigationControllerTest,
       NavigateFromFrameProxyWithReplacementWithOnlyInitialEntry) {}

// Tests that calling RemoveForwareEntries() clears all forward entries
// including non-committed entries.
TEST_F(NavigationControllerTest, PruneForwardEntries) {}

// Make sure that cloning a WebContentsImpl and clearing forward entries
// before the first commit doesn't clear all entries.
TEST_F(NavigationControllerTest, PruneForwardEntriesAfterClone) {}

TEST_F(NavigationControllerTest,
       NavigateToNavigationApiKey_DifferentSiteInstance) {}

TEST_F(NavigationControllerTest, NavigateToNavigationApiKey_KeyForWrongFrame) {}

class FakeLocalFrameWithDisposedEntries : public content::FakeLocalFrame {};

TEST_F(NavigationControllerTest, NavigationApiDisposedEntries) {}

// Once instantiated, will insert `mock_page_broadcast` as the PageBroadcast on
// a newly created RenderViewHost. This is important for listening for the
// update to a RenderViewHost which was created for a proxy, as it swaps to a
// local frame in a different browsing context group. Note that this this will
// only work once, as MockPageBroadcast does not support multiple bindings.
class PageBroadcastMockInserter : public WebContentsObserver {};

// Test that navigations across browsing context groups trigger a page broadcast
// with up to date browsing context group information.
TEST_F(NavigationControllerTest, BrowsingContextGroupUpdate) {}

class NavigationControllerFencedFrameTest : public NavigationControllerTest {};

// Tests that receiving a request to navigate a fenced frame will not rewrite
// the fenced frame URL.
TEST_F(NavigationControllerFencedFrameTest, NoURLRewriteForFencedFrames) {}

}  // namespace content